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