]> begriffs open source - freertos/blob - portable/GCC/ARM_CM55/non_secure/port.c
Fix remarks emitted by IAR compiler (#763)
[freertos] / portable / GCC / ARM_CM55 / 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 used during system call enter and exit.
112  */
113 #define portPSR_STACK_PADDING_MASK                ( 1UL << 9UL )
114 #define portEXC_RETURN_STACK_FRAME_TYPE_MASK      ( 1UL << 4UL )
115 /*-----------------------------------------------------------*/
116
117 /**
118  * @brief Constants required to manipulate the FPU.
119  */
120 #define portCPACR               ( ( volatile uint32_t * ) 0xe000ed88 )              /* Coprocessor Access Control Register. */
121 #define portCPACR_CP10_VALUE    ( 3UL )
122 #define portCPACR_CP11_VALUE    portCPACR_CP10_VALUE
123 #define portCPACR_CP10_POS      ( 20UL )
124 #define portCPACR_CP11_POS      ( 22UL )
125
126 #define portFPCCR               ( ( volatile uint32_t * ) 0xe000ef34 )              /* Floating Point Context Control Register. */
127 #define portFPCCR_ASPEN_POS     ( 31UL )
128 #define portFPCCR_ASPEN_MASK    ( 1UL << portFPCCR_ASPEN_POS )
129 #define portFPCCR_LSPEN_POS     ( 30UL )
130 #define portFPCCR_LSPEN_MASK    ( 1UL << portFPCCR_LSPEN_POS )
131 /*-----------------------------------------------------------*/
132
133 /**
134  * @brief Offsets in the stack to the parameters when inside the SVC handler.
135  */
136 #define portOFFSET_TO_LR                    ( 5 )
137 #define portOFFSET_TO_PC                    ( 6 )
138 #define portOFFSET_TO_PSR                   ( 7 )
139 /*-----------------------------------------------------------*/
140
141 /**
142  * @brief Constants required to manipulate the MPU.
143  */
144 #define portMPU_TYPE_REG                      ( *( ( volatile uint32_t * ) 0xe000ed90 ) )
145 #define portMPU_CTRL_REG                      ( *( ( volatile uint32_t * ) 0xe000ed94 ) )
146 #define portMPU_RNR_REG                       ( *( ( volatile uint32_t * ) 0xe000ed98 ) )
147
148 #define portMPU_RBAR_REG                      ( *( ( volatile uint32_t * ) 0xe000ed9c ) )
149 #define portMPU_RLAR_REG                      ( *( ( volatile uint32_t * ) 0xe000eda0 ) )
150
151 #define portMPU_RBAR_A1_REG                   ( *( ( volatile uint32_t * ) 0xe000eda4 ) )
152 #define portMPU_RLAR_A1_REG                   ( *( ( volatile uint32_t * ) 0xe000eda8 ) )
153
154 #define portMPU_RBAR_A2_REG                   ( *( ( volatile uint32_t * ) 0xe000edac ) )
155 #define portMPU_RLAR_A2_REG                   ( *( ( volatile uint32_t * ) 0xe000edb0 ) )
156
157 #define portMPU_RBAR_A3_REG                   ( *( ( volatile uint32_t * ) 0xe000edb4 ) )
158 #define portMPU_RLAR_A3_REG                   ( *( ( volatile uint32_t * ) 0xe000edb8 ) )
159
160 #define portMPU_MAIR0_REG                     ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
161 #define portMPU_MAIR1_REG                     ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
162
163 #define portMPU_RBAR_ADDRESS_MASK             ( 0xffffffe0 ) /* Must be 32-byte aligned. */
164 #define portMPU_RLAR_ADDRESS_MASK             ( 0xffffffe0 ) /* Must be 32-byte aligned. */
165
166 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK  ( 3UL << 1UL )
167
168 #define portMPU_MAIR_ATTR0_POS                ( 0UL )
169 #define portMPU_MAIR_ATTR0_MASK               ( 0x000000ff )
170
171 #define portMPU_MAIR_ATTR1_POS                ( 8UL )
172 #define portMPU_MAIR_ATTR1_MASK               ( 0x0000ff00 )
173
174 #define portMPU_MAIR_ATTR2_POS                ( 16UL )
175 #define portMPU_MAIR_ATTR2_MASK               ( 0x00ff0000 )
176
177 #define portMPU_MAIR_ATTR3_POS                ( 24UL )
178 #define portMPU_MAIR_ATTR3_MASK               ( 0xff000000 )
179
180 #define portMPU_MAIR_ATTR4_POS                ( 0UL )
181 #define portMPU_MAIR_ATTR4_MASK               ( 0x000000ff )
182
183 #define portMPU_MAIR_ATTR5_POS                ( 8UL )
184 #define portMPU_MAIR_ATTR5_MASK               ( 0x0000ff00 )
185
186 #define portMPU_MAIR_ATTR6_POS                ( 16UL )
187 #define portMPU_MAIR_ATTR6_MASK               ( 0x00ff0000 )
188
189 #define portMPU_MAIR_ATTR7_POS                ( 24UL )
190 #define portMPU_MAIR_ATTR7_MASK               ( 0xff000000 )
191
192 #define portMPU_RLAR_ATTR_INDEX0              ( 0UL << 1UL )
193 #define portMPU_RLAR_ATTR_INDEX1              ( 1UL << 1UL )
194 #define portMPU_RLAR_ATTR_INDEX2              ( 2UL << 1UL )
195 #define portMPU_RLAR_ATTR_INDEX3              ( 3UL << 1UL )
196 #define portMPU_RLAR_ATTR_INDEX4              ( 4UL << 1UL )
197 #define portMPU_RLAR_ATTR_INDEX5              ( 5UL << 1UL )
198 #define portMPU_RLAR_ATTR_INDEX6              ( 6UL << 1UL )
199 #define portMPU_RLAR_ATTR_INDEX7              ( 7UL << 1UL )
200
201 #define portMPU_RLAR_REGION_ENABLE            ( 1UL )
202
203 /* Enable privileged access to unmapped region. */
204 #define portMPU_PRIV_BACKGROUND_ENABLE_BIT    ( 1UL << 2UL )
205
206 /* Enable MPU. */
207 #define portMPU_ENABLE_BIT                    ( 1UL << 0UL )
208
209 /* Expected value of the portMPU_TYPE register. */
210 #define portEXPECTED_MPU_TYPE_VALUE           ( configTOTAL_MPU_REGIONS << 8UL )
211
212 /* Extract first address of the MPU region as encoded in the
213  * RBAR (Region Base Address Register) value. */
214 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
215     ( ( rbar ) & portMPU_RBAR_ADDRESS_MASK )
216
217 /* Extract last address of the MPU region as encoded in the
218  * RLAR (Region Limit Address Register) value. */
219 #define portEXTRACT_LAST_ADDRESS_FROM_RLAR( rlar )  \
220     ( ( ( rlar ) & portMPU_RLAR_ADDRESS_MASK ) | ~portMPU_RLAR_ADDRESS_MASK )
221
222 /* Does addr lies within [start, end] address range? */
223 #define portIS_ADDRESS_WITHIN_RANGE( addr, start, end )    \
224     ( ( ( addr ) >= ( start ) ) && ( ( addr ) <= ( end ) ) )
225
226 /* Is the access request satisfied by the available permissions? */
227 #define portIS_AUTHORIZED( accessRequest, permissions ) \
228     ( ( ( permissions ) & ( accessRequest ) ) == accessRequest )
229
230 /* Max value that fits in a uint32_t type. */
231 #define portUINT32_MAX    ( ~( ( uint32_t ) 0 ) )
232
233 /* Check if adding a and b will result in overflow. */
234 #define portADD_UINT32_WILL_OVERFLOW( a, b )    ( ( a ) > ( portUINT32_MAX - ( b ) ) )
235 /*-----------------------------------------------------------*/
236
237 /**
238  * @brief The maximum 24-bit number.
239  *
240  * It is needed because the systick is a 24-bit counter.
241  */
242 #define portMAX_24_BIT_NUMBER       ( 0xffffffUL )
243
244 /**
245  * @brief A fiddle factor to estimate the number of SysTick counts that would
246  * have occurred while the SysTick counter is stopped during tickless idle
247  * calculations.
248  */
249 #define portMISSED_COUNTS_FACTOR    ( 94UL )
250 /*-----------------------------------------------------------*/
251
252 /**
253  * @brief Constants required to set up the initial stack.
254  */
255 #define portINITIAL_XPSR    ( 0x01000000 )
256
257 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
258
259 /**
260  * @brief Initial EXC_RETURN value.
261  *
262  *     FF         FF         FF         FD
263  * 1111 1111  1111 1111  1111 1111  1111 1101
264  *
265  * Bit[6] - 1 --> The exception was taken from the Secure state.
266  * Bit[5] - 1 --> Do not skip stacking of additional state context.
267  * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
268  * Bit[3] - 1 --> Return to the Thread mode.
269  * Bit[2] - 1 --> Restore registers from the process stack.
270  * Bit[1] - 0 --> Reserved, 0.
271  * Bit[0] - 1 --> The exception was taken to the Secure state.
272  */
273     #define portINITIAL_EXC_RETURN    ( 0xfffffffd )
274 #else
275
276 /**
277  * @brief Initial EXC_RETURN value.
278  *
279  *     FF         FF         FF         BC
280  * 1111 1111  1111 1111  1111 1111  1011 1100
281  *
282  * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
283  * Bit[5] - 1 --> Do not skip stacking of additional state context.
284  * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
285  * Bit[3] - 1 --> Return to the Thread mode.
286  * Bit[2] - 1 --> Restore registers from the process stack.
287  * Bit[1] - 0 --> Reserved, 0.
288  * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
289  */
290     #define portINITIAL_EXC_RETURN    ( 0xffffffbc )
291 #endif /* configRUN_FREERTOS_SECURE_ONLY */
292
293 /**
294  * @brief CONTROL register privileged bit mask.
295  *
296  * Bit[0] in CONTROL register tells the privilege:
297  *  Bit[0] = 0 ==> The task is privileged.
298  *  Bit[0] = 1 ==> The task is not privileged.
299  */
300 #define portCONTROL_PRIVILEGED_MASK         ( 1UL << 0UL )
301
302 /**
303  * @brief Initial CONTROL register values.
304  */
305 #define portINITIAL_CONTROL_UNPRIVILEGED    ( 0x3 )
306 #define portINITIAL_CONTROL_PRIVILEGED      ( 0x2 )
307
308 /**
309  * @brief Let the user override the default SysTick clock rate.  If defined by the
310  * user, this symbol must equal the SysTick clock rate when the CLK bit is 0 in the
311  * configuration register.
312  */
313 #ifndef configSYSTICK_CLOCK_HZ
314     #define configSYSTICK_CLOCK_HZ             ( configCPU_CLOCK_HZ )
315     /* Ensure the SysTick is clocked at the same frequency as the core. */
316     #define portNVIC_SYSTICK_CLK_BIT_CONFIG    ( portNVIC_SYSTICK_CLK_BIT )
317 #else
318     /* Select the option to clock SysTick not at the same frequency as the core. */
319     #define portNVIC_SYSTICK_CLK_BIT_CONFIG    ( 0 )
320 #endif
321
322 /**
323  * @brief Let the user override the pre-loading of the initial LR with the
324  * address of prvTaskExitError() in case it messes up unwinding of the stack
325  * in the debugger.
326  */
327 #ifdef configTASK_RETURN_ADDRESS
328     #define portTASK_RETURN_ADDRESS    configTASK_RETURN_ADDRESS
329 #else
330     #define portTASK_RETURN_ADDRESS    prvTaskExitError
331 #endif
332
333 /**
334  * @brief If portPRELOAD_REGISTERS then registers will be given an initial value
335  * when a task is created. This helps in debugging at the cost of code size.
336  */
337 #define portPRELOAD_REGISTERS    1
338
339 /**
340  * @brief A task is created without a secure context, and must call
341  * portALLOCATE_SECURE_CONTEXT() to give itself a secure context before it makes
342  * any secure calls.
343  */
344 #define portNO_SECURE_CONTEXT    0
345 /*-----------------------------------------------------------*/
346
347 /**
348  * @brief Used to catch tasks that attempt to return from their implementing
349  * function.
350  */
351 static void prvTaskExitError( void );
352
353 #if ( configENABLE_MPU == 1 )
354
355 /**
356  * @brief Extract MPU region's access permissions from the Region Base Address
357  * Register (RBAR) value.
358  *
359  * @param ulRBARValue RBAR value for the MPU region.
360  *
361  * @return uint32_t Access permissions.
362  */
363     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
364 #endif /* configENABLE_MPU */
365
366 #if ( configENABLE_MPU == 1 )
367
368 /**
369  * @brief Setup the Memory Protection Unit (MPU).
370  */
371     static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
372 #endif /* configENABLE_MPU */
373
374 #if ( configENABLE_FPU == 1 )
375
376 /**
377  * @brief Setup the Floating Point Unit (FPU).
378  */
379     static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
380 #endif /* configENABLE_FPU */
381
382 /**
383  * @brief Setup the timer to generate the tick interrupts.
384  *
385  * The implementation in this file is weak to allow application writers to
386  * change the timer used to generate the tick interrupt.
387  */
388 void vPortSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION;
389
390 /**
391  * @brief Checks whether the current execution context is interrupt.
392  *
393  * @return pdTRUE if the current execution context is interrupt, pdFALSE
394  * otherwise.
395  */
396 BaseType_t xPortIsInsideInterrupt( void );
397
398 /**
399  * @brief Yield the processor.
400  */
401 void vPortYield( void ) PRIVILEGED_FUNCTION;
402
403 /**
404  * @brief Enter critical section.
405  */
406 void vPortEnterCritical( void ) PRIVILEGED_FUNCTION;
407
408 /**
409  * @brief Exit from critical section.
410  */
411 void vPortExitCritical( void ) PRIVILEGED_FUNCTION;
412
413 /**
414  * @brief SysTick handler.
415  */
416 void SysTick_Handler( void ) PRIVILEGED_FUNCTION;
417
418 /**
419  * @brief C part of SVC handler.
420  */
421 portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIVILEGED_FUNCTION;
422
423 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
424
425     /**
426      * @brief Sets up the system call stack so that upon returning from
427      * SVC, the system call stack is used.
428      *
429      * It is used for the system calls with up to 4 parameters.
430      *
431      * @param pulTaskStack The current SP when the SVC was raised.
432      * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
433      */
434     void vSystemCallEnter( uint32_t * pulTaskStack, uint32_t ulLR ) PRIVILEGED_FUNCTION;
435
436 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
437
438 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
439
440     /**
441      * @brief Sets up the system call stack so that upon returning from
442      * SVC, the system call stack is used.
443      *
444      * It is used for the system calls with 5 parameters.
445      *
446      * @param pulTaskStack The current SP when the SVC was raised.
447      * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
448      */
449     void vSystemCallEnter_1( uint32_t * pulTaskStack, uint32_t ulLR ) PRIVILEGED_FUNCTION;
450
451 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
452
453 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
454
455     /**
456      * @brief Sets up the task stack so that upon returning from
457      * SVC, the task stack is used again.
458      *
459      * @param pulSystemCallStack The current SP when the SVC was raised.
460      * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
461      */
462     void vSystemCallExit( uint32_t * pulSystemCallStack, uint32_t ulLR ) PRIVILEGED_FUNCTION;
463
464 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
465
466 #if ( configENABLE_MPU == 1 )
467
468     /**
469      * @brief Checks whether or not the calling task is privileged.
470      *
471      * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
472      */
473     BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
474
475 #endif /* configENABLE_MPU == 1 */
476 /*-----------------------------------------------------------*/
477
478 /**
479  * @brief Each task maintains its own interrupt status in the critical nesting
480  * variable.
481  */
482 PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
483
484 #if ( configENABLE_TRUSTZONE == 1 )
485
486 /**
487  * @brief Saved as part of the task context to indicate which context the
488  * task is using on the secure side.
489  */
490     PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
491 #endif /* configENABLE_TRUSTZONE */
492
493 /**
494  * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
495  * FreeRTOS API functions are not called from interrupts that have been assigned
496  * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
497  */
498 #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
499
500     static uint8_t ucMaxSysCallPriority = 0;
501     static uint32_t ulMaxPRIGROUPValue = 0;
502     static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16;
503
504 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
505
506 #if ( configUSE_TICKLESS_IDLE == 1 )
507
508 /**
509  * @brief The number of SysTick increments that make up one tick period.
510  */
511     PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
512
513 /**
514  * @brief The maximum number of tick periods that can be suppressed is
515  * limited by the 24 bit resolution of the SysTick timer.
516  */
517     PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
518
519 /**
520  * @brief Compensate for the CPU cycles that pass while the SysTick is
521  * stopped (low power functionality only).
522  */
523     PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
524 #endif /* configUSE_TICKLESS_IDLE */
525 /*-----------------------------------------------------------*/
526
527 #if ( configUSE_TICKLESS_IDLE == 1 )
528     __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
529     {
530         uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft;
531         TickType_t xModifiableIdleTime;
532
533         /* Make sure the SysTick reload value does not overflow the counter. */
534         if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
535         {
536             xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
537         }
538
539         /* Enter a critical section but don't use the taskENTER_CRITICAL()
540          * method as that will mask interrupts that should exit sleep mode. */
541         __asm volatile ( "cpsid i" ::: "memory" );
542         __asm volatile ( "dsb" );
543         __asm volatile ( "isb" );
544
545         /* If a context switch is pending or a task is waiting for the scheduler
546          * to be unsuspended then abandon the low power entry. */
547         if( eTaskConfirmSleepModeStatus() == eAbortSleep )
548         {
549             /* Re-enable interrupts - see comments above the cpsid instruction
550              * above. */
551             __asm volatile ( "cpsie i" ::: "memory" );
552         }
553         else
554         {
555             /* Stop the SysTick momentarily.  The time the SysTick is stopped for
556              * is accounted for as best it can be, but using the tickless mode will
557              * inevitably result in some tiny drift of the time maintained by the
558              * kernel with respect to calendar time. */
559             portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT );
560
561             /* Use the SysTick current-value register to determine the number of
562              * SysTick decrements remaining until the next tick interrupt.  If the
563              * current-value register is zero, then there are actually
564              * ulTimerCountsForOneTick decrements remaining, not zero, because the
565              * SysTick requests the interrupt when decrementing from 1 to 0. */
566             ulSysTickDecrementsLeft = portNVIC_SYSTICK_CURRENT_VALUE_REG;
567
568             if( ulSysTickDecrementsLeft == 0 )
569             {
570                 ulSysTickDecrementsLeft = ulTimerCountsForOneTick;
571             }
572
573             /* Calculate the reload value required to wait xExpectedIdleTime
574              * tick periods.  -1 is used because this code normally executes part
575              * way through the first tick period.  But if the SysTick IRQ is now
576              * pending, then clear the IRQ, suppressing the first tick, and correct
577              * the reload value to reflect that the second tick period is already
578              * underway.  The expected idle time is always at least two ticks. */
579             ulReloadValue = ulSysTickDecrementsLeft + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
580
581             if( ( portNVIC_INT_CTRL_REG & portNVIC_PEND_SYSTICK_SET_BIT ) != 0 )
582             {
583                 portNVIC_INT_CTRL_REG = portNVIC_PEND_SYSTICK_CLEAR_BIT;
584                 ulReloadValue -= ulTimerCountsForOneTick;
585             }
586
587             if( ulReloadValue > ulStoppedTimerCompensation )
588             {
589                 ulReloadValue -= ulStoppedTimerCompensation;
590             }
591
592             /* Set the new reload value. */
593             portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
594
595             /* Clear the SysTick count flag and set the count value back to
596              * zero. */
597             portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
598
599             /* Restart SysTick. */
600             portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
601
602             /* Sleep until something happens.  configPRE_SLEEP_PROCESSING() can
603              * set its parameter to 0 to indicate that its implementation contains
604              * its own wait for interrupt or wait for event instruction, and so wfi
605              * should not be executed again.  However, the original expected idle
606              * time variable must remain unmodified, so a copy is taken. */
607             xModifiableIdleTime = xExpectedIdleTime;
608             configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
609
610             if( xModifiableIdleTime > 0 )
611             {
612                 __asm volatile ( "dsb" ::: "memory" );
613                 __asm volatile ( "wfi" );
614                 __asm volatile ( "isb" );
615             }
616
617             configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
618
619             /* Re-enable interrupts to allow the interrupt that brought the MCU
620              * out of sleep mode to execute immediately.  See comments above
621              * the cpsid instruction above. */
622             __asm volatile ( "cpsie i" ::: "memory" );
623             __asm volatile ( "dsb" );
624             __asm volatile ( "isb" );
625
626             /* Disable interrupts again because the clock is about to be stopped
627              * and interrupts that execute while the clock is stopped will increase
628              * any slippage between the time maintained by the RTOS and calendar
629              * time. */
630             __asm volatile ( "cpsid i" ::: "memory" );
631             __asm volatile ( "dsb" );
632             __asm volatile ( "isb" );
633
634             /* Disable the SysTick clock without reading the
635              * portNVIC_SYSTICK_CTRL_REG register to ensure the
636              * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set.  Again,
637              * the time the SysTick is stopped for is accounted for as best it can
638              * be, but using the tickless mode will inevitably result in some tiny
639              * drift of the time maintained by the kernel with respect to calendar
640              * time*/
641             portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT );
642
643             /* Determine whether the SysTick has already counted to zero. */
644             if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
645             {
646                 uint32_t ulCalculatedLoadValue;
647
648                 /* The tick interrupt ended the sleep (or is now pending), and
649                  * a new tick period has started.  Reset portNVIC_SYSTICK_LOAD_REG
650                  * with whatever remains of the new tick period. */
651                 ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
652
653                 /* Don't allow a tiny value, or values that have somehow
654                  * underflowed because the post sleep hook did something
655                  * that took too long or because the SysTick current-value register
656                  * is zero. */
657                 if( ( ulCalculatedLoadValue <= ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
658                 {
659                     ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
660                 }
661
662                 portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
663
664                 /* As the pending tick will be processed as soon as this
665                  * function exits, the tick value maintained by the tick is stepped
666                  * forward by one less than the time spent waiting. */
667                 ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
668             }
669             else
670             {
671                 /* Something other than the tick interrupt ended the sleep. */
672
673                 /* Use the SysTick current-value register to determine the
674                  * number of SysTick decrements remaining until the expected idle
675                  * time would have ended. */
676                 ulSysTickDecrementsLeft = portNVIC_SYSTICK_CURRENT_VALUE_REG;
677                 #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG != portNVIC_SYSTICK_CLK_BIT )
678                 {
679                     /* If the SysTick is not using the core clock, the current-
680                      * value register might still be zero here.  In that case, the
681                      * SysTick didn't load from the reload register, and there are
682                      * ulReloadValue decrements remaining in the expected idle
683                      * time, not zero. */
684                     if( ulSysTickDecrementsLeft == 0 )
685                     {
686                         ulSysTickDecrementsLeft = ulReloadValue;
687                     }
688                 }
689                 #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */
690
691                 /* Work out how long the sleep lasted rounded to complete tick
692                  * periods (not the ulReload value which accounted for part
693                  * ticks). */
694                 ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - ulSysTickDecrementsLeft;
695
696                 /* How many complete tick periods passed while the processor
697                  * was waiting? */
698                 ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
699
700                 /* The reload value is set to whatever fraction of a single tick
701                  * period remains. */
702                 portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
703             }
704
705             /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again,
706              * then set portNVIC_SYSTICK_LOAD_REG back to its standard value.  If
707              * the SysTick is not using the core clock, temporarily configure it to
708              * use the core clock.  This configuration forces the SysTick to load
709              * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next
710              * cycle of the other clock.  Then portNVIC_SYSTICK_LOAD_REG is ready
711              * to receive the standard value immediately. */
712             portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
713             portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
714             #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT )
715             {
716                 portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
717             }
718             #else
719             {
720                 /* The temporary usage of the core clock has served its purpose,
721                  * as described above.  Resume usage of the other clock. */
722                 portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
723
724                 if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
725                 {
726                     /* The partial tick period already ended.  Be sure the SysTick
727                      * counts it only once. */
728                     portNVIC_SYSTICK_CURRENT_VALUE_REG = 0;
729                 }
730
731                 portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
732                 portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
733             }
734             #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */
735
736             /* Step the tick to account for any tick periods that elapsed. */
737             vTaskStepTick( ulCompleteTickPeriods );
738
739             /* Exit with interrupts enabled. */
740             __asm volatile ( "cpsie i" ::: "memory" );
741         }
742     }
743 #endif /* configUSE_TICKLESS_IDLE */
744 /*-----------------------------------------------------------*/
745
746 __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
747 {
748     /* Calculate the constants required to configure the tick interrupt. */
749     #if ( configUSE_TICKLESS_IDLE == 1 )
750     {
751         ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
752         xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
753         ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
754     }
755     #endif /* configUSE_TICKLESS_IDLE */
756
757     /* Stop and reset SysTick.
758      *
759      * QEMU versions older than 7.0.0 contain a bug which causes an error if we
760      * enable SysTick without first selecting a valid clock source. We trigger
761      * the bug if we change clock sources from a clock with a zero clock period
762      * to one with a nonzero clock period and enable Systick at the same time.
763      * So we configure the CLKSOURCE bit here, prior to setting the ENABLE bit.
764      * This workaround avoids the bug in QEMU versions older than 7.0.0. */
765     portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG;
766     portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
767
768     /* Configure SysTick to interrupt at the requested rate. */
769     portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
770     portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
771 }
772 /*-----------------------------------------------------------*/
773
774 static void prvTaskExitError( void )
775 {
776     volatile uint32_t ulDummy = 0UL;
777
778     /* A function that implements a task must not exit or attempt to return to
779      * its caller as there is nothing to return to. If a task wants to exit it
780      * should instead call vTaskDelete( NULL ). Artificially force an assert()
781      * to be triggered if configASSERT() is defined, then stop here so
782      * application writers can catch the error. */
783     configASSERT( ulCriticalNesting == ~0UL );
784     portDISABLE_INTERRUPTS();
785
786     while( ulDummy == 0 )
787     {
788         /* This file calls prvTaskExitError() after the scheduler has been
789          * started to remove a compiler warning about the function being
790          * defined but never called.  ulDummy is used purely to quieten other
791          * warnings about code appearing after this function is called - making
792          * ulDummy volatile makes the compiler think the function could return
793          * and therefore not output an 'unreachable code' warning for code that
794          * appears after it. */
795     }
796 }
797 /*-----------------------------------------------------------*/
798
799 #if ( configENABLE_MPU == 1 )
800     static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) /* PRIVILEGED_FUNCTION */
801     {
802         uint32_t ulAccessPermissions = 0;
803
804         if( ( ulRBARValue & portMPU_RBAR_ACCESS_PERMISSIONS_MASK ) == portMPU_REGION_READ_ONLY )
805         {
806             ulAccessPermissions = tskMPU_READ_PERMISSION;
807         }
808
809         if( ( ulRBARValue & portMPU_RBAR_ACCESS_PERMISSIONS_MASK ) == portMPU_REGION_READ_WRITE )
810         {
811             ulAccessPermissions = ( tskMPU_READ_PERMISSION | tskMPU_WRITE_PERMISSION );
812         }
813
814         return ulAccessPermissions;
815     }
816 #endif /* configENABLE_MPU */
817 /*-----------------------------------------------------------*/
818
819 #if ( configENABLE_MPU == 1 )
820     static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */
821     {
822         #if defined( __ARMCC_VERSION )
823
824             /* Declaration when these variable are defined in code instead of being
825              * exported from linker scripts. */
826             extern uint32_t * __privileged_functions_start__;
827             extern uint32_t * __privileged_functions_end__;
828             extern uint32_t * __syscalls_flash_start__;
829             extern uint32_t * __syscalls_flash_end__;
830             extern uint32_t * __unprivileged_flash_start__;
831             extern uint32_t * __unprivileged_flash_end__;
832             extern uint32_t * __privileged_sram_start__;
833             extern uint32_t * __privileged_sram_end__;
834         #else /* if defined( __ARMCC_VERSION ) */
835             /* Declaration when these variable are exported from linker scripts. */
836             extern uint32_t __privileged_functions_start__[];
837             extern uint32_t __privileged_functions_end__[];
838             extern uint32_t __syscalls_flash_start__[];
839             extern uint32_t __syscalls_flash_end__[];
840             extern uint32_t __unprivileged_flash_start__[];
841             extern uint32_t __unprivileged_flash_end__[];
842             extern uint32_t __privileged_sram_start__[];
843             extern uint32_t __privileged_sram_end__[];
844         #endif /* defined( __ARMCC_VERSION ) */
845
846         /* The only permitted number of regions are 8 or 16. */
847         configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
848
849         /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
850         configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
851
852         /* Check that the MPU is present. */
853         if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
854         {
855             /* MAIR0 - Index 0. */
856             portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
857             /* MAIR0 - Index 1. */
858             portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
859
860             /* Setup privileged flash as Read Only so that privileged tasks can
861              * read it but not modify. */
862             portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
863             portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
864                                ( portMPU_REGION_NON_SHAREABLE ) |
865                                ( portMPU_REGION_PRIVILEGED_READ_ONLY );
866             portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
867                                ( portMPU_RLAR_ATTR_INDEX0 ) |
868                                ( portMPU_RLAR_REGION_ENABLE );
869
870             /* Setup unprivileged flash as Read Only by both privileged and
871              * unprivileged tasks. All tasks can read it but no-one can modify. */
872             portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
873             portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
874                                ( portMPU_REGION_NON_SHAREABLE ) |
875                                ( portMPU_REGION_READ_ONLY );
876             portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
877                                ( portMPU_RLAR_ATTR_INDEX0 ) |
878                                ( portMPU_RLAR_REGION_ENABLE );
879
880             /* Setup unprivileged syscalls flash as Read Only by both privileged
881              * and unprivileged tasks. All tasks can read it but no-one can modify. */
882             portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
883             portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
884                                ( portMPU_REGION_NON_SHAREABLE ) |
885                                ( portMPU_REGION_READ_ONLY );
886             portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
887                                ( portMPU_RLAR_ATTR_INDEX0 ) |
888                                ( portMPU_RLAR_REGION_ENABLE );
889
890             /* Setup RAM containing kernel data for privileged access only. */
891             portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
892             portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
893                                ( portMPU_REGION_NON_SHAREABLE ) |
894                                ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
895                                ( portMPU_REGION_EXECUTE_NEVER );
896             portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
897                                ( portMPU_RLAR_ATTR_INDEX0 ) |
898                                ( portMPU_RLAR_REGION_ENABLE );
899
900             /* Enable mem fault. */
901             portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
902
903             /* Enable MPU with privileged background access i.e. unmapped
904              * regions have privileged access. */
905             portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
906         }
907     }
908 #endif /* configENABLE_MPU */
909 /*-----------------------------------------------------------*/
910
911 #if ( configENABLE_FPU == 1 )
912     static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */
913     {
914         #if ( configENABLE_TRUSTZONE == 1 )
915         {
916             /* Enable non-secure access to the FPU. */
917             SecureInit_EnableNSFPUAccess();
918         }
919         #endif /* configENABLE_TRUSTZONE */
920
921         /* CP10 = 11 ==> Full access to FPU i.e. both privileged and
922          * unprivileged code should be able to access FPU. CP11 should be
923          * programmed to the same value as CP10. */
924         *( portCPACR ) |= ( ( portCPACR_CP10_VALUE << portCPACR_CP10_POS ) |
925                             ( portCPACR_CP11_VALUE << portCPACR_CP11_POS )
926                             );
927
928         /* ASPEN = 1 ==> Hardware should automatically preserve floating point
929          * context on exception entry and restore on exception return.
930          * LSPEN = 1 ==> Enable lazy context save of FP state. */
931         *( portFPCCR ) |= ( portFPCCR_ASPEN_MASK | portFPCCR_LSPEN_MASK );
932     }
933 #endif /* configENABLE_FPU */
934 /*-----------------------------------------------------------*/
935
936 void vPortYield( void ) /* PRIVILEGED_FUNCTION */
937 {
938     /* Set a PendSV to request a context switch. */
939     portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
940
941     /* Barriers are normally not required but do ensure the code is
942      * completely within the specified behaviour for the architecture. */
943     __asm volatile ( "dsb" ::: "memory" );
944     __asm volatile ( "isb" );
945 }
946 /*-----------------------------------------------------------*/
947
948 void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
949 {
950     portDISABLE_INTERRUPTS();
951     ulCriticalNesting++;
952
953     /* Barriers are normally not required but do ensure the code is
954      * completely within the specified behaviour for the architecture. */
955     __asm volatile ( "dsb" ::: "memory" );
956     __asm volatile ( "isb" );
957 }
958 /*-----------------------------------------------------------*/
959
960 void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
961 {
962     configASSERT( ulCriticalNesting );
963     ulCriticalNesting--;
964
965     if( ulCriticalNesting == 0 )
966     {
967         portENABLE_INTERRUPTS();
968     }
969 }
970 /*-----------------------------------------------------------*/
971
972 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
973 {
974     uint32_t ulPreviousMask;
975
976     ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
977     {
978         /* Increment the RTOS tick. */
979         if( xTaskIncrementTick() != pdFALSE )
980         {
981             /* Pend a context switch. */
982             portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
983         }
984     }
985     portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
986 }
987 /*-----------------------------------------------------------*/
988
989 void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */
990 {
991     #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
992         #if defined( __ARMCC_VERSION )
993
994             /* Declaration when these variable are defined in code instead of being
995              * exported from linker scripts. */
996             extern uint32_t * __syscalls_flash_start__;
997             extern uint32_t * __syscalls_flash_end__;
998         #else
999             /* Declaration when these variable are exported from linker scripts. */
1000             extern uint32_t __syscalls_flash_start__[];
1001             extern uint32_t __syscalls_flash_end__[];
1002         #endif /* defined( __ARMCC_VERSION ) */
1003     #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
1004
1005     uint32_t ulPC;
1006
1007     #if ( configENABLE_TRUSTZONE == 1 )
1008         uint32_t ulR0, ulR1;
1009         extern TaskHandle_t pxCurrentTCB;
1010         #if ( configENABLE_MPU == 1 )
1011             uint32_t ulControl, ulIsTaskPrivileged;
1012         #endif /* configENABLE_MPU */
1013     #endif /* configENABLE_TRUSTZONE */
1014     uint8_t ucSVCNumber;
1015
1016     /* Register are stored on the stack in the following order - R0, R1, R2, R3,
1017      * R12, LR, PC, xPSR. */
1018     ulPC = pulCallerStackAddress[ portOFFSET_TO_PC ];
1019     ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];
1020
1021     switch( ucSVCNumber )
1022     {
1023         #if ( configENABLE_TRUSTZONE == 1 )
1024             case portSVC_ALLOCATE_SECURE_CONTEXT:
1025
1026                 /* R0 contains the stack size passed as parameter to the
1027                  * vPortAllocateSecureContext function. */
1028                 ulR0 = pulCallerStackAddress[ 0 ];
1029
1030                 #if ( configENABLE_MPU == 1 )
1031                 {
1032                     /* Read the CONTROL register value. */
1033                     __asm volatile ( "mrs %0, control"  : "=r" ( ulControl ) );
1034
1035                     /* The task that raised the SVC is privileged if Bit[0]
1036                      * in the CONTROL register is 0. */
1037                     ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
1038
1039                     /* Allocate and load a context for the secure task. */
1040                     xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
1041                 }
1042                 #else /* if ( configENABLE_MPU == 1 ) */
1043                 {
1044                     /* Allocate and load a context for the secure task. */
1045                     xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
1046                 }
1047                 #endif /* configENABLE_MPU */
1048
1049                 configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
1050                 SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
1051                 break;
1052
1053             case portSVC_FREE_SECURE_CONTEXT:
1054
1055                 /* R0 contains TCB being freed and R1 contains the secure
1056                  * context handle to be freed. */
1057                 ulR0 = pulCallerStackAddress[ 0 ];
1058                 ulR1 = pulCallerStackAddress[ 1 ];
1059
1060                 /* Free the secure context. */
1061                 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
1062                 break;
1063         #endif /* configENABLE_TRUSTZONE */
1064
1065         case portSVC_START_SCHEDULER:
1066             #if ( configENABLE_TRUSTZONE == 1 )
1067             {
1068                 /* De-prioritize the non-secure exceptions so that the
1069                  * non-secure pendSV runs at the lowest priority. */
1070                 SecureInit_DePrioritizeNSExceptions();
1071
1072                 /* Initialize the secure context management system. */
1073                 SecureContext_Init();
1074             }
1075             #endif /* configENABLE_TRUSTZONE */
1076
1077             #if ( configENABLE_FPU == 1 )
1078             {
1079                 /* Setup the Floating Point Unit (FPU). */
1080                 prvSetupFPU();
1081             }
1082             #endif /* configENABLE_FPU */
1083
1084             /* Setup the context of the first task so that the first task starts
1085              * executing. */
1086             vRestoreContextOfFirstTask();
1087             break;
1088
1089         #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
1090             case portSVC_RAISE_PRIVILEGE:
1091
1092                 /* Only raise the privilege, if the svc was raised from any of
1093                  * the system calls. */
1094                 if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
1095                     ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
1096                 {
1097                     vRaisePrivilege();
1098                 }
1099                 break;
1100         #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
1101
1102         default:
1103             /* Incorrect SVC call. */
1104             configASSERT( pdFALSE );
1105     }
1106 }
1107 /*-----------------------------------------------------------*/
1108
1109 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
1110
1111 void vSystemCallEnter( uint32_t * pulTaskStack, uint32_t ulLR ) /* PRIVILEGED_FUNCTION */
1112 {
1113     extern TaskHandle_t pxCurrentTCB;
1114     xMPU_SETTINGS * pxMpuSettings;
1115     uint32_t * pulSystemCallStack;
1116     uint32_t ulStackFrameSize, ulSystemCallLocation, i;
1117     #if defined( __ARMCC_VERSION )
1118         /* Declaration when these variable are defined in code instead of being
1119          * exported from linker scripts. */
1120         extern uint32_t * __syscalls_flash_start__;
1121         extern uint32_t * __syscalls_flash_end__;
1122     #else
1123         /* Declaration when these variable are exported from linker scripts. */
1124         extern uint32_t __syscalls_flash_start__[];
1125         extern uint32_t __syscalls_flash_end__[];
1126     #endif /* #if defined( __ARMCC_VERSION ) */
1127
1128     ulSystemCallLocation = pulTaskStack[ portOFFSET_TO_PC ];
1129
1130     /* If the request did not come from the system call section, do nothing. */
1131     if( ( ulSystemCallLocation >= ( uint32_t ) __syscalls_flash_start__ ) &&
1132         ( ulSystemCallLocation <= ( uint32_t ) __syscalls_flash_end__ ) )
1133     {
1134         pxMpuSettings = xTaskGetMPUSettings( pxCurrentTCB );
1135         pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
1136
1137         /* This is not NULL only for the duration of the system call. */
1138         configASSERT( pxMpuSettings->xSystemCallStackInfo.pulTaskStack == NULL );
1139
1140         #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
1141         {
1142             if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
1143             {
1144                 /* Extended frame i.e. FPU in use. */
1145                 ulStackFrameSize = 26;
1146                 __asm volatile (
1147                                     " vpush {s0}         \n" /* Trigger lazy stacking. */
1148                                     " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
1149                                     ::: "memory"
1150                             );
1151             }
1152             else
1153             {
1154                 /* Standard frame i.e. FPU not in use. */
1155                 ulStackFrameSize = 8;
1156             }
1157         }
1158         #else
1159         {
1160             ulStackFrameSize = 8;
1161         }
1162         #endif /* configENABLE_FPU || configENABLE_MVE */
1163
1164         /* Make space on the system call stack for the stack frame. */
1165         pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
1166
1167         /* Copy the stack frame. */
1168         for( i = 0; i < ulStackFrameSize; i++ )
1169         {
1170             pulSystemCallStack[ i ] = pulTaskStack[ i ];
1171         }
1172
1173         /* Store the value of the LR and PSPLIM registers before the SVC was raised. We need to
1174          * restore it when we exit from the system call. */
1175         pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
1176         __asm volatile ( "mrs %0, psplim" : "=r" ( pxMpuSettings->xSystemCallStackInfo.ulStackLimitRegisterAtSystemCallEntry ) );
1177
1178         /* Use the pulSystemCallStack in thread mode. */
1179         __asm volatile ( "msr psp, %0" : : "r" ( pulSystemCallStack ) );
1180         __asm volatile ( "msr psplim, %0" : : "r" ( pxMpuSettings->xSystemCallStackInfo.pulSystemCallStackLimit ) );
1181
1182         /* Remember the location where we should copy the stack frame when we exit from
1183          * the system call. */
1184         pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
1185
1186         /* Record if the hardware used padding to force the stack pointer
1187          * to be double word aligned. */
1188         if( ( pulTaskStack[ portOFFSET_TO_PSR ] & portPSR_STACK_PADDING_MASK ) == portPSR_STACK_PADDING_MASK )
1189         {
1190             pxMpuSettings->ulTaskFlags |= portSTACK_FRAME_HAS_PADDING_FLAG;
1191         }
1192         else
1193         {
1194             pxMpuSettings->ulTaskFlags &= ( ~portSTACK_FRAME_HAS_PADDING_FLAG );
1195         }
1196
1197         /* We ensure in pxPortInitialiseStack that the system call stack is
1198          * double word aligned and therefore, there is no need of padding.
1199          * Clear the bit[9] of stacked xPSR. */
1200         pulSystemCallStack[ portOFFSET_TO_PSR ] &= ( ~portPSR_STACK_PADDING_MASK );
1201
1202         /* Raise the privilege for the duration of the system call. */
1203         __asm volatile (
1204                             " mrs r0, control     \n" /* Obtain current control value. */
1205                             " movs r1, #1         \n" /* r1 = 1. */
1206                             " bics r0, r1         \n" /* Clear nPRIV bit. */
1207                             " msr control, r0     \n" /* Write back new control value. */
1208                             ::: "r0", "r1", "memory"
1209                         );
1210     }
1211 }
1212
1213 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
1214 /*-----------------------------------------------------------*/
1215
1216 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
1217
1218 void vSystemCallEnter_1( uint32_t * pulTaskStack, uint32_t ulLR ) /* PRIVILEGED_FUNCTION */
1219 {
1220     extern TaskHandle_t pxCurrentTCB;
1221     xMPU_SETTINGS * pxMpuSettings;
1222     uint32_t * pulSystemCallStack;
1223     uint32_t ulStackFrameSize, ulSystemCallLocation, i;
1224     #if defined( __ARMCC_VERSION )
1225         /* Declaration when these variable are defined in code instead of being
1226          * exported from linker scripts. */
1227         extern uint32_t * __syscalls_flash_start__;
1228         extern uint32_t * __syscalls_flash_end__;
1229     #else
1230         /* Declaration when these variable are exported from linker scripts. */
1231         extern uint32_t __syscalls_flash_start__[];
1232         extern uint32_t __syscalls_flash_end__[];
1233     #endif /* #if defined( __ARMCC_VERSION ) */
1234
1235     ulSystemCallLocation = pulTaskStack[ portOFFSET_TO_PC ];
1236
1237     /* If the request did not come from the system call section, do nothing. */
1238     if( ( ulSystemCallLocation >= ( uint32_t ) __syscalls_flash_start__ ) &&
1239         ( ulSystemCallLocation <= ( uint32_t ) __syscalls_flash_end__ ) )
1240     {
1241         pxMpuSettings = xTaskGetMPUSettings( pxCurrentTCB );
1242         pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
1243
1244         /* This is not NULL only for the duration of the system call. */
1245         configASSERT( pxMpuSettings->xSystemCallStackInfo.pulTaskStack == NULL );
1246
1247         #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
1248         {
1249             if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
1250             {
1251                 /* Extended frame i.e. FPU in use. */
1252                 ulStackFrameSize = 26;
1253                 __asm volatile (
1254                                     " vpush {s0}         \n" /* Trigger lazy stacking. */
1255                                     " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
1256                                     ::: "memory"
1257                             );
1258             }
1259             else
1260             {
1261                 /* Standard frame i.e. FPU not in use. */
1262                 ulStackFrameSize = 8;
1263             }
1264         }
1265         #else
1266         {
1267             ulStackFrameSize = 8;
1268         }
1269         #endif /* configENABLE_FPU || configENABLE_MVE */
1270
1271         /* Make space on the system call stack for the stack frame and
1272          * the parameter passed on the stack. We only need to copy one
1273          * parameter but we still reserve 2 spaces to keep the stack
1274          * double word aligned. */
1275         pulSystemCallStack = pulSystemCallStack - ulStackFrameSize - 2UL;
1276
1277         /* Copy the stack frame. */
1278         for( i = 0; i < ulStackFrameSize; i++ )
1279         {
1280             pulSystemCallStack[ i ] = pulTaskStack[ i ];
1281         }
1282
1283         /* Copy the parameter which is passed the stack. */
1284         if( ( pulTaskStack[ portOFFSET_TO_PSR ] & portPSR_STACK_PADDING_MASK ) == portPSR_STACK_PADDING_MASK )
1285         {
1286             pulSystemCallStack[ ulStackFrameSize ] = pulTaskStack[ ulStackFrameSize + 1 ];
1287             /* Record if the hardware used padding to force the stack pointer
1288              * to be double word aligned. */
1289             pxMpuSettings->ulTaskFlags |= portSTACK_FRAME_HAS_PADDING_FLAG;
1290         }
1291         else
1292         {
1293             pulSystemCallStack[ ulStackFrameSize ] = pulTaskStack[ ulStackFrameSize ];
1294             /* Record if the hardware used padding to force the stack pointer
1295              * to be double word aligned. */
1296             pxMpuSettings->ulTaskFlags &= ( ~portSTACK_FRAME_HAS_PADDING_FLAG );
1297         }
1298
1299         /* Store the value of the LR and PSPLIM registers before the SVC was raised.
1300          * We need to restore it when we exit from the system call. */
1301         pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
1302         __asm volatile ( "mrs %0, psplim" : "=r" ( pxMpuSettings->xSystemCallStackInfo.ulStackLimitRegisterAtSystemCallEntry ) );
1303
1304         /* Use the pulSystemCallStack in thread mode. */
1305         __asm volatile ( "msr psp, %0" : : "r" ( pulSystemCallStack ) );
1306         __asm volatile ( "msr psplim, %0" : : "r" ( pxMpuSettings->xSystemCallStackInfo.pulSystemCallStackLimit ) );
1307
1308         /* Remember the location where we should copy the stack frame when we exit from
1309          * the system call. */
1310         pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
1311
1312         /* We ensure in pxPortInitialiseStack that the system call stack is
1313          * double word aligned and therefore, there is no need of padding.
1314          * Clear the bit[9] of stacked xPSR. */
1315         pulSystemCallStack[ portOFFSET_TO_PSR ] &= ( ~portPSR_STACK_PADDING_MASK );
1316
1317         /* Raise the privilege for the duration of the system call. */
1318         __asm volatile (
1319                             " mrs r0, control     \n" /* Obtain current control value. */
1320                             " movs r1, #1         \n" /* r1 = 1. */
1321                             " bics r0, r1         \n" /* Clear nPRIV bit. */
1322                             " msr control, r0     \n" /* Write back new control value. */
1323                             ::: "r0", "r1", "memory"
1324                         );
1325     }
1326 }
1327
1328 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
1329 /*-----------------------------------------------------------*/
1330
1331 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
1332
1333 void vSystemCallExit( uint32_t * pulSystemCallStack, uint32_t ulLR ) /* PRIVILEGED_FUNCTION */
1334 {
1335     extern TaskHandle_t pxCurrentTCB;
1336     xMPU_SETTINGS * pxMpuSettings;
1337     uint32_t * pulTaskStack;
1338     uint32_t ulStackFrameSize, ulSystemCallLocation, i;
1339     #if defined( __ARMCC_VERSION )
1340         /* Declaration when these variable are defined in code instead of being
1341          * exported from linker scripts. */
1342         extern uint32_t * __syscalls_flash_start__;
1343         extern uint32_t * __syscalls_flash_end__;
1344     #else
1345         /* Declaration when these variable are exported from linker scripts. */
1346         extern uint32_t __syscalls_flash_start__[];
1347         extern uint32_t __syscalls_flash_end__[];
1348     #endif /* #if defined( __ARMCC_VERSION ) */
1349
1350     ulSystemCallLocation = pulSystemCallStack[ portOFFSET_TO_PC ];
1351
1352     /* If the request did not come from the system call section, do nothing. */
1353     if( ( ulSystemCallLocation >= ( uint32_t ) __syscalls_flash_start__ ) &&
1354         ( ulSystemCallLocation <= ( uint32_t ) __syscalls_flash_end__ ) )
1355     {
1356         pxMpuSettings = xTaskGetMPUSettings( pxCurrentTCB );
1357         pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
1358
1359         #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
1360         {
1361             if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
1362             {
1363                 /* Extended frame i.e. FPU in use. */
1364                 ulStackFrameSize = 26;
1365                 __asm volatile (
1366                                     " vpush {s0}         \n" /* Trigger lazy stacking. */
1367                                     " vpop  {s0}         \n" /* Nullify the affect of the above instruction. */
1368                                     ::: "memory"
1369                             );
1370             }
1371             else
1372             {
1373                 /* Standard frame i.e. FPU not in use. */
1374                 ulStackFrameSize = 8;
1375             }
1376         }
1377         #else
1378         {
1379             ulStackFrameSize = 8;
1380         }
1381         #endif /* configENABLE_FPU || configENABLE_MVE */
1382
1383         /* Make space on the task stack for the stack frame. */
1384         pulTaskStack = pulTaskStack - ulStackFrameSize;
1385
1386         /* Copy the stack frame. */
1387         for( i = 0; i < ulStackFrameSize; i++ )
1388         {
1389             pulTaskStack[ i ] = pulSystemCallStack[ i ];
1390         }
1391
1392         /* Use the pulTaskStack in thread mode. */
1393         __asm volatile ( "msr psp, %0" : : "r" ( pulTaskStack ) );
1394
1395         /* Restore the LR and PSPLIM to what they were at the time of
1396          * system call entry. */
1397         pulTaskStack[ portOFFSET_TO_LR ] = pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry;
1398         __asm volatile ( "msr psplim, %0" : : "r" ( pxMpuSettings->xSystemCallStackInfo.ulStackLimitRegisterAtSystemCallEntry ) );
1399
1400         /* If the hardware used padding to force the stack pointer
1401          * to be double word aligned, set the stacked xPSR bit[9],
1402          * otherwise clear it. */
1403         if( ( pxMpuSettings->ulTaskFlags & portSTACK_FRAME_HAS_PADDING_FLAG ) == portSTACK_FRAME_HAS_PADDING_FLAG )
1404         {
1405             pulTaskStack[ portOFFSET_TO_PSR ] |= portPSR_STACK_PADDING_MASK;
1406         }
1407         else
1408         {
1409             pulTaskStack[ portOFFSET_TO_PSR ] &= ( ~portPSR_STACK_PADDING_MASK );
1410         }
1411
1412         /* This is not NULL only for the duration of the system call. */
1413         pxMpuSettings->xSystemCallStackInfo.pulTaskStack = NULL;
1414
1415         /* Drop the privilege before returning to the thread mode. */
1416         __asm volatile (
1417                             " mrs r0, control     \n" /* Obtain current control value. */
1418                             " movs r1, #1         \n" /* r1 = 1. */
1419                             " orrs r0, r1         \n" /* Set nPRIV bit. */
1420                             " msr control, r0     \n" /* Write back new control value. */
1421                             ::: "r0", "r1", "memory"
1422                         );
1423     }
1424 }
1425
1426 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
1427 /*-----------------------------------------------------------*/
1428
1429 #if ( configENABLE_MPU == 1 )
1430
1431 BaseType_t xPortIsTaskPrivileged( void ) /* PRIVILEGED_FUNCTION */
1432 {
1433     BaseType_t xTaskIsPrivileged = pdFALSE;
1434     const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
1435
1436     if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
1437     {
1438         xTaskIsPrivileged = pdTRUE;
1439     }
1440
1441     return xTaskIsPrivileged;
1442 }
1443
1444 #endif /* configENABLE_MPU == 1 */
1445 /*-----------------------------------------------------------*/
1446
1447 #if( configENABLE_MPU == 1 )
1448
1449 StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
1450                                      StackType_t * pxEndOfStack,
1451                                      TaskFunction_t pxCode,
1452                                      void * pvParameters,
1453                                      BaseType_t xRunPrivileged,
1454                                      xMPU_SETTINGS * xMPUSettings ) /* PRIVILEGED_FUNCTION */
1455 {
1456     uint32_t ulIndex = 0;
1457
1458     xMPUSettings->ulContext[ ulIndex ] = 0x04040404; /* r4. */
1459     ulIndex++;
1460     xMPUSettings->ulContext[ ulIndex ] = 0x05050505; /* r5. */
1461     ulIndex++;
1462     xMPUSettings->ulContext[ ulIndex ] = 0x06060606; /* r6. */
1463     ulIndex++;
1464     xMPUSettings->ulContext[ ulIndex ] = 0x07070707; /* r7. */
1465     ulIndex++;
1466     xMPUSettings->ulContext[ ulIndex ] = 0x08080808; /* r8. */
1467     ulIndex++;
1468     xMPUSettings->ulContext[ ulIndex ] = 0x09090909; /* r9. */
1469     ulIndex++;
1470     xMPUSettings->ulContext[ ulIndex ] = 0x10101010; /* r10. */
1471     ulIndex++;
1472     xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
1473     ulIndex++;
1474
1475     xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
1476     ulIndex++;
1477     xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
1478     ulIndex++;
1479     xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
1480     ulIndex++;
1481     xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
1482     ulIndex++;
1483     xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
1484     ulIndex++;
1485     xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
1486     ulIndex++;
1487     xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
1488     ulIndex++;
1489     xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
1490     ulIndex++;
1491
1492     #if ( configENABLE_TRUSTZONE == 1 )
1493     {
1494         xMPUSettings->ulContext[ ulIndex ] = portNO_SECURE_CONTEXT;  /* xSecureContext. */
1495         ulIndex++;
1496     }
1497     #endif /* configENABLE_TRUSTZONE */
1498     xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
1499     ulIndex++;
1500     xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
1501     ulIndex++;
1502     if( xRunPrivileged == pdTRUE )
1503     {
1504         xMPUSettings->ulTaskFlags |= portTASK_IS_PRIVILEGED_FLAG;
1505         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portINITIAL_CONTROL_PRIVILEGED; /* CONTROL. */
1506         ulIndex++;
1507     }
1508     else
1509     {
1510         xMPUSettings->ulTaskFlags &= ( ~portTASK_IS_PRIVILEGED_FLAG );
1511         xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portINITIAL_CONTROL_UNPRIVILEGED; /* CONTROL. */
1512         ulIndex++;
1513     }
1514     xMPUSettings->ulContext[ ulIndex ] = portINITIAL_EXC_RETURN; /* LR (EXC_RETURN). */
1515     ulIndex++;
1516
1517     #if ( configUSE_MPU_WRAPPERS_V1 == 0 )
1518     {
1519         /* Ensure that the system call stack is double word aligned. */
1520         xMPUSettings->xSystemCallStackInfo.pulSystemCallStack = &( xMPUSettings->xSystemCallStackInfo.ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE - 1 ] );
1521         xMPUSettings->xSystemCallStackInfo.pulSystemCallStack = ( uint32_t * ) ( ( uint32_t ) ( xMPUSettings->xSystemCallStackInfo.pulSystemCallStack ) &
1522                                                                                  ( uint32_t ) ( ~( portBYTE_ALIGNMENT_MASK ) ) );
1523
1524         xMPUSettings->xSystemCallStackInfo.pulSystemCallStackLimit = &( xMPUSettings->xSystemCallStackInfo.ulSystemCallStackBuffer[ 0 ] );
1525         xMPUSettings->xSystemCallStackInfo.pulSystemCallStackLimit = ( uint32_t * ) ( ( ( uint32_t ) ( xMPUSettings->xSystemCallStackInfo.pulSystemCallStackLimit ) +
1526                                                                                         ( uint32_t ) ( portBYTE_ALIGNMENT - 1 ) ) &
1527                                                                                       ( uint32_t ) ( ~( portBYTE_ALIGNMENT_MASK ) ) );
1528
1529         /* This is not NULL only for the duration of a system call. */
1530         xMPUSettings->xSystemCallStackInfo.pulTaskStack = NULL;
1531     }
1532     #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
1533
1534     return &( xMPUSettings->ulContext[ ulIndex ] );
1535 }
1536
1537 #else /* configENABLE_MPU */
1538
1539 StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
1540                                      StackType_t * pxEndOfStack,
1541                                      TaskFunction_t pxCode,
1542                                      void * pvParameters ) /* PRIVILEGED_FUNCTION */
1543 {
1544     /* Simulate the stack frame as it would be created by a context switch
1545      * interrupt. */
1546     #if ( portPRELOAD_REGISTERS == 0 )
1547     {
1548         pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
1549         *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
1550         pxTopOfStack--;
1551         *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
1552         pxTopOfStack--;
1553         *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
1554         pxTopOfStack -= 5;                                       /* R12, R3, R2 and R1. */
1555         *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
1556         pxTopOfStack -= 9;                                       /* R11..R4, EXC_RETURN. */
1557         *pxTopOfStack = portINITIAL_EXC_RETURN;
1558         pxTopOfStack--;
1559         *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
1560
1561         #if ( configENABLE_TRUSTZONE == 1 )
1562         {
1563             pxTopOfStack--;
1564             *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
1565         }
1566         #endif /* configENABLE_TRUSTZONE */
1567     }
1568     #else /* portPRELOAD_REGISTERS */
1569     {
1570         pxTopOfStack--;                                          /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
1571         *pxTopOfStack = portINITIAL_XPSR;                        /* xPSR. */
1572         pxTopOfStack--;
1573         *pxTopOfStack = ( StackType_t ) pxCode;                  /* PC. */
1574         pxTopOfStack--;
1575         *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
1576         pxTopOfStack--;
1577         *pxTopOfStack = ( StackType_t ) 0x12121212UL;            /* R12. */
1578         pxTopOfStack--;
1579         *pxTopOfStack = ( StackType_t ) 0x03030303UL;            /* R3. */
1580         pxTopOfStack--;
1581         *pxTopOfStack = ( StackType_t ) 0x02020202UL;            /* R2. */
1582         pxTopOfStack--;
1583         *pxTopOfStack = ( StackType_t ) 0x01010101UL;            /* R1. */
1584         pxTopOfStack--;
1585         *pxTopOfStack = ( StackType_t ) pvParameters;            /* R0. */
1586         pxTopOfStack--;
1587         *pxTopOfStack = ( StackType_t ) 0x11111111UL;            /* R11. */
1588         pxTopOfStack--;
1589         *pxTopOfStack = ( StackType_t ) 0x10101010UL;            /* R10. */
1590         pxTopOfStack--;
1591         *pxTopOfStack = ( StackType_t ) 0x09090909UL;            /* R09. */
1592         pxTopOfStack--;
1593         *pxTopOfStack = ( StackType_t ) 0x08080808UL;            /* R08. */
1594         pxTopOfStack--;
1595         *pxTopOfStack = ( StackType_t ) 0x07070707UL;            /* R07. */
1596         pxTopOfStack--;
1597         *pxTopOfStack = ( StackType_t ) 0x06060606UL;            /* R06. */
1598         pxTopOfStack--;
1599         *pxTopOfStack = ( StackType_t ) 0x05050505UL;            /* R05. */
1600         pxTopOfStack--;
1601         *pxTopOfStack = ( StackType_t ) 0x04040404UL;            /* R04. */
1602         pxTopOfStack--;
1603         *pxTopOfStack = portINITIAL_EXC_RETURN;                  /* EXC_RETURN. */
1604         pxTopOfStack--;
1605         *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
1606
1607         #if ( configENABLE_TRUSTZONE == 1 )
1608         {
1609             pxTopOfStack--;
1610             *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
1611         }
1612         #endif /* configENABLE_TRUSTZONE */
1613     }
1614     #endif /* portPRELOAD_REGISTERS */
1615
1616     return pxTopOfStack;
1617 }
1618
1619 #endif /* configENABLE_MPU */
1620 /*-----------------------------------------------------------*/
1621
1622 BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
1623 {
1624     #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
1625     {
1626         volatile uint32_t ulOriginalPriority;
1627         volatile uint32_t ulImplementedPrioBits = 0;
1628         volatile uint8_t ucMaxPriorityValue;
1629
1630         /* Determine the maximum priority from which ISR safe FreeRTOS API
1631          * functions can be called.  ISR safe functions are those that end in
1632          * "FromISR".  FreeRTOS maintains separate thread and ISR API functions to
1633          * ensure interrupt entry is as fast and simple as possible.
1634          *
1635          * Save the interrupt priority value that is about to be clobbered. */
1636         ulOriginalPriority = portNVIC_SHPR2_REG;
1637
1638         /* Determine the number of priority bits available.  First write to all
1639          * possible bits. */
1640         portNVIC_SHPR2_REG = 0xFF000000;
1641
1642         /* Read the value back to see how many bits stuck. */
1643         ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
1644
1645         /* Use the same mask on the maximum system call priority. */
1646         ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
1647
1648         /* Check that the maximum system call priority is nonzero after
1649          * accounting for the number of priority bits supported by the
1650          * hardware. A priority of 0 is invalid because setting the BASEPRI
1651          * register to 0 unmasks all interrupts, and interrupts with priority 0
1652          * cannot be masked using BASEPRI.
1653          * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
1654         configASSERT( ucMaxSysCallPriority );
1655
1656         /* Check that the bits not implemented in hardware are zero in
1657          * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
1658         configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
1659
1660         /* Calculate the maximum acceptable priority group value for the number
1661          * of bits read back. */
1662
1663         while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
1664         {
1665             ulImplementedPrioBits++;
1666             ucMaxPriorityValue <<= ( uint8_t ) 0x01;
1667         }
1668
1669         if( ulImplementedPrioBits == 8 )
1670         {
1671             /* When the hardware implements 8 priority bits, there is no way for
1672              * the software to configure PRIGROUP to not have sub-priorities. As
1673              * a result, the least significant bit is always used for sub-priority
1674              * and there are 128 preemption priorities and 2 sub-priorities.
1675              *
1676              * This may cause some confusion in some cases - for example, if
1677              * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
1678              * priority interrupts will be masked in Critical Sections as those
1679              * are at the same preemption priority. This may appear confusing as
1680              * 4 is higher (numerically lower) priority than
1681              * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
1682              * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
1683              * to 4, this confusion does not happen and the behaviour remains the same.
1684              *
1685              * The following assert ensures that the sub-priority bit in the
1686              * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
1687              * confusion. */
1688             configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
1689             ulMaxPRIGROUPValue = 0;
1690         }
1691         else
1692         {
1693             ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
1694         }
1695
1696         /* Shift the priority group value back to its position within the AIRCR
1697          * register. */
1698         ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
1699         ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
1700
1701         /* Restore the clobbered interrupt priority register to its original
1702          * value. */
1703         portNVIC_SHPR2_REG = ulOriginalPriority;
1704     }
1705     #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
1706
1707     /* Make PendSV, CallSV and SysTick the same priority as the kernel. */
1708     portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
1709     portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
1710
1711     #if ( configENABLE_MPU == 1 )
1712     {
1713         /* Setup the Memory Protection Unit (MPU). */
1714         prvSetupMPU();
1715     }
1716     #endif /* configENABLE_MPU */
1717
1718     /* Start the timer that generates the tick ISR. Interrupts are disabled
1719      * here already. */
1720     vPortSetupTimerInterrupt();
1721
1722     /* Initialize the critical nesting count ready for the first task. */
1723     ulCriticalNesting = 0;
1724
1725     /* Start the first task. */
1726     vStartFirstTask();
1727
1728     /* Should never get here as the tasks will now be executing. Call the task
1729      * exit error function to prevent compiler warnings about a static function
1730      * not being called in the case that the application writer overrides this
1731      * functionality by defining configTASK_RETURN_ADDRESS. Call
1732      * vTaskSwitchContext() so link time optimization does not remove the
1733      * symbol. */
1734     vTaskSwitchContext();
1735     prvTaskExitError();
1736
1737     /* Should not get here. */
1738     return 0;
1739 }
1740 /*-----------------------------------------------------------*/
1741
1742 void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
1743 {
1744     /* Not implemented in ports where there is nothing to return to.
1745      * Artificially force an assert. */
1746     configASSERT( ulCriticalNesting == 1000UL );
1747 }
1748 /*-----------------------------------------------------------*/
1749
1750 #if ( configENABLE_MPU == 1 )
1751     void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
1752                                     const struct xMEMORY_REGION * const xRegions,
1753                                     StackType_t * pxBottomOfStack,
1754                                     uint32_t ulStackDepth )
1755     {
1756         uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
1757         int32_t lIndex = 0;
1758
1759         #if defined( __ARMCC_VERSION )
1760
1761             /* Declaration when these variable are defined in code instead of being
1762              * exported from linker scripts. */
1763             extern uint32_t * __privileged_sram_start__;
1764             extern uint32_t * __privileged_sram_end__;
1765         #else
1766             /* Declaration when these variable are exported from linker scripts. */
1767             extern uint32_t __privileged_sram_start__[];
1768             extern uint32_t __privileged_sram_end__[];
1769         #endif /* defined( __ARMCC_VERSION ) */
1770
1771         /* Setup MAIR0. */
1772         xMPUSettings->ulMAIR0 = ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
1773         xMPUSettings->ulMAIR0 |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
1774
1775         /* This function is called automatically when the task is created - in
1776          * which case the stack region parameters will be valid.  At all other
1777          * times the stack parameters will not be valid and it is assumed that
1778          * the stack region has already been configured. */
1779         if( ulStackDepth > 0 )
1780         {
1781             ulRegionStartAddress = ( uint32_t ) pxBottomOfStack;
1782             ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) - 1;
1783
1784             /* If the stack is within the privileged SRAM, do not protect it
1785              * using a separate MPU region. This is needed because privileged
1786              * SRAM is already protected using an MPU region and ARMv8-M does
1787              * not allow overlapping MPU regions. */
1788             if( ( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ ) &&
1789                 ( ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) )
1790             {
1791                 xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0;
1792                 xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0;
1793             }
1794             else
1795             {
1796                 /* Define the region that allows access to the stack. */
1797                 ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK;
1798                 ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
1799
1800                 xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) |
1801                                                              ( portMPU_REGION_NON_SHAREABLE ) |
1802                                                              ( portMPU_REGION_READ_WRITE ) |
1803                                                              ( portMPU_REGION_EXECUTE_NEVER );
1804
1805                 xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) |
1806                                                              ( portMPU_RLAR_ATTR_INDEX0 ) |
1807                                                              ( portMPU_RLAR_REGION_ENABLE );
1808             }
1809         }
1810
1811         /* User supplied configurable regions. */
1812         for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ )
1813         {
1814             /* If xRegions is NULL i.e. the task has not specified any MPU
1815              * region, the else part ensures that all the configurable MPU
1816              * regions are invalidated. */
1817             if( ( xRegions != NULL ) && ( xRegions[ lIndex ].ulLengthInBytes > 0UL ) )
1818             {
1819                 /* Translate the generic region definition contained in xRegions
1820                  * into the ARMv8 specific MPU settings that are then stored in
1821                  * xMPUSettings. */
1822                 ulRegionStartAddress = ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) & portMPU_RBAR_ADDRESS_MASK;
1823                 ulRegionEndAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1;
1824                 ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
1825
1826                 /* Start address. */
1827                 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) |
1828                                                                           ( portMPU_REGION_NON_SHAREABLE );
1829
1830                 /* RO/RW. */
1831                 if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_READ_ONLY ) != 0 )
1832                 {
1833                     xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_ONLY );
1834                 }
1835                 else
1836                 {
1837                     xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_WRITE );
1838                 }
1839
1840                 /* XN. */
1841                 if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 )
1842                 {
1843                     xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER );
1844                 }
1845
1846                 /* End Address. */
1847                 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) |
1848                                                                           ( portMPU_RLAR_REGION_ENABLE );
1849
1850                 /* Normal memory/ Device memory. */
1851                 if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_DEVICE_MEMORY ) != 0 )
1852                 {
1853                     /* Attr1 in MAIR0 is configured as device memory. */
1854                     xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX1;
1855                 }
1856                 else
1857                 {
1858                     /* Attr0 in MAIR0 is configured as normal memory. */
1859                     xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX0;
1860                 }
1861             }
1862             else
1863             {
1864                 /* Invalidate the region. */
1865                 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = 0UL;
1866                 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = 0UL;
1867             }
1868
1869             lIndex++;
1870         }
1871     }
1872 #endif /* configENABLE_MPU */
1873 /*-----------------------------------------------------------*/
1874
1875 #if ( configENABLE_MPU == 1 )
1876     BaseType_t xPortIsAuthorizedToAccessBuffer( const void * pvBuffer,
1877                                                 uint32_t ulBufferLength,
1878                                                 uint32_t ulAccessRequested ) /* PRIVILEGED_FUNCTION */
1879
1880     {
1881         uint32_t i, ulBufferStartAddress, ulBufferEndAddress;
1882         BaseType_t xAccessGranted = pdFALSE;
1883         const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
1884
1885         if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
1886         {
1887             xAccessGranted = pdTRUE;
1888         }
1889         else
1890         {
1891             if( portADD_UINT32_WILL_OVERFLOW( ( ( uint32_t ) pvBuffer ), ( ulBufferLength - 1UL ) ) == pdFALSE )
1892             {
1893                 ulBufferStartAddress = ( uint32_t ) pvBuffer;
1894                 ulBufferEndAddress = ( ( ( uint32_t ) pvBuffer ) + ulBufferLength - 1UL );
1895
1896                 for( i = 0; i < portTOTAL_NUM_REGIONS; i++ )
1897                 {
1898                     /* Is the MPU region enabled? */
1899                     if( ( xTaskMpuSettings->xRegionsSettings[ i ].ulRLAR & portMPU_RLAR_REGION_ENABLE ) == portMPU_RLAR_REGION_ENABLE )
1900                     {
1901                         if( portIS_ADDRESS_WITHIN_RANGE( ulBufferStartAddress,
1902                                                          portEXTRACT_FIRST_ADDRESS_FROM_RBAR( xTaskMpuSettings->xRegionsSettings[ i ].ulRBAR ),
1903                                                          portEXTRACT_LAST_ADDRESS_FROM_RLAR( xTaskMpuSettings->xRegionsSettings[ i ].ulRLAR ) ) &&
1904                             portIS_ADDRESS_WITHIN_RANGE( ulBufferEndAddress,
1905                                                          portEXTRACT_FIRST_ADDRESS_FROM_RBAR( xTaskMpuSettings->xRegionsSettings[ i ].ulRBAR ),
1906                                                          portEXTRACT_LAST_ADDRESS_FROM_RLAR( xTaskMpuSettings->xRegionsSettings[ i ].ulRLAR ) ) &&
1907                             portIS_AUTHORIZED( ulAccessRequested,
1908                                                prvGetRegionAccessPermissions( xTaskMpuSettings->xRegionsSettings[ i ].ulRBAR ) ) )
1909                         {
1910                             xAccessGranted = pdTRUE;
1911                             break;
1912                         }
1913                     }
1914                 }
1915             }
1916         }
1917
1918         return xAccessGranted;
1919     }
1920 #endif /* configENABLE_MPU */
1921 /*-----------------------------------------------------------*/
1922
1923 BaseType_t xPortIsInsideInterrupt( void )
1924 {
1925     uint32_t ulCurrentInterrupt;
1926     BaseType_t xReturn;
1927
1928     /* Obtain the number of the currently executing interrupt. Interrupt Program
1929      * Status Register (IPSR) holds the exception number of the currently-executing
1930      * exception or zero for Thread mode.*/
1931     __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
1932
1933     if( ulCurrentInterrupt == 0 )
1934     {
1935         xReturn = pdFALSE;
1936     }
1937     else
1938     {
1939         xReturn = pdTRUE;
1940     }
1941
1942     return xReturn;
1943 }
1944 /*-----------------------------------------------------------*/
1945
1946 #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
1947
1948     void vPortValidateInterruptPriority( void )
1949     {
1950         uint32_t ulCurrentInterrupt;
1951         uint8_t ucCurrentPriority;
1952
1953         /* Obtain the number of the currently executing interrupt. */
1954         __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
1955
1956         /* Is the interrupt number a user defined interrupt? */
1957         if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
1958         {
1959             /* Look up the interrupt's priority. */
1960             ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
1961
1962             /* The following assertion will fail if a service routine (ISR) for
1963              * an interrupt that has been assigned a priority above
1964              * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
1965              * function.  ISR safe FreeRTOS API functions must *only* be called
1966              * from interrupts that have been assigned a priority at or below
1967              * configMAX_SYSCALL_INTERRUPT_PRIORITY.
1968              *
1969              * Numerically low interrupt priority numbers represent logically high
1970              * interrupt priorities, therefore the priority of the interrupt must
1971              * be set to a value equal to or numerically *higher* than
1972              * configMAX_SYSCALL_INTERRUPT_PRIORITY.
1973              *
1974              * Interrupts that  use the FreeRTOS API must not be left at their
1975              * default priority of  zero as that is the highest possible priority,
1976              * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
1977              * and  therefore also guaranteed to be invalid.
1978              *
1979              * FreeRTOS maintains separate thread and ISR API functions to ensure
1980              * interrupt entry is as fast and simple as possible.
1981              *
1982              * The following links provide detailed information:
1983              * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
1984              * https://www.FreeRTOS.org/FAQHelp.html */
1985             configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
1986         }
1987
1988         /* Priority grouping:  The interrupt controller (NVIC) allows the bits
1989          * that define each interrupt's priority to be split between bits that
1990          * define the interrupt's pre-emption priority bits and bits that define
1991          * the interrupt's sub-priority.  For simplicity all bits must be defined
1992          * to be pre-emption priority bits.  The following assertion will fail if
1993          * this is not the case (if some bits represent a sub-priority).
1994          *
1995          * If the application only uses CMSIS libraries for interrupt
1996          * configuration then the correct setting can be achieved on all Cortex-M
1997          * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
1998          * scheduler.  Note however that some vendor specific peripheral libraries
1999          * assume a non-zero priority group setting, in which cases using a value
2000          * of zero will result in unpredictable behaviour. */
2001         configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
2002     }
2003
2004 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
2005 /*-----------------------------------------------------------*/