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