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