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