]> begriffs open source - freertos/blob - portable/GCC/ARM_CM33/non_secure/port.c
Update SMP branch readme for port migration (#999)
[freertos] / portable / GCC / ARM_CM33 / non_secure / port.c
1 /*
2  * FreeRTOS SMP Kernel V202110.00
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * https://www.FreeRTOS.org
23  * https://github.com/FreeRTOS
24  *
25  */
26
27 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
28  * all the API functions to use the MPU wrappers. That should only be done when
29  * task.h is included from an application file. */
30 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
31
32 /* Scheduler includes. */
33 #include "FreeRTOS.h"
34 #include "task.h"
35
36 /* MPU wrappers includes. */
37 #include "mpu_wrappers.h"
38
39 /* Portasm includes. */
40 #include "portasm.h"
41
42 #if ( configENABLE_TRUSTZONE == 1 )
43     /* Secure components includes. */
44     #include "secure_context.h"
45     #include "secure_init.h"
46 #endif /* configENABLE_TRUSTZONE */
47
48 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
49
50 /**
51  * The FreeRTOS Cortex M33 port can be configured to run on the Secure Side only
52  * i.e. the processor boots as secure and never jumps to the non-secure side.
53  * The Trust Zone support in the port must be disabled in order to run FreeRTOS
54  * on the secure side. The following are the valid configuration seetings:
55  *
56  * 1. Run FreeRTOS on the Secure Side:
57  *    configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0
58  *
59  * 2. Run FreeRTOS on the Non-Secure Side with Secure Side function call support:
60  *    configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1
61  *
62  * 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support:
63  *    configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0
64  */
65 #if ( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) )
66     #error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side.
67 #endif
68 /*-----------------------------------------------------------*/
69
70 /**
71  * @brief Constants required to manipulate the NVIC.
72  */
73 #define portNVIC_SYSTICK_CTRL_REG             ( *( ( volatile uint32_t * ) 0xe000e010 ) )
74 #define portNVIC_SYSTICK_LOAD_REG             ( *( ( volatile uint32_t * ) 0xe000e014 ) )
75 #define portNVIC_SYSTICK_CURRENT_VALUE_REG    ( *( ( volatile uint32_t * ) 0xe000e018 ) )
76 #define portNVIC_SHPR3_REG                    ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
77 #define portNVIC_SYSTICK_ENABLE_BIT           ( 1UL << 0UL )
78 #define portNVIC_SYSTICK_INT_BIT              ( 1UL << 1UL )
79 #define portNVIC_SYSTICK_COUNT_FLAG_BIT       ( 1UL << 16UL )
80 #define portMIN_INTERRUPT_PRIORITY            ( 255UL )
81 #define portNVIC_PENDSV_PRI                   ( portMIN_INTERRUPT_PRIORITY << 16UL )
82 #define portNVIC_SYSTICK_PRI                  ( portMIN_INTERRUPT_PRIORITY << 24UL )
83 #ifndef configSYSTICK_CLOCK_HZ
84     #define configSYSTICK_CLOCK_HZ            configCPU_CLOCK_HZ
85     /* Ensure the SysTick is clocked at the same frequency as the core. */
86     #define portNVIC_SYSTICK_CLK_BIT          ( 1UL << 2UL )
87 #else
88
89 /* The way the SysTick is clocked is not modified in case it is not the
90  * same a the core. */
91     #define portNVIC_SYSTICK_CLK_BIT    ( 0 )
92 #endif
93 /*-----------------------------------------------------------*/
94
95 /**
96  * @brief Constants required to manipulate the SCB.
97  */
98 #define portSCB_SYS_HANDLER_CTRL_STATE_REG    ( *( volatile uint32_t * ) 0xe000ed24 )
99 #define portSCB_MEM_FAULT_ENABLE_BIT          ( 1UL << 16UL )
100 /*-----------------------------------------------------------*/
101
102 /**
103  * @brief Constants required to manipulate the FPU.
104  */
105 #define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
106 #define portCPACR_CP10_VALUE    ( 3UL )
107 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
108 #define portCPACR_CP10_POS      ( 20UL )
109 #define portCPACR_CP11_POS      ( 22UL )
110
111 #define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
112 #define portFPCCR_ASPEN_POS     ( 31UL )
113 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
114 #define portFPCCR_LSPEN_POS     ( 30UL )
115 #define portFPCCR_LSPEN_MASK    ( 1UL << portFPCCR_LSPEN_POS )
116 /*-----------------------------------------------------------*/
117
118 /**
119  * @brief Constants required to manipulate the MPU.
120  */
121 #define portMPU_TYPE_REG                      ( *( ( volatile uint32_t * ) 0xe000ed90 ) )
122 #define portMPU_CTRL_REG                      ( *( ( volatile uint32_t * ) 0xe000ed94 ) )
123 #define portMPU_RNR_REG                       ( *( ( volatile uint32_t * ) 0xe000ed98 ) )
124
125 #define portMPU_RBAR_REG                      ( *( ( volatile uint32_t * ) 0xe000ed9c ) )
126 #define portMPU_RLAR_REG                      ( *( ( volatile uint32_t * ) 0xe000eda0 ) )
127
128 #define portMPU_RBAR_A1_REG                   ( *( ( volatile uint32_t * ) 0xe000eda4 ) )
129 #define portMPU_RLAR_A1_REG                   ( *( ( volatile uint32_t * ) 0xe000eda8 ) )
130
131 #define portMPU_RBAR_A2_REG                   ( *( ( volatile uint32_t * ) 0xe000edac ) )
132 #define portMPU_RLAR_A2_REG                   ( *( ( volatile uint32_t * ) 0xe000edb0 ) )
133
134 #define portMPU_RBAR_A3_REG                   ( *( ( volatile uint32_t * ) 0xe000edb4 ) )
135 #define portMPU_RLAR_A3_REG                   ( *( ( volatile uint32_t * ) 0xe000edb8 ) )
136
137 #define portMPU_MAIR0_REG                     ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
138 #define portMPU_MAIR1_REG                     ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
139
140 #define portMPU_RBAR_ADDRESS_MASK             ( 0xffffffe0 ) /* Must be 32-byte aligned. */
141 #define portMPU_RLAR_ADDRESS_MASK             ( 0xffffffe0 ) /* Must be 32-byte aligned. */
142
143 #define portMPU_MAIR_ATTR0_POS                ( 0UL )
144 #define portMPU_MAIR_ATTR0_MASK               ( 0x000000ff )
145
146 #define portMPU_MAIR_ATTR1_POS                ( 8UL )
147 #define portMPU_MAIR_ATTR1_MASK               ( 0x0000ff00 )
148
149 #define portMPU_MAIR_ATTR2_POS                ( 16UL )
150 #define portMPU_MAIR_ATTR2_MASK               ( 0x00ff0000 )
151
152 #define portMPU_MAIR_ATTR3_POS                ( 24UL )
153 #define portMPU_MAIR_ATTR3_MASK               ( 0xff000000 )
154
155 #define portMPU_MAIR_ATTR4_POS                ( 0UL )
156 #define portMPU_MAIR_ATTR4_MASK               ( 0x000000ff )
157
158 #define portMPU_MAIR_ATTR5_POS                ( 8UL )
159 #define portMPU_MAIR_ATTR5_MASK               ( 0x0000ff00 )
160
161 #define portMPU_MAIR_ATTR6_POS                ( 16UL )
162 #define portMPU_MAIR_ATTR6_MASK               ( 0x00ff0000 )
163
164 #define portMPU_MAIR_ATTR7_POS                ( 24UL )
165 #define portMPU_MAIR_ATTR7_MASK               ( 0xff000000 )
166
167 #define portMPU_RLAR_ATTR_INDEX0              ( 0UL << 1UL )
168 #define portMPU_RLAR_ATTR_INDEX1              ( 1UL << 1UL )
169 #define portMPU_RLAR_ATTR_INDEX2              ( 2UL << 1UL )
170 #define portMPU_RLAR_ATTR_INDEX3              ( 3UL << 1UL )
171 #define portMPU_RLAR_ATTR_INDEX4              ( 4UL << 1UL )
172 #define portMPU_RLAR_ATTR_INDEX5              ( 5UL << 1UL )
173 #define portMPU_RLAR_ATTR_INDEX6              ( 6UL << 1UL )
174 #define portMPU_RLAR_ATTR_INDEX7              ( 7UL << 1UL )
175
176 #define portMPU_RLAR_REGION_ENABLE            ( 1UL )
177
178 /* Enable privileged access to unmapped region. */
179 #define portMPU_PRIV_BACKGROUND_ENABLE_BIT    ( 1UL << 2UL )
180
181 /* Enable MPU. */
182 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
183
184 /* Expected value of the portMPU_TYPE register. */
185 #define portEXPECTED_MPU_TYPE_VALUE           ( 8UL << 8UL ) /* 8 regions, unified. */
186 /*-----------------------------------------------------------*/
187
188 /**
189  * @brief The maximum 24-bit number.
190  *
191  * It is needed because the systick is a 24-bit counter.
192  */
193 #define portMAX_24_BIT_NUMBER       ( 0xffffffUL )
194
195 /**
196  * @brief A fiddle factor to estimate the number of SysTick counts that would
197  * have occurred while the SysTick counter is stopped during tickless idle
198  * calculations.
199  */
200 #define portMISSED_COUNTS_FACTOR    ( 45UL )
201 /*-----------------------------------------------------------*/
202
203 /**
204  * @brief Constants required to set up the initial stack.
205  */
206 #define portINITIAL_XPSR    ( 0x01000000 )
207
208 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
209
210 /**
211  * @brief Initial EXC_RETURN value.
212  *
213  *     FF         FF         FF         FD
214  * 1111 1111  1111 1111  1111 1111  1111 1101
215  *
216  * Bit[6] - 1 --> The exception was taken from the Secure state.
217  * Bit[5] - 1 --> Do not skip stacking of additional state context.
218  * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
219  * Bit[3] - 1 --> Return to the Thread mode.
220  * Bit[2] - 1 --> Restore registers from the process stack.
221  * Bit[1] - 0 --> Reserved, 0.
222  * Bit[0] - 1 --> The exception was taken to the Secure state.
223  */
224     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
225 #else
226
227 /**
228  * @brief Initial EXC_RETURN value.
229  *
230  *     FF         FF         FF         BC
231  * 1111 1111  1111 1111  1111 1111  1011 1100
232  *
233  * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
234  * Bit[5] - 1 --> Do not skip stacking of additional state context.
235  * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
236  * Bit[3] - 1 --> Return to the Thread mode.
237  * Bit[2] - 1 --> Restore registers from the process stack.
238  * Bit[1] - 0 --> Reserved, 0.
239  * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
240  */
241     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
242 #endif /* configRUN_FREERTOS_SECURE_ONLY */
243
244 /**
245  * @brief CONTROL register privileged bit mask.
246  *
247  * Bit[0] in CONTROL register tells the privilege:
248  *  Bit[0] = 0 ==> The task is privileged.
249  *  Bit[0] = 1 ==> The task is not privileged.
250  */
251 #define portCONTROL_PRIVILEGED_MASK         ( 1UL << 0UL )
252
253 /**
254  * @brief Initial CONTROL register values.
255  */
256 #define portINITIAL_CONTROL_UNPRIVILEGED    ( 0x3 )
257 #define portINITIAL_CONTROL_PRIVILEGED      ( 0x2 )
258
259 /**
260  * @brief Let the user override the pre-loading of the initial LR with the
261  * address of prvTaskExitError() in case it messes up unwinding of the stack
262  * in the debugger.
263  */
264 #ifdef configTASK_RETURN_ADDRESS
265     #define portTASK_RETURN_ADDRESS    configTASK_RETURN_ADDRESS
266 #else
267     #define portTASK_RETURN_ADDRESS    prvTaskExitError
268 #endif
269
270 /**
271  * @brief If portPRELOAD_REGISTERS then registers will be given an initial value
272  * when a task is created. This helps in debugging at the cost of code size.
273  */
274 #define portPRELOAD_REGISTERS    1
275
276 /**
277  * @brief A task is created without a secure context, and must call
278  * portALLOCATE_SECURE_CONTEXT() to give itself a secure context before it makes
279  * any secure calls.
280  */
281 #define portNO_SECURE_CONTEXT    0
282 /*-----------------------------------------------------------*/
283
284 /**
285  * @brief Used to catch tasks that attempt to return from their implementing
286  * function.
287  */
288 static void prvTaskExitError( void );
289
290 #if ( configENABLE_MPU == 1 )
291
292 /**
293  * @brief Setup the Memory Protection Unit (MPU).
294  */
295     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
296 #endif /* configENABLE_MPU */
297
298 #if ( configENABLE_FPU == 1 )
299
300 /**
301  * @brief Setup the Floating Point Unit (FPU).
302  */
303     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
304 #endif /* configENABLE_FPU */
305
306 /**
307  * @brief Setup the timer to generate the tick interrupts.
308  *
309  * The implementation in this file is weak to allow application writers to
310  * change the timer used to generate the tick interrupt.
311  */
312 void vPortSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION;
313
314 /**
315  * @brief Checks whether the current execution context is interrupt.
316  *
317  * @return pdTRUE if the current execution context is interrupt, pdFALSE
318  * otherwise.
319  */
320 BaseType_t xPortIsInsideInterrupt( void );
321
322 /**
323  * @brief Yield the processor.
324  */
325 void vPortYield( void ) PRIVILEGED_FUNCTION;
326
327 /**
328  * @brief Enter critical section.
329  */
330 void vPortEnterCritical( void ) PRIVILEGED_FUNCTION;
331
332 /**
333  * @brief Exit from critical section.
334  */
335 void vPortExitCritical( void ) PRIVILEGED_FUNCTION;
336
337 /**
338  * @brief SysTick handler.
339  */
340 void SysTick_Handler( void ) PRIVILEGED_FUNCTION;
341
342 /**
343  * @brief C part of SVC handler.
344  */
345 portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIVILEGED_FUNCTION;
346 /*-----------------------------------------------------------*/
347
348 /**
349  * @brief Each task maintains its own interrupt status in the critical nesting
350  * variable.
351  */
352 PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
353
354 #if ( configENABLE_TRUSTZONE == 1 )
355
356 /**
357  * @brief Saved as part of the task context to indicate which context the
358  * task is using on the secure side.
359  */
360     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
361 #endif /* configENABLE_TRUSTZONE */
362
363 #if ( configUSE_TICKLESS_IDLE == 1 )
364
365 /**
366  * @brief The number of SysTick increments that make up one tick period.
367  */
368     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
369
370 /**
371  * @brief The maximum number of tick periods that can be suppressed is
372  * limited by the 24 bit resolution of the SysTick timer.
373  */
374     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
375
376 /**
377  * @brief Compensate for the CPU cycles that pass while the SysTick is
378  * stopped (low power functionality only).
379  */
380     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
381 #endif /* configUSE_TICKLESS_IDLE */
382 /*-----------------------------------------------------------*/
383
384 #if ( configUSE_TICKLESS_IDLE == 1 )
385     __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
386     {
387         uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
388         TickType_t xModifiableIdleTime;
389
390         /* Make sure the SysTick reload value does not overflow the counter. */
391         if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
392         {
393             xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
394         }
395
396         /* Stop the SysTick momentarily. The time the SysTick is stopped for is
397          * accounted for as best it can be, but using the tickless mode will
398          * inevitably result in some tiny drift of the time maintained by the
399          * kernel with respect to calendar time. */
400         portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
401
402         /* Calculate the reload value required to wait xExpectedIdleTime
403          * tick periods. -1 is used because this code will execute part way
404          * through one of the tick periods. */
405         ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
406
407         if( ulReloadValue > ulStoppedTimerCompensation )
408         {
409             ulReloadValue -= ulStoppedTimerCompensation;
410         }
411
412         /* Enter a critical section but don't use the taskENTER_CRITICAL()
413          * method as that will mask interrupts that should exit sleep mode. */
414         __asm volatile ( "cpsid i" ::: "memory" );
415         __asm volatile ( "dsb" );
416         __asm volatile ( "isb" );
417
418         /* If a context switch is pending or a task is waiting for the scheduler
419          * to be un-suspended then abandon the low power entry. */
420         if( eTaskConfirmSleepModeStatus() == eAbortSleep )
421         {
422             /* Restart from whatever is left in the count register to complete
423              * this tick period. */
424             portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
425
426             /* Restart SysTick. */
427             portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
428
429             /* Reset the reload register to the value required for normal tick
430              * periods. */
431             portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
432
433             /* Re-enable interrupts - see comments above the cpsid instruction()
434              * above. */
435             __asm volatile ( "cpsie i" ::: "memory" );
436         }
437         else
438         {
439             /* Set the new reload value. */
440             portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
441
442             /* Clear the SysTick count flag and set the count value back to
443              * zero. */
444             portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
445
446             /* Restart SysTick. */
447             portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
448
449             /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
450              * set its parameter to 0 to indicate that its implementation
451              * contains its own wait for interrupt or wait for event
452              * instruction, and so wfi should not be executed again. However,
453              * the original expected idle time variable must remain unmodified,
454              * so a copy is taken. */
455             xModifiableIdleTime = xExpectedIdleTime;
456             configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
457
458             if( xModifiableIdleTime > 0 )
459             {
460                 __asm volatile ( "dsb" ::: "memory" );
461                 __asm volatile ( "wfi" );
462                 __asm volatile ( "isb" );
463             }
464
465             configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
466
467             /* Re-enable interrupts to allow the interrupt that brought the MCU
468              * out of sleep mode to execute immediately. See comments above
469              * the cpsid instruction above. */
470             __asm volatile ( "cpsie i" ::: "memory" );
471             __asm volatile ( "dsb" );
472             __asm volatile ( "isb" );
473
474             /* Disable interrupts again because the clock is about to be stopped
475              * and interrupts that execute while the clock is stopped will
476              * increase any slippage between the time maintained by the RTOS and
477              * calendar time. */
478             __asm volatile ( "cpsid i" ::: "memory" );
479             __asm volatile ( "dsb" );
480             __asm volatile ( "isb" );
481
482             /* Disable the SysTick clock without reading the
483              * portNVIC_SYSTICK_CTRL_REG register to ensure the
484              * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set.
485              * Again, the time the SysTick is stopped for is accounted for as
486              * best it can be, but using the tickless mode will inevitably
487              * result in some tiny drift of the time maintained by the kernel
488              * with respect to calendar time*/
489             portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT );
490
491             /* Determine if the SysTick clock has already counted to zero and
492              * been set back to the current reload value (the reload back being
493              * correct for the entire expected idle time) or if the SysTick is
494              * yet to count to zero (in which case an interrupt other than the
495              * SysTick must have brought the system out of sleep mode). */
496             if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
497             {
498                 uint32_t ulCalculatedLoadValue;
499
500                 /* The tick interrupt is already pending, and the SysTick count
501                  * reloaded with ulReloadValue.  Reset the
502                  * portNVIC_SYSTICK_LOAD_REG with whatever remains of this tick
503                  * period. */
504                 ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
505
506                 /* Don't allow a tiny value, or values that have somehow
507                  * underflowed because the post sleep hook did something
508                  * that took too long. */
509                 if( ( ulCalculatedLoadValue < ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
510                 {
511                     ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
512                 }
513
514                 portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
515
516                 /* As the pending tick will be processed as soon as this
517                  * function exits, the tick value maintained by the tick is
518                  * stepped forward by one less than the time spent waiting. */
519                 ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
520             }
521             else
522             {
523                 /* Something other than the tick interrupt ended the sleep.
524                  * Work out how long the sleep lasted rounded to complete tick
525                  * periods (not the ulReload value which accounted for part
526                  * ticks). */
527                 ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - portNVIC_SYSTICK_CURRENT_VALUE_REG;
528
529                 /* How many complete tick periods passed while the processor
530                  * was waiting? */
531                 ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
532
533                 /* The reload value is set to whatever fraction of a single tick
534                  * period remains. */
535                 portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
536             }
537
538             /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG
539              * again, then set portNVIC_SYSTICK_LOAD_REG back to its standard
540              * value. */
541             portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
542             portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
543             vTaskStepTick( ulCompleteTickPeriods );
544             portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
545
546             /* Exit with interrupts enabled. */
547             __asm volatile ( "cpsie i" ::: "memory" );
548         }
549     }
550 #endif /* configUSE_TICKLESS_IDLE */
551 /*-----------------------------------------------------------*/
552
553 __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
554 {
555     /* Calculate the constants required to configure the tick interrupt. */
556     #if ( configUSE_TICKLESS_IDLE == 1 )
557         {
558             ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
559             xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
560             ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
561         }
562     #endif /* configUSE_TICKLESS_IDLE */
563
564     /* Stop and reset the SysTick. */
565     portNVIC_SYSTICK_CTRL_REG = 0UL;
566     portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
567
568     /* Configure SysTick to interrupt at the requested rate. */
569     portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
570     portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
571 }
572 /*-----------------------------------------------------------*/
573
574 static void prvTaskExitError( void )
575 {
576     volatile uint32_t ulDummy = 0UL;
577
578     /* A function that implements a task must not exit or attempt to return to
579      * its caller as there is nothing to return to. If a task wants to exit it
580      * should instead call vTaskDelete( NULL ). Artificially force an assert()
581      * to be triggered if configASSERT() is defined, then stop here so
582      * application writers can catch the error. */
583     configASSERT( ulCriticalNesting == ~0UL );
584     portDISABLE_INTERRUPTS();
585
586     while( ulDummy == 0 )
587     {
588         /* This file calls prvTaskExitError() after the scheduler has been
589          * started to remove a compiler warning about the function being
590          * defined but never called.  ulDummy is used purely to quieten other
591          * warnings about code appearing after this function is called - making
592          * ulDummy volatile makes the compiler think the function could return
593          * and therefore not output an 'unreachable code' warning for code that
594          * appears after it. */
595     }
596 }
597 /*-----------------------------------------------------------*/
598
599 #if ( configENABLE_MPU == 1 )
600     static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */
601     {
602         #if defined( __ARMCC_VERSION )
603
604             /* Declaration when these variable are defined in code instead of being
605              * exported from linker scripts. */
606             extern uint32_t * __privileged_functions_start__;
607             extern uint32_t * __privileged_functions_end__;
608             extern uint32_t * __syscalls_flash_start__;
609             extern uint32_t * __syscalls_flash_end__;
610             extern uint32_t * __unprivileged_flash_start__;
611             extern uint32_t * __unprivileged_flash_end__;
612             extern uint32_t * __privileged_sram_start__;
613             extern uint32_t * __privileged_sram_end__;
614         #else /* if defined( __ARMCC_VERSION ) */
615             /* Declaration when these variable are exported from linker scripts. */
616             extern uint32_t __privileged_functions_start__[];
617             extern uint32_t __privileged_functions_end__[];
618             extern uint32_t __syscalls_flash_start__[];
619             extern uint32_t __syscalls_flash_end__[];
620             extern uint32_t __unprivileged_flash_start__[];
621             extern uint32_t __unprivileged_flash_end__[];
622             extern uint32_t __privileged_sram_start__[];
623             extern uint32_t __privileged_sram_end__[];
624         #endif /* defined( __ARMCC_VERSION ) */
625
626         /* Check that the MPU is present. */
627         if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
628         {
629             /* MAIR0 - Index 0. */
630             portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
631             /* MAIR0 - Index 1. */
632             portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
633
634             /* Setup privileged flash as Read Only so that privileged tasks can
635              * read it but not modify. */
636             portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
637             portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
638                                ( portMPU_REGION_NON_SHAREABLE ) |
639                                ( portMPU_REGION_PRIVILEGED_READ_ONLY );
640             portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
641                                ( portMPU_RLAR_ATTR_INDEX0 ) |
642                                ( portMPU_RLAR_REGION_ENABLE );
643
644             /* Setup unprivileged flash as Read Only by both privileged and
645              * unprivileged tasks. All tasks can read it but no-one can modify. */
646             portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
647             portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
648                                ( portMPU_REGION_NON_SHAREABLE ) |
649                                ( portMPU_REGION_READ_ONLY );
650             portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
651                                ( portMPU_RLAR_ATTR_INDEX0 ) |
652                                ( portMPU_RLAR_REGION_ENABLE );
653
654             /* Setup unprivileged syscalls flash as Read Only by both privileged
655              * and unprivileged tasks. All tasks can read it but no-one can modify. */
656             portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
657             portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
658                                ( portMPU_REGION_NON_SHAREABLE ) |
659                                ( portMPU_REGION_READ_ONLY );
660             portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
661                                ( portMPU_RLAR_ATTR_INDEX0 ) |
662                                ( portMPU_RLAR_REGION_ENABLE );
663
664             /* Setup RAM containing kernel data for privileged access only. */
665             portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
666             portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
667                                ( portMPU_REGION_NON_SHAREABLE ) |
668                                ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
669                                ( portMPU_REGION_EXECUTE_NEVER );
670             portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
671                                ( portMPU_RLAR_ATTR_INDEX0 ) |
672                                ( portMPU_RLAR_REGION_ENABLE );
673
674             /* Enable mem fault. */
675             portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
676
677             /* Enable MPU with privileged background access i.e. unmapped
678              * regions have privileged access. */
679             portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
680         }
681     }
682 #endif /* configENABLE_MPU */
683 /*-----------------------------------------------------------*/
684
685 #if ( configENABLE_FPU == 1 )
686     static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */
687     {
688         #if ( configENABLE_TRUSTZONE == 1 )
689             {
690                 /* Enable non-secure access to the FPU. */
691                 SecureInit_EnableNSFPUAccess();
692             }
693         #endif /* configENABLE_TRUSTZONE */
694
695         /* CP10 = 11 ==> Full access to FPU i.e. both privileged and
696          * unprivileged code should be able to access FPU. CP11 should be
697          * programmed to the same value as CP10. */
698         *( portCPACR ) |= ( ( portCPACR_CP10_VALUE << portCPACR_CP10_POS ) |
699                             ( portCPACR_CP11_VALUE << portCPACR_CP11_POS )
700                             );
701
702         /* ASPEN = 1 ==> Hardware should automatically preserve floating point
703          * context on exception entry and restore on exception return.
704          * LSPEN = 1 ==> Enable lazy context save of FP state. */
705         *( portFPCCR ) |= ( portFPCCR_ASPEN_MASK | portFPCCR_LSPEN_MASK );
706     }
707 #endif /* configENABLE_FPU */
708 /*-----------------------------------------------------------*/
709
710 void vPortYield( void ) /* PRIVILEGED_FUNCTION */
711 {
712     /* Set a PendSV to request a context switch. */
713     portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
714
715     /* Barriers are normally not required but do ensure the code is
716      * completely within the specified behaviour for the architecture. */
717     __asm volatile ( "dsb" ::: "memory" );
718     __asm volatile ( "isb" );
719 }
720 /*-----------------------------------------------------------*/
721
722 void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
723 {
724     portDISABLE_INTERRUPTS();
725     ulCriticalNesting++;
726
727     /* Barriers are normally not required but do ensure the code is
728      * completely within the specified behaviour for the architecture. */
729     __asm volatile ( "dsb" ::: "memory" );
730     __asm volatile ( "isb" );
731 }
732 /*-----------------------------------------------------------*/
733
734 void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
735 {
736     configASSERT( ulCriticalNesting );
737     ulCriticalNesting--;
738
739     if( ulCriticalNesting == 0 )
740     {
741         portENABLE_INTERRUPTS();
742     }
743 }
744 /*-----------------------------------------------------------*/
745
746 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
747 {
748     uint32_t ulPreviousMask;
749
750     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
751     {
752         /* Increment the RTOS tick. */
753         if( xTaskIncrementTick() != pdFALSE )
754         {
755             /* Pend a context switch. */
756             portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
757         }
758     }
759     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
760 }
761 /*-----------------------------------------------------------*/
762
763 void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */
764 {
765     #if ( configENABLE_MPU == 1 )
766         #if defined( __ARMCC_VERSION )
767
768             /* Declaration when these variable are defined in code instead of being
769              * exported from linker scripts. */
770             extern uint32_t * __syscalls_flash_start__;
771             extern uint32_t * __syscalls_flash_end__;
772         #else
773             /* Declaration when these variable are exported from linker scripts. */
774             extern uint32_t __syscalls_flash_start__[];
775             extern uint32_t __syscalls_flash_end__[];
776         #endif /* defined( __ARMCC_VERSION ) */
777     #endif /* configENABLE_MPU */
778
779     uint32_t ulPC;
780
781     #if ( configENABLE_TRUSTZONE == 1 )
782         uint32_t ulR0;
783         #if ( configENABLE_MPU == 1 )
784             uint32_t ulControl, ulIsTaskPrivileged;
785         #endif /* configENABLE_MPU */
786     #endif /* configENABLE_TRUSTZONE */
787     uint8_t ucSVCNumber;
788
789     /* Register are stored on the stack in the following order - R0, R1, R2, R3,
790      * R12, LR, PC, xPSR. */
791     ulPC = pulCallerStackAddress[ 6 ];
792     ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];
793
794     switch( ucSVCNumber )
795     {
796         #if ( configENABLE_TRUSTZONE == 1 )
797             case portSVC_ALLOCATE_SECURE_CONTEXT:
798
799                 /* R0 contains the stack size passed as parameter to the
800                  * vPortAllocateSecureContext function. */
801                 ulR0 = pulCallerStackAddress[ 0 ];
802
803                 #if ( configENABLE_MPU == 1 )
804                     {
805                         /* Read the CONTROL register value. */
806                         __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
807
808                         /* The task that raised the SVC is privileged if Bit[0]
809                          * in the CONTROL register is 0. */
810                         ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
811
812                         /* Allocate and load a context for the secure task. */
813                         xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged );
814                     }
815                 #else /* if ( configENABLE_MPU == 1 ) */
816                     {
817                         /* Allocate and load a context for the secure task. */
818                         xSecureContext = SecureContext_AllocateContext( ulR0 );
819                     }
820                 #endif /* configENABLE_MPU */
821
822                 configASSERT( xSecureContext != NULL );
823                 SecureContext_LoadContext( xSecureContext );
824                 break;
825
826             case portSVC_FREE_SECURE_CONTEXT:
827                 /* R0 contains the secure context handle to be freed. */
828                 ulR0 = pulCallerStackAddress[ 0 ];
829
830                 /* Free the secure context. */
831                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR0 );
832                 break;
833         #endif /* configENABLE_TRUSTZONE */
834
835         case portSVC_START_SCHEDULER:
836             #if ( configENABLE_TRUSTZONE == 1 )
837                 {
838                     /* De-prioritize the non-secure exceptions so that the
839                      * non-secure pendSV runs at the lowest priority. */
840                     SecureInit_DePrioritizeNSExceptions();
841
842                     /* Initialize the secure context management system. */
843                     SecureContext_Init();
844                 }
845             #endif /* configENABLE_TRUSTZONE */
846
847             #if ( configENABLE_FPU == 1 )
848                 {
849                     /* Setup the Floating Point Unit (FPU). */
850                     prvSetupFPU();
851                 }
852             #endif /* configENABLE_FPU */
853
854             /* Setup the context of the first task so that the first task starts
855              * executing. */
856             vRestoreContextOfFirstTask();
857             break;
858
859             #if ( configENABLE_MPU == 1 )
860                 case portSVC_RAISE_PRIVILEGE:
861
862                     /* Only raise the privilege, if the svc was raised from any of
863                      * the system calls. */
864                     if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
865                         ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
866                     {
867                         vRaisePrivilege();
868                     }
869                     break;
870             #endif /* configENABLE_MPU */
871
872         default:
873             /* Incorrect SVC call. */
874             configASSERT( pdFALSE );
875     }
876 }
877 /*-----------------------------------------------------------*/
878 /* *INDENT-OFF* */
879 #if ( configENABLE_MPU == 1 )
880     StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
881                                          StackType_t * pxEndOfStack,
882                                          TaskFunction_t pxCode,
883                                          void * pvParameters,
884                                          BaseType_t xRunPrivileged ) /* PRIVILEGED_FUNCTION */
885 #else
886     StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
887                                          StackType_t * pxEndOfStack,
888                                          TaskFunction_t pxCode,
889                                          void * pvParameters ) /* PRIVILEGED_FUNCTION */
890 #endif /* configENABLE_MPU */
891 /* *INDENT-ON* */
892 {
893     /* Simulate the stack frame as it would be created by a context switch
894      * interrupt. */
895     #if ( portPRELOAD_REGISTERS == 0 )
896         {
897             pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
898             *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR */
899             pxTopOfStack--;
900             *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC */
901             pxTopOfStack--;
902             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
903             pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
904             *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0 */
905             pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
906             *pxTopOfStack = portINITIAL_EXC_RETURN;
907
908             #if ( configENABLE_MPU == 1 )
909                 {
910                     pxTopOfStack--;
911
912                     if( xRunPrivileged == pdTRUE )
913                     {
914                         *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
915                     }
916                     else
917                     {
918                         *pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */
919                     }
920                 }
921             #endif /* configENABLE_MPU */
922
923             pxTopOfStack--;
924             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
925
926             #if ( configENABLE_TRUSTZONE == 1 )
927                 {
928                     pxTopOfStack--;
929                     *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
930                 }
931             #endif /* configENABLE_TRUSTZONE */
932         }
933     #else /* portPRELOAD_REGISTERS */
934         {
935             pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
936             *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR */
937             pxTopOfStack--;
938             *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC */
939             pxTopOfStack--;
940             *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */
941             pxTopOfStack--;
942             *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12 */
943             pxTopOfStack--;
944             *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3 */
945             pxTopOfStack--;
946             *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2 */
947             pxTopOfStack--;
948             *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1 */
949             pxTopOfStack--;
950             *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0 */
951             pxTopOfStack--;
952             *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11 */
953             pxTopOfStack--;
954             *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10 */
955             pxTopOfStack--;
956             *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09 */
957             pxTopOfStack--;
958             *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08 */
959             pxTopOfStack--;
960             *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07 */
961             pxTopOfStack--;
962             *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06 */
963             pxTopOfStack--;
964             *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05 */
965             pxTopOfStack--;
966             *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04 */
967             pxTopOfStack--;
968             *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN */
969
970             #if ( configENABLE_MPU == 1 )
971                 {
972                     pxTopOfStack--;
973
974                     if( xRunPrivileged == pdTRUE )
975                     {
976                         *pxTopOfStack = portINITIAL_CONTROL_PRIVILEGED; /* Slot used to hold this task's CONTROL value. */
977                     }
978                     else
979                     {
980                         *pxTopOfStack = portINITIAL_CONTROL_UNPRIVILEGED; /* Slot used to hold this task's CONTROL value. */
981                     }
982                 }
983             #endif /* configENABLE_MPU */
984
985             pxTopOfStack--;
986             *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
987
988             #if ( configENABLE_TRUSTZONE == 1 )
989                 {
990                     pxTopOfStack--;
991                     *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
992                 }
993             #endif /* configENABLE_TRUSTZONE */
994         }
995     #endif /* portPRELOAD_REGISTERS */
996
997     return pxTopOfStack;
998 }
999 /*-----------------------------------------------------------*/
1000
1001 BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
1002 {
1003     /* Make PendSV, CallSV and SysTick the same priority as the kernel. */
1004     portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
1005     portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
1006
1007     #if ( configENABLE_MPU == 1 )
1008         {
1009             /* Setup the Memory Protection Unit (MPU). */
1010             prvSetupMPU();
1011         }
1012     #endif /* configENABLE_MPU */
1013
1014     /* Start the timer that generates the tick ISR. Interrupts are disabled
1015      * here already. */
1016     vPortSetupTimerInterrupt();
1017
1018     /* Initialize the critical nesting count ready for the first task. */
1019     ulCriticalNesting = 0;
1020
1021     /* Start the first task. */
1022     vStartFirstTask();
1023
1024     /* Should never get here as the tasks will now be executing. Call the task
1025      * exit error function to prevent compiler warnings about a static function
1026      * not being called in the case that the application writer overrides this
1027      * functionality by defining configTASK_RETURN_ADDRESS. Call
1028      * vTaskSwitchContext() so link time optimization does not remove the
1029      * symbol. */
1030     vTaskSwitchContext();
1031     prvTaskExitError();
1032
1033     /* Should not get here. */
1034     return 0;
1035 }
1036 /*-----------------------------------------------------------*/
1037
1038 void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
1039 {
1040     /* Not implemented in ports where there is nothing to return to.
1041      * Artificially force an assert. */
1042     configASSERT( ulCriticalNesting == 1000UL );
1043 }
1044 /*-----------------------------------------------------------*/
1045
1046 #if ( configENABLE_MPU == 1 )
1047     void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
1048                                     const struct xMEMORY_REGION * const xRegions,
1049                                     StackType_t * pxBottomOfStack,
1050                                     uint32_t ulStackDepth )
1051     {
1052         uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
1053         int32_t lIndex = 0;
1054
1055         #if defined( __ARMCC_VERSION )
1056
1057             /* Declaration when these variable are defined in code instead of being
1058              * exported from linker scripts. */
1059             extern uint32_t * __privileged_sram_start__;
1060             extern uint32_t * __privileged_sram_end__;
1061         #else
1062             /* Declaration when these variable are exported from linker scripts. */
1063             extern uint32_t __privileged_sram_start__[];
1064             extern uint32_t __privileged_sram_end__[];
1065         #endif /* defined( __ARMCC_VERSION ) */
1066
1067         /* Setup MAIR0. */
1068         xMPUSettings->ulMAIR0 = ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
1069         xMPUSettings->ulMAIR0 |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
1070
1071         /* This function is called automatically when the task is created - in
1072          * which case the stack region parameters will be valid.  At all other
1073          * times the stack parameters will not be valid and it is assumed that
1074          * the stack region has already been configured. */
1075         if( ulStackDepth > 0 )
1076         {
1077             ulRegionStartAddress = ( uint32_t ) pxBottomOfStack;
1078             ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1;
1079
1080             /* If the stack is within the privileged SRAM, do not protect it
1081              * using a separate MPU region. This is needed because privileged
1082              * SRAM is already protected using an MPU region and ARMv8-M does
1083              * not allow overlapping MPU regions. */
1084             if( ( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ ) &&
1085                 ( ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) )
1086             {
1087                 xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0;
1088                 xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0;
1089             }
1090             else
1091             {
1092                 /* Define the region that allows access to the stack. */
1093                 ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK;
1094                 ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
1095
1096                 xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) |
1097                                                              ( portMPU_REGION_NON_SHAREABLE ) |
1098                                                              ( portMPU_REGION_READ_WRITE ) |
1099                                                              ( portMPU_REGION_EXECUTE_NEVER );
1100
1101                 xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) |
1102                                                              ( portMPU_RLAR_ATTR_INDEX0 ) |
1103                                                              ( portMPU_RLAR_REGION_ENABLE );
1104             }
1105         }
1106
1107         /* User supplied configurable regions. */
1108         for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ )
1109         {
1110             /* If xRegions is NULL i.e. the task has not specified any MPU
1111              * region, the else part ensures that all the configurable MPU
1112              * regions are invalidated. */
1113             if( ( xRegions != NULL ) && ( xRegions[ lIndex ].ulLengthInBytes > 0UL ) )
1114             {
1115                 /* Translate the generic region definition contained in xRegions
1116                  * into the ARMv8 specific MPU settings that are then stored in
1117                  * xMPUSettings. */
1118                 ulRegionStartAddress = ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) & portMPU_RBAR_ADDRESS_MASK;
1119                 ulRegionEndAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1;
1120                 ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
1121
1122                 /* Start address. */
1123                 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) |
1124                                                                           ( portMPU_REGION_NON_SHAREABLE );
1125
1126                 /* RO/RW. */
1127                 if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_READ_ONLY ) != 0 )
1128                 {
1129                     xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_ONLY );
1130                 }
1131                 else
1132                 {
1133                     xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_WRITE );
1134                 }
1135
1136                 /* XN. */
1137                 if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 )
1138                 {
1139                     xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER );
1140                 }
1141
1142                 /* End Address. */
1143                 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) |
1144                                                                           ( portMPU_RLAR_REGION_ENABLE );
1145
1146                 /* Normal memory/ Device memory. */
1147                 if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_DEVICE_MEMORY ) != 0 )
1148                 {
1149                     /* Attr1 in MAIR0 is configured as device memory. */
1150                     xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX1;
1151                 }
1152                 else
1153                 {
1154                     /* Attr1 in MAIR0 is configured as normal memory. */
1155                     xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX0;
1156                 }
1157             }
1158             else
1159             {
1160                 /* Invalidate the region. */
1161                 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = 0UL;
1162                 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = 0UL;
1163             }
1164
1165             lIndex++;
1166         }
1167     }
1168 #endif /* configENABLE_MPU */
1169 /*-----------------------------------------------------------*/
1170
1171 BaseType_t xPortIsInsideInterrupt( void )
1172 {
1173     uint32_t ulCurrentInterrupt;
1174     BaseType_t xReturn;
1175
1176     /* Obtain the number of the currently executing interrupt. Interrupt Program
1177      * Status Register (IPSR) holds the exception number of the currently-executing
1178      * exception or zero for Thread mode.*/
1179     __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
1180
1181     if( ulCurrentInterrupt == 0 )
1182     {
1183         xReturn = pdFALSE;
1184     }
1185     else
1186     {
1187         xReturn = pdTRUE;
1188     }
1189
1190     return xReturn;
1191 }
1192 /*-----------------------------------------------------------*/