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