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