2 * FreeRTOS Kernel <DEVELOPMENT BRANCH>
3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 * Copyright 2024 Arm Limited and/or its affiliates
5 * <open-source-office@arm.com>
7 * SPDX-License-Identifier: MIT
9 * Permission is hereby granted, free of charge, to any person obtaining a copy of
10 * this software and associated documentation files (the "Software"), to deal in
11 * the Software without restriction, including without limitation the rights to
12 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
13 * the Software, and to permit persons to whom the Software is furnished to do so,
14 * subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included in all
17 * copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
21 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
22 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
23 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * https://www.FreeRTOS.org
27 * https://github.com/FreeRTOS
31 /* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
32 * all the API functions to use the MPU wrappers. That should only be done when
33 * task.h is included from an application file. */
34 #define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
36 /* Scheduler includes. */
41 #include "mpu_wrappers.h"
42 #include "mpu_syscall_numbers.h"
44 /* Portasm includes. */
47 #if ( configENABLE_TRUSTZONE == 1 )
48 /* Secure components includes. */
49 #include "secure_context.h"
50 #include "secure_init.h"
51 #endif /* configENABLE_TRUSTZONE */
53 #undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
56 * The FreeRTOS Cortex M33 port can be configured to run on the Secure Side only
57 * i.e. the processor boots as secure and never jumps to the non-secure side.
58 * The Trust Zone support in the port must be disabled in order to run FreeRTOS
59 * on the secure side. The following are the valid configuration seetings:
61 * 1. Run FreeRTOS on the Secure Side:
62 * configRUN_FREERTOS_SECURE_ONLY = 1 and configENABLE_TRUSTZONE = 0
64 * 2. Run FreeRTOS on the Non-Secure Side with Secure Side function call support:
65 * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 1
67 * 3. Run FreeRTOS on the Non-Secure Side only i.e. no Secure Side function call support:
68 * configRUN_FREERTOS_SECURE_ONLY = 0 and configENABLE_TRUSTZONE = 0
70 #if ( ( configRUN_FREERTOS_SECURE_ONLY == 1 ) && ( configENABLE_TRUSTZONE == 1 ) )
71 #error TrustZone needs to be disabled in order to run FreeRTOS on the Secure Side.
75 * Cortex-M23 does not have non-secure PSPLIM. We should use PSPLIM on Cortex-M23
76 * only when FreeRTOS runs on secure side.
78 #if ( ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) && ( configRUN_FREERTOS_SECURE_ONLY == 0 ) )
79 #define portUSE_PSPLIM_REGISTER 0
81 #define portUSE_PSPLIM_REGISTER 1
83 /*-----------------------------------------------------------*/
86 * @brief Prototype of all Interrupt Service Routines (ISRs).
88 typedef void ( * portISR_t )( void );
89 /*-----------------------------------------------------------*/
92 * @brief Constants required to manipulate the NVIC.
94 #define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) )
95 #define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) )
96 #define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) )
97 #define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) )
98 #define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL )
99 #define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL )
100 #define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL )
101 #define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL )
102 #define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL )
103 #define portNVIC_PEND_SYSTICK_SET_BIT ( 1UL << 26UL )
104 #define portMIN_INTERRUPT_PRIORITY ( 255UL )
105 #define portNVIC_PENDSV_PRI ( portMIN_INTERRUPT_PRIORITY << 16UL )
106 #define portNVIC_SYSTICK_PRI ( portMIN_INTERRUPT_PRIORITY << 24UL )
107 /*-----------------------------------------------------------*/
110 * @brief Constants required to manipulate the SCB.
112 #define portSCB_VTOR_REG ( *( ( portISR_t ** ) 0xe000ed08 ) )
113 #define portSCB_SYS_HANDLER_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) )
114 #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL )
115 #define portSCB_USG_FAULT_ENABLE_BIT ( 1UL << 18UL )
116 /*-----------------------------------------------------------*/
119 * @brief Constants used to check the installation of the FreeRTOS interrupt handlers.
121 #define portVECTOR_INDEX_SVC ( 11 )
122 #define portVECTOR_INDEX_PENDSV ( 14 )
123 /*-----------------------------------------------------------*/
126 * @brief Constants required to check the validity of an interrupt priority.
128 #define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) )
129 #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
130 #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
131 #define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) )
132 #define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 )
133 #define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 )
134 #define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL )
135 #define portPRIGROUP_SHIFT ( 8UL )
136 /*-----------------------------------------------------------*/
139 * @brief Constants used during system call enter and exit.
141 #define portPSR_STACK_PADDING_MASK ( 1UL << 9UL )
142 #define portEXC_RETURN_STACK_FRAME_TYPE_MASK ( 1UL << 4UL )
143 /*-----------------------------------------------------------*/
146 * @brief Constants required to manipulate the FPU.
148 #define portCPACR ( ( volatile uint32_t * ) 0xe000ed88 ) /* Coprocessor Access Control Register. */
149 #define portCPACR_CP10_VALUE ( 3UL )
150 #define portCPACR_CP11_VALUE portCPACR_CP10_VALUE
151 #define portCPACR_CP10_POS ( 20UL )
152 #define portCPACR_CP11_POS ( 22UL )
154 #define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating Point Context Control Register. */
155 #define portFPCCR_ASPEN_POS ( 31UL )
156 #define portFPCCR_ASPEN_MASK ( 1UL << portFPCCR_ASPEN_POS )
157 #define portFPCCR_LSPEN_POS ( 30UL )
158 #define portFPCCR_LSPEN_MASK ( 1UL << portFPCCR_LSPEN_POS )
159 /*-----------------------------------------------------------*/
162 * @brief Offsets in the stack to the parameters when inside the SVC handler.
164 #define portOFFSET_TO_LR ( 5 )
165 #define portOFFSET_TO_PC ( 6 )
166 #define portOFFSET_TO_PSR ( 7 )
167 /*-----------------------------------------------------------*/
170 * @brief Constants required to manipulate the MPU.
172 #define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) )
173 #define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) )
174 #define portMPU_RNR_REG ( *( ( volatile uint32_t * ) 0xe000ed98 ) )
176 #define portMPU_RBAR_REG ( *( ( volatile uint32_t * ) 0xe000ed9c ) )
177 #define portMPU_RLAR_REG ( *( ( volatile uint32_t * ) 0xe000eda0 ) )
179 #define portMPU_RBAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda4 ) )
180 #define portMPU_RLAR_A1_REG ( *( ( volatile uint32_t * ) 0xe000eda8 ) )
182 #define portMPU_RBAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edac ) )
183 #define portMPU_RLAR_A2_REG ( *( ( volatile uint32_t * ) 0xe000edb0 ) )
185 #define portMPU_RBAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb4 ) )
186 #define portMPU_RLAR_A3_REG ( *( ( volatile uint32_t * ) 0xe000edb8 ) )
188 #define portMPU_MAIR0_REG ( *( ( volatile uint32_t * ) 0xe000edc0 ) )
189 #define portMPU_MAIR1_REG ( *( ( volatile uint32_t * ) 0xe000edc4 ) )
191 #define portMPU_RBAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
192 #define portMPU_RLAR_ADDRESS_MASK ( 0xffffffe0 ) /* Must be 32-byte aligned. */
194 #define portMPU_RBAR_ACCESS_PERMISSIONS_MASK ( 3UL << 1UL )
196 #define portMPU_MAIR_ATTR0_POS ( 0UL )
197 #define portMPU_MAIR_ATTR0_MASK ( 0x000000ff )
199 #define portMPU_MAIR_ATTR1_POS ( 8UL )
200 #define portMPU_MAIR_ATTR1_MASK ( 0x0000ff00 )
202 #define portMPU_MAIR_ATTR2_POS ( 16UL )
203 #define portMPU_MAIR_ATTR2_MASK ( 0x00ff0000 )
205 #define portMPU_MAIR_ATTR3_POS ( 24UL )
206 #define portMPU_MAIR_ATTR3_MASK ( 0xff000000 )
208 #define portMPU_MAIR_ATTR4_POS ( 0UL )
209 #define portMPU_MAIR_ATTR4_MASK ( 0x000000ff )
211 #define portMPU_MAIR_ATTR5_POS ( 8UL )
212 #define portMPU_MAIR_ATTR5_MASK ( 0x0000ff00 )
214 #define portMPU_MAIR_ATTR6_POS ( 16UL )
215 #define portMPU_MAIR_ATTR6_MASK ( 0x00ff0000 )
217 #define portMPU_MAIR_ATTR7_POS ( 24UL )
218 #define portMPU_MAIR_ATTR7_MASK ( 0xff000000 )
220 #define portMPU_RLAR_ATTR_INDEX0 ( 0UL << 1UL )
221 #define portMPU_RLAR_ATTR_INDEX1 ( 1UL << 1UL )
222 #define portMPU_RLAR_ATTR_INDEX2 ( 2UL << 1UL )
223 #define portMPU_RLAR_ATTR_INDEX3 ( 3UL << 1UL )
224 #define portMPU_RLAR_ATTR_INDEX4 ( 4UL << 1UL )
225 #define portMPU_RLAR_ATTR_INDEX5 ( 5UL << 1UL )
226 #define portMPU_RLAR_ATTR_INDEX6 ( 6UL << 1UL )
227 #define portMPU_RLAR_ATTR_INDEX7 ( 7UL << 1UL )
229 #define portMPU_RLAR_REGION_ENABLE ( 1UL )
231 #if ( portARMV8M_MINOR_VERSION >= 1 )
232 /* Enable Privileged eXecute Never MPU attribute for the selected memory
234 #define portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER ( 1UL << 4UL )
235 #endif /* portARMV8M_MINOR_VERSION >= 1 */
237 /* Enable privileged access to unmapped region. */
238 #define portMPU_PRIV_BACKGROUND_ENABLE_BIT ( 1UL << 2UL )
241 #define portMPU_ENABLE_BIT ( 1UL << 0UL )
243 /* Expected value of the portMPU_TYPE register. */
244 #define portEXPECTED_MPU_TYPE_VALUE ( configTOTAL_MPU_REGIONS << 8UL )
246 /* Extract first address of the MPU region as encoded in the
247 * RBAR (Region Base Address Register) value. */
248 #define portEXTRACT_FIRST_ADDRESS_FROM_RBAR( rbar ) \
249 ( ( rbar ) & portMPU_RBAR_ADDRESS_MASK )
251 /* Extract last address of the MPU region as encoded in the
252 * RLAR (Region Limit Address Register) value. */
253 #define portEXTRACT_LAST_ADDRESS_FROM_RLAR( rlar ) \
254 ( ( ( rlar ) & portMPU_RLAR_ADDRESS_MASK ) | ~portMPU_RLAR_ADDRESS_MASK )
256 /* Does addr lies within [start, end] address range? */
257 #define portIS_ADDRESS_WITHIN_RANGE( addr, start, end ) \
258 ( ( ( addr ) >= ( start ) ) && ( ( addr ) <= ( end ) ) )
260 /* Is the access request satisfied by the available permissions? */
261 #define portIS_AUTHORIZED( accessRequest, permissions ) \
262 ( ( ( permissions ) & ( accessRequest ) ) == accessRequest )
264 /* Max value that fits in a uint32_t type. */
265 #define portUINT32_MAX ( ~( ( uint32_t ) 0 ) )
267 /* Check if adding a and b will result in overflow. */
268 #define portADD_UINT32_WILL_OVERFLOW( a, b ) ( ( a ) > ( portUINT32_MAX - ( b ) ) )
269 /*-----------------------------------------------------------*/
272 * @brief The maximum 24-bit number.
274 * It is needed because the systick is a 24-bit counter.
276 #define portMAX_24_BIT_NUMBER ( 0xffffffUL )
279 * @brief A fiddle factor to estimate the number of SysTick counts that would
280 * have occurred while the SysTick counter is stopped during tickless idle
283 #define portMISSED_COUNTS_FACTOR ( 94UL )
284 /*-----------------------------------------------------------*/
287 * @brief Constants required to set up the initial stack.
289 #define portINITIAL_XPSR ( 0x01000000 )
291 #if ( configRUN_FREERTOS_SECURE_ONLY == 1 )
294 * @brief Initial EXC_RETURN value.
297 * 1111 1111 1111 1111 1111 1111 1111 1101
299 * Bit[6] - 1 --> The exception was taken from the Secure state.
300 * Bit[5] - 1 --> Do not skip stacking of additional state context.
301 * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
302 * Bit[3] - 1 --> Return to the Thread mode.
303 * Bit[2] - 1 --> Restore registers from the process stack.
304 * Bit[1] - 0 --> Reserved, 0.
305 * Bit[0] - 1 --> The exception was taken to the Secure state.
307 #define portINITIAL_EXC_RETURN ( 0xfffffffd )
311 * @brief Initial EXC_RETURN value.
314 * 1111 1111 1111 1111 1111 1111 1011 1100
316 * Bit[6] - 0 --> The exception was taken from the Non-Secure state.
317 * Bit[5] - 1 --> Do not skip stacking of additional state context.
318 * Bit[4] - 1 --> The PE did not allocate space on the stack for FP context.
319 * Bit[3] - 1 --> Return to the Thread mode.
320 * Bit[2] - 1 --> Restore registers from the process stack.
321 * Bit[1] - 0 --> Reserved, 0.
322 * Bit[0] - 0 --> The exception was taken to the Non-Secure state.
324 #define portINITIAL_EXC_RETURN ( 0xffffffbc )
325 #endif /* configRUN_FREERTOS_SECURE_ONLY */
328 * @brief CONTROL register privileged bit mask.
330 * Bit[0] in CONTROL register tells the privilege:
331 * Bit[0] = 0 ==> The task is privileged.
332 * Bit[0] = 1 ==> The task is not privileged.
334 #define portCONTROL_PRIVILEGED_MASK ( 1UL << 0UL )
337 * @brief Initial CONTROL register values.
339 #define portINITIAL_CONTROL_UNPRIVILEGED ( 0x3 )
340 #define portINITIAL_CONTROL_PRIVILEGED ( 0x2 )
343 * @brief Let the user override the default SysTick clock rate. If defined by the
344 * user, this symbol must equal the SysTick clock rate when the CLK bit is 0 in the
345 * configuration register.
347 #ifndef configSYSTICK_CLOCK_HZ
348 #define configSYSTICK_CLOCK_HZ ( configCPU_CLOCK_HZ )
349 /* Ensure the SysTick is clocked at the same frequency as the core. */
350 #define portNVIC_SYSTICK_CLK_BIT_CONFIG ( portNVIC_SYSTICK_CLK_BIT )
352 /* Select the option to clock SysTick not at the same frequency as the core. */
353 #define portNVIC_SYSTICK_CLK_BIT_CONFIG ( 0 )
357 * @brief Let the user override the pre-loading of the initial LR with the
358 * address of prvTaskExitError() in case it messes up unwinding of the stack
361 #ifdef configTASK_RETURN_ADDRESS
362 #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
364 #define portTASK_RETURN_ADDRESS prvTaskExitError
368 * @brief If portPRELOAD_REGISTERS then registers will be given an initial value
369 * when a task is created. This helps in debugging at the cost of code size.
371 #define portPRELOAD_REGISTERS 1
374 * @brief A task is created without a secure context, and must call
375 * portALLOCATE_SECURE_CONTEXT() to give itself a secure context before it makes
378 #define portNO_SECURE_CONTEXT 0
381 * @brief Constants required to check and configure PACBTI security feature implementation.
383 #if ( portHAS_PACBTI_FEATURE == 1 )
385 #define portID_ISAR5_REG ( *( ( volatile uint32_t * ) 0xe000ed74 ) )
387 #define portCONTROL_UPAC_EN ( 1UL << 7UL )
388 #define portCONTROL_PAC_EN ( 1UL << 6UL )
389 #define portCONTROL_UBTI_EN ( 1UL << 5UL )
390 #define portCONTROL_BTI_EN ( 1UL << 4UL )
392 #endif /* portHAS_PACBTI_FEATURE */
393 /*-----------------------------------------------------------*/
396 * @brief Used to catch tasks that attempt to return from their implementing
399 static void prvTaskExitError( void );
401 #if ( configENABLE_MPU == 1 )
404 * @brief Extract MPU region's access permissions from the Region Base Address
405 * Register (RBAR) value.
407 * @param ulRBARValue RBAR value for the MPU region.
409 * @return uint32_t Access permissions.
411 static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) PRIVILEGED_FUNCTION;
412 #endif /* configENABLE_MPU */
414 #if ( configENABLE_MPU == 1 )
417 * @brief Setup the Memory Protection Unit (MPU).
419 static void prvSetupMPU( void ) PRIVILEGED_FUNCTION;
420 #endif /* configENABLE_MPU */
422 #if ( configENABLE_FPU == 1 )
425 * @brief Setup the Floating Point Unit (FPU).
427 static void prvSetupFPU( void ) PRIVILEGED_FUNCTION;
428 #endif /* configENABLE_FPU */
430 #if ( portHAS_PACBTI_FEATURE == 1 )
433 * @brief Configures PACBTI features.
435 * This function configures the Pointer Authentication, and Branch Target
436 * Identification security features as per the user configuration. It returns
437 * the value of the special purpose CONTROL register accordingly, and optionally
438 * updates the CONTROL register value. Currently, only Cortex-M85 (ARMv8.1-M
439 * architecture based) target supports PACBTI security feature.
441 * @param xWriteControlRegister Used to control whether the special purpose
442 * CONTROL register should be updated or not.
444 * @return CONTROL register value according to the configured PACBTI option.
446 static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister );
448 #endif /* portHAS_PACBTI_FEATURE */
451 * @brief Setup the timer to generate the tick interrupts.
453 * The implementation in this file is weak to allow application writers to
454 * change the timer used to generate the tick interrupt.
456 void vPortSetupTimerInterrupt( void ) PRIVILEGED_FUNCTION;
459 * @brief Checks whether the current execution context is interrupt.
461 * @return pdTRUE if the current execution context is interrupt, pdFALSE
464 BaseType_t xPortIsInsideInterrupt( void );
467 * @brief Yield the processor.
469 void vPortYield( void ) PRIVILEGED_FUNCTION;
472 * @brief Enter critical section.
474 void vPortEnterCritical( void ) PRIVILEGED_FUNCTION;
477 * @brief Exit from critical section.
479 void vPortExitCritical( void ) PRIVILEGED_FUNCTION;
482 * @brief SysTick handler.
484 void SysTick_Handler( void ) PRIVILEGED_FUNCTION;
487 * @brief C part of SVC handler.
489 portDONT_DISCARD void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) PRIVILEGED_FUNCTION;
491 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
494 * @brief Sets up the system call stack so that upon returning from
495 * SVC, the system call stack is used.
497 * @param pulTaskStack The current SP when the SVC was raised.
498 * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
499 * @param ucSystemCallNumber The system call number of the system call.
501 void vSystemCallEnter( uint32_t * pulTaskStack,
503 uint8_t ucSystemCallNumber ) PRIVILEGED_FUNCTION;
505 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
507 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
510 * @brief Raise SVC for exiting from a system call.
512 void vRequestSystemCallExit( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION;
514 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
516 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
519 * @brief Sets up the task stack so that upon returning from
520 * SVC, the task stack is used again.
522 * @param pulSystemCallStack The current SP when the SVC was raised.
523 * @param ulLR The value of Link Register (EXC_RETURN) in the SVC handler.
525 void vSystemCallExit( uint32_t * pulSystemCallStack,
526 uint32_t ulLR ) PRIVILEGED_FUNCTION;
528 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
530 #if ( configENABLE_MPU == 1 )
533 * @brief Checks whether or not the calling task is privileged.
535 * @return pdTRUE if the calling task is privileged, pdFALSE otherwise.
537 BaseType_t xPortIsTaskPrivileged( void ) PRIVILEGED_FUNCTION;
539 #endif /* configENABLE_MPU == 1 */
540 /*-----------------------------------------------------------*/
542 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
545 * @brief This variable is set to pdTRUE when the scheduler is started.
547 PRIVILEGED_DATA static BaseType_t xSchedulerRunning = pdFALSE;
549 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
552 * @brief Each task maintains its own interrupt status in the critical nesting
555 PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL;
557 #if ( configENABLE_TRUSTZONE == 1 )
560 * @brief Saved as part of the task context to indicate which context the
561 * task is using on the secure side.
563 PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT;
564 #endif /* configENABLE_TRUSTZONE */
567 * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
568 * FreeRTOS API functions are not called from interrupts that have been assigned
569 * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
571 #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
573 static uint8_t ucMaxSysCallPriority = 0;
574 static uint32_t ulMaxPRIGROUPValue = 0;
575 static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16;
577 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
579 #if ( configUSE_TICKLESS_IDLE == 1 )
582 * @brief The number of SysTick increments that make up one tick period.
584 PRIVILEGED_DATA static uint32_t ulTimerCountsForOneTick = 0;
587 * @brief The maximum number of tick periods that can be suppressed is
588 * limited by the 24 bit resolution of the SysTick timer.
590 PRIVILEGED_DATA static uint32_t xMaximumPossibleSuppressedTicks = 0;
593 * @brief Compensate for the CPU cycles that pass while the SysTick is
594 * stopped (low power functionality only).
596 PRIVILEGED_DATA static uint32_t ulStoppedTimerCompensation = 0;
597 #endif /* configUSE_TICKLESS_IDLE */
598 /*-----------------------------------------------------------*/
600 #if ( configUSE_TICKLESS_IDLE == 1 )
602 __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime )
604 uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft;
605 TickType_t xModifiableIdleTime;
607 /* Make sure the SysTick reload value does not overflow the counter. */
608 if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks )
610 xExpectedIdleTime = xMaximumPossibleSuppressedTicks;
613 /* Enter a critical section but don't use the taskENTER_CRITICAL()
614 * method as that will mask interrupts that should exit sleep mode. */
615 __asm volatile ( "cpsid i" ::: "memory" );
616 __asm volatile ( "dsb" );
617 __asm volatile ( "isb" );
619 /* If a context switch is pending or a task is waiting for the scheduler
620 * to be unsuspended then abandon the low power entry. */
621 if( eTaskConfirmSleepModeStatus() == eAbortSleep )
623 /* Re-enable interrupts - see comments above the cpsid instruction
625 __asm volatile ( "cpsie i" ::: "memory" );
629 /* Stop the SysTick momentarily. The time the SysTick is stopped for
630 * is accounted for as best it can be, but using the tickless mode will
631 * inevitably result in some tiny drift of the time maintained by the
632 * kernel with respect to calendar time. */
633 portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT );
635 /* Use the SysTick current-value register to determine the number of
636 * SysTick decrements remaining until the next tick interrupt. If the
637 * current-value register is zero, then there are actually
638 * ulTimerCountsForOneTick decrements remaining, not zero, because the
639 * SysTick requests the interrupt when decrementing from 1 to 0. */
640 ulSysTickDecrementsLeft = portNVIC_SYSTICK_CURRENT_VALUE_REG;
642 if( ulSysTickDecrementsLeft == 0 )
644 ulSysTickDecrementsLeft = ulTimerCountsForOneTick;
647 /* Calculate the reload value required to wait xExpectedIdleTime
648 * tick periods. -1 is used because this code normally executes part
649 * way through the first tick period. But if the SysTick IRQ is now
650 * pending, then clear the IRQ, suppressing the first tick, and correct
651 * the reload value to reflect that the second tick period is already
652 * underway. The expected idle time is always at least two ticks. */
653 ulReloadValue = ulSysTickDecrementsLeft + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );
655 if( ( portNVIC_INT_CTRL_REG & portNVIC_PEND_SYSTICK_SET_BIT ) != 0 )
657 portNVIC_INT_CTRL_REG = portNVIC_PEND_SYSTICK_CLEAR_BIT;
658 ulReloadValue -= ulTimerCountsForOneTick;
661 if( ulReloadValue > ulStoppedTimerCompensation )
663 ulReloadValue -= ulStoppedTimerCompensation;
666 /* Set the new reload value. */
667 portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
669 /* Clear the SysTick count flag and set the count value back to
671 portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
673 /* Restart SysTick. */
674 portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
676 /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
677 * set its parameter to 0 to indicate that its implementation contains
678 * its own wait for interrupt or wait for event instruction, and so wfi
679 * should not be executed again. However, the original expected idle
680 * time variable must remain unmodified, so a copy is taken. */
681 xModifiableIdleTime = xExpectedIdleTime;
682 configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
684 if( xModifiableIdleTime > 0 )
686 __asm volatile ( "dsb" ::: "memory" );
687 __asm volatile ( "wfi" );
688 __asm volatile ( "isb" );
691 configPOST_SLEEP_PROCESSING( xExpectedIdleTime );
693 /* Re-enable interrupts to allow the interrupt that brought the MCU
694 * out of sleep mode to execute immediately. See comments above
695 * the cpsid instruction above. */
696 __asm volatile ( "cpsie i" ::: "memory" );
697 __asm volatile ( "dsb" );
698 __asm volatile ( "isb" );
700 /* Disable interrupts again because the clock is about to be stopped
701 * and interrupts that execute while the clock is stopped will increase
702 * any slippage between the time maintained by the RTOS and calendar
704 __asm volatile ( "cpsid i" ::: "memory" );
705 __asm volatile ( "dsb" );
706 __asm volatile ( "isb" );
708 /* Disable the SysTick clock without reading the
709 * portNVIC_SYSTICK_CTRL_REG register to ensure the
710 * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again,
711 * the time the SysTick is stopped for is accounted for as best it can
712 * be, but using the tickless mode will inevitably result in some tiny
713 * drift of the time maintained by the kernel with respect to calendar
715 portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT );
717 /* Determine whether the SysTick has already counted to zero. */
718 if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
720 uint32_t ulCalculatedLoadValue;
722 /* The tick interrupt ended the sleep (or is now pending), and
723 * a new tick period has started. Reset portNVIC_SYSTICK_LOAD_REG
724 * with whatever remains of the new tick period. */
725 ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG );
727 /* Don't allow a tiny value, or values that have somehow
728 * underflowed because the post sleep hook did something
729 * that took too long or because the SysTick current-value register
731 if( ( ulCalculatedLoadValue <= ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) )
733 ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL );
736 portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue;
738 /* As the pending tick will be processed as soon as this
739 * function exits, the tick value maintained by the tick is stepped
740 * forward by one less than the time spent waiting. */
741 ulCompleteTickPeriods = xExpectedIdleTime - 1UL;
745 /* Something other than the tick interrupt ended the sleep. */
747 /* Use the SysTick current-value register to determine the
748 * number of SysTick decrements remaining until the expected idle
749 * time would have ended. */
750 ulSysTickDecrementsLeft = portNVIC_SYSTICK_CURRENT_VALUE_REG;
751 #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG != portNVIC_SYSTICK_CLK_BIT )
753 /* If the SysTick is not using the core clock, the current-
754 * value register might still be zero here. In that case, the
755 * SysTick didn't load from the reload register, and there are
756 * ulReloadValue decrements remaining in the expected idle
758 if( ulSysTickDecrementsLeft == 0 )
760 ulSysTickDecrementsLeft = ulReloadValue;
763 #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */
765 /* Work out how long the sleep lasted rounded to complete tick
766 * periods (not the ulReload value which accounted for part
768 ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - ulSysTickDecrementsLeft;
770 /* How many complete tick periods passed while the processor
772 ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick;
774 /* The reload value is set to whatever fraction of a single tick
776 portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements;
779 /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again,
780 * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If
781 * the SysTick is not using the core clock, temporarily configure it to
782 * use the core clock. This configuration forces the SysTick to load
783 * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next
784 * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready
785 * to receive the standard value immediately. */
786 portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
787 portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
788 #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT )
790 portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
794 /* The temporary usage of the core clock has served its purpose,
795 * as described above. Resume usage of the other clock. */
796 portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;
798 if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
800 /* The partial tick period already ended. Be sure the SysTick
801 * counts it only once. */
802 portNVIC_SYSTICK_CURRENT_VALUE_REG = 0;
805 portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
806 portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
808 #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */
810 /* Step the tick to account for any tick periods that elapsed. */
811 vTaskStepTick( ulCompleteTickPeriods );
813 /* Exit with interrupts enabled. */
814 __asm volatile ( "cpsie i" ::: "memory" );
818 #endif /* configUSE_TICKLESS_IDLE */
819 /*-----------------------------------------------------------*/
821 __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) /* PRIVILEGED_FUNCTION */
823 /* Calculate the constants required to configure the tick interrupt. */
824 #if ( configUSE_TICKLESS_IDLE == 1 )
826 ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
827 xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
828 ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
830 #endif /* configUSE_TICKLESS_IDLE */
832 /* Stop and reset SysTick.
834 * QEMU versions older than 7.0.0 contain a bug which causes an error if we
835 * enable SysTick without first selecting a valid clock source. We trigger
836 * the bug if we change clock sources from a clock with a zero clock period
837 * to one with a nonzero clock period and enable Systick at the same time.
838 * So we configure the CLKSOURCE bit here, prior to setting the ENABLE bit.
839 * This workaround avoids the bug in QEMU versions older than 7.0.0. */
840 portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG;
841 portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
843 /* Configure SysTick to interrupt at the requested rate. */
844 portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
845 portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
847 /*-----------------------------------------------------------*/
849 static void prvTaskExitError( void )
851 volatile uint32_t ulDummy = 0UL;
853 /* A function that implements a task must not exit or attempt to return to
854 * its caller as there is nothing to return to. If a task wants to exit it
855 * should instead call vTaskDelete( NULL ). Artificially force an assert()
856 * to be triggered if configASSERT() is defined, then stop here so
857 * application writers can catch the error. */
858 configASSERT( ulCriticalNesting == ~0UL );
859 portDISABLE_INTERRUPTS();
861 while( ulDummy == 0 )
863 /* This file calls prvTaskExitError() after the scheduler has been
864 * started to remove a compiler warning about the function being
865 * defined but never called. ulDummy is used purely to quieten other
866 * warnings about code appearing after this function is called - making
867 * ulDummy volatile makes the compiler think the function could return
868 * and therefore not output an 'unreachable code' warning for code that
869 * appears after it. */
872 /*-----------------------------------------------------------*/
874 #if ( configENABLE_MPU == 1 )
876 static uint32_t prvGetRegionAccessPermissions( uint32_t ulRBARValue ) /* PRIVILEGED_FUNCTION */
878 uint32_t ulAccessPermissions = 0;
880 if( ( ulRBARValue & portMPU_RBAR_ACCESS_PERMISSIONS_MASK ) == portMPU_REGION_READ_ONLY )
882 ulAccessPermissions = tskMPU_READ_PERMISSION;
885 if( ( ulRBARValue & portMPU_RBAR_ACCESS_PERMISSIONS_MASK ) == portMPU_REGION_READ_WRITE )
887 ulAccessPermissions = ( tskMPU_READ_PERMISSION | tskMPU_WRITE_PERMISSION );
890 return ulAccessPermissions;
893 #endif /* configENABLE_MPU */
894 /*-----------------------------------------------------------*/
896 #if ( configENABLE_MPU == 1 )
898 static void prvSetupMPU( void ) /* PRIVILEGED_FUNCTION */
900 #if defined( __ARMCC_VERSION )
902 /* Declaration when these variable are defined in code instead of being
903 * exported from linker scripts. */
904 extern uint32_t * __privileged_functions_start__;
905 extern uint32_t * __privileged_functions_end__;
906 extern uint32_t * __syscalls_flash_start__;
907 extern uint32_t * __syscalls_flash_end__;
908 extern uint32_t * __unprivileged_flash_start__;
909 extern uint32_t * __unprivileged_flash_end__;
910 extern uint32_t * __privileged_sram_start__;
911 extern uint32_t * __privileged_sram_end__;
912 #else /* if defined( __ARMCC_VERSION ) */
913 /* Declaration when these variable are exported from linker scripts. */
914 extern uint32_t __privileged_functions_start__[];
915 extern uint32_t __privileged_functions_end__[];
916 extern uint32_t __syscalls_flash_start__[];
917 extern uint32_t __syscalls_flash_end__[];
918 extern uint32_t __unprivileged_flash_start__[];
919 extern uint32_t __unprivileged_flash_end__[];
920 extern uint32_t __privileged_sram_start__[];
921 extern uint32_t __privileged_sram_end__[];
922 #endif /* defined( __ARMCC_VERSION ) */
924 /* The only permitted number of regions are 8 or 16. */
925 configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) );
927 /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */
928 configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE );
930 /* Check that the MPU is present. */
931 if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE )
933 /* MAIR0 - Index 0. */
934 portMPU_MAIR0_REG |= ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
935 /* MAIR0 - Index 1. */
936 portMPU_MAIR0_REG |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
938 /* Setup privileged flash as Read Only so that privileged tasks can
939 * read it but not modify. */
940 portMPU_RNR_REG = portPRIVILEGED_FLASH_REGION;
941 portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_functions_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
942 ( portMPU_REGION_NON_SHAREABLE ) |
943 ( portMPU_REGION_PRIVILEGED_READ_ONLY );
944 portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_functions_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
945 ( portMPU_RLAR_ATTR_INDEX0 ) |
946 ( portMPU_RLAR_REGION_ENABLE );
948 /* Setup unprivileged flash as Read Only by both privileged and
949 * unprivileged tasks. All tasks can read it but no-one can modify. */
950 portMPU_RNR_REG = portUNPRIVILEGED_FLASH_REGION;
951 portMPU_RBAR_REG = ( ( ( uint32_t ) __unprivileged_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
952 ( portMPU_REGION_NON_SHAREABLE ) |
953 ( portMPU_REGION_READ_ONLY );
954 portMPU_RLAR_REG = ( ( ( uint32_t ) __unprivileged_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
955 ( portMPU_RLAR_ATTR_INDEX0 ) |
956 ( portMPU_RLAR_REGION_ENABLE );
958 /* Setup unprivileged syscalls flash as Read Only by both privileged
959 * and unprivileged tasks. All tasks can read it but no-one can modify. */
960 portMPU_RNR_REG = portUNPRIVILEGED_SYSCALLS_REGION;
961 portMPU_RBAR_REG = ( ( ( uint32_t ) __syscalls_flash_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
962 ( portMPU_REGION_NON_SHAREABLE ) |
963 ( portMPU_REGION_READ_ONLY );
964 portMPU_RLAR_REG = ( ( ( uint32_t ) __syscalls_flash_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
965 ( portMPU_RLAR_ATTR_INDEX0 ) |
966 ( portMPU_RLAR_REGION_ENABLE );
968 /* Setup RAM containing kernel data for privileged access only. */
969 portMPU_RNR_REG = portPRIVILEGED_RAM_REGION;
970 portMPU_RBAR_REG = ( ( ( uint32_t ) __privileged_sram_start__ ) & portMPU_RBAR_ADDRESS_MASK ) |
971 ( portMPU_REGION_NON_SHAREABLE ) |
972 ( portMPU_REGION_PRIVILEGED_READ_WRITE ) |
973 ( portMPU_REGION_EXECUTE_NEVER );
974 portMPU_RLAR_REG = ( ( ( uint32_t ) __privileged_sram_end__ ) & portMPU_RLAR_ADDRESS_MASK ) |
975 ( portMPU_RLAR_ATTR_INDEX0 ) |
976 ( portMPU_RLAR_REGION_ENABLE );
978 /* Enable mem fault. */
979 portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_MEM_FAULT_ENABLE_BIT;
981 /* Enable MPU with privileged background access i.e. unmapped
982 * regions have privileged access. */
983 portMPU_CTRL_REG |= ( portMPU_PRIV_BACKGROUND_ENABLE_BIT | portMPU_ENABLE_BIT );
987 #endif /* configENABLE_MPU */
988 /*-----------------------------------------------------------*/
990 #if ( configENABLE_FPU == 1 )
992 static void prvSetupFPU( void ) /* PRIVILEGED_FUNCTION */
994 #if ( configENABLE_TRUSTZONE == 1 )
996 /* Enable non-secure access to the FPU. */
997 SecureInit_EnableNSFPUAccess();
999 #endif /* configENABLE_TRUSTZONE */
1001 /* CP10 = 11 ==> Full access to FPU i.e. both privileged and
1002 * unprivileged code should be able to access FPU. CP11 should be
1003 * programmed to the same value as CP10. */
1004 *( portCPACR ) |= ( ( portCPACR_CP10_VALUE << portCPACR_CP10_POS ) |
1005 ( portCPACR_CP11_VALUE << portCPACR_CP11_POS )
1008 /* ASPEN = 1 ==> Hardware should automatically preserve floating point
1009 * context on exception entry and restore on exception return.
1010 * LSPEN = 1 ==> Enable lazy context save of FP state. */
1011 *( portFPCCR ) |= ( portFPCCR_ASPEN_MASK | portFPCCR_LSPEN_MASK );
1014 #endif /* configENABLE_FPU */
1015 /*-----------------------------------------------------------*/
1017 void vPortYield( void ) /* PRIVILEGED_FUNCTION */
1019 /* Set a PendSV to request a context switch. */
1020 portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
1022 /* Barriers are normally not required but do ensure the code is
1023 * completely within the specified behaviour for the architecture. */
1024 __asm volatile ( "dsb" ::: "memory" );
1025 __asm volatile ( "isb" );
1027 /*-----------------------------------------------------------*/
1029 void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */
1031 portDISABLE_INTERRUPTS();
1032 ulCriticalNesting++;
1034 /* Barriers are normally not required but do ensure the code is
1035 * completely within the specified behaviour for the architecture. */
1036 __asm volatile ( "dsb" ::: "memory" );
1037 __asm volatile ( "isb" );
1039 /*-----------------------------------------------------------*/
1041 void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */
1043 configASSERT( ulCriticalNesting );
1044 ulCriticalNesting--;
1046 if( ulCriticalNesting == 0 )
1048 portENABLE_INTERRUPTS();
1051 /*-----------------------------------------------------------*/
1053 void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */
1055 uint32_t ulPreviousMask;
1057 ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR();
1060 /* Increment the RTOS tick. */
1061 if( xTaskIncrementTick() != pdFALSE )
1063 traceISR_EXIT_TO_SCHEDULER();
1064 /* Pend a context switch. */
1065 portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
1072 portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask );
1074 /*-----------------------------------------------------------*/
1076 void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTION portDONT_DISCARD */
1078 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
1079 #if defined( __ARMCC_VERSION )
1081 /* Declaration when these variable are defined in code instead of being
1082 * exported from linker scripts. */
1083 extern uint32_t * __syscalls_flash_start__;
1084 extern uint32_t * __syscalls_flash_end__;
1086 /* Declaration when these variable are exported from linker scripts. */
1087 extern uint32_t __syscalls_flash_start__[];
1088 extern uint32_t __syscalls_flash_end__[];
1089 #endif /* defined( __ARMCC_VERSION ) */
1090 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
1094 #if ( configENABLE_TRUSTZONE == 1 )
1095 uint32_t ulR0, ulR1;
1096 extern TaskHandle_t pxCurrentTCB;
1097 #if ( configENABLE_MPU == 1 )
1098 uint32_t ulControl, ulIsTaskPrivileged;
1099 #endif /* configENABLE_MPU */
1100 #endif /* configENABLE_TRUSTZONE */
1101 uint8_t ucSVCNumber;
1103 /* Register are stored on the stack in the following order - R0, R1, R2, R3,
1104 * R12, LR, PC, xPSR. */
1105 ulPC = pulCallerStackAddress[ portOFFSET_TO_PC ];
1106 ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ];
1108 switch( ucSVCNumber )
1110 #if ( configENABLE_TRUSTZONE == 1 )
1111 case portSVC_ALLOCATE_SECURE_CONTEXT:
1113 /* R0 contains the stack size passed as parameter to the
1114 * vPortAllocateSecureContext function. */
1115 ulR0 = pulCallerStackAddress[ 0 ];
1117 #if ( configENABLE_MPU == 1 )
1119 /* Read the CONTROL register value. */
1120 __asm volatile ( "mrs %0, control" : "=r" ( ulControl ) );
1122 /* The task that raised the SVC is privileged if Bit[0]
1123 * in the CONTROL register is 0. */
1124 ulIsTaskPrivileged = ( ( ulControl & portCONTROL_PRIVILEGED_MASK ) == 0 );
1126 /* Allocate and load a context for the secure task. */
1127 xSecureContext = SecureContext_AllocateContext( ulR0, ulIsTaskPrivileged, pxCurrentTCB );
1129 #else /* if ( configENABLE_MPU == 1 ) */
1131 /* Allocate and load a context for the secure task. */
1132 xSecureContext = SecureContext_AllocateContext( ulR0, pxCurrentTCB );
1134 #endif /* configENABLE_MPU */
1136 configASSERT( xSecureContext != securecontextINVALID_CONTEXT_ID );
1137 SecureContext_LoadContext( xSecureContext, pxCurrentTCB );
1140 case portSVC_FREE_SECURE_CONTEXT:
1142 /* R0 contains TCB being freed and R1 contains the secure
1143 * context handle to be freed. */
1144 ulR0 = pulCallerStackAddress[ 0 ];
1145 ulR1 = pulCallerStackAddress[ 1 ];
1147 /* Free the secure context. */
1148 SecureContext_FreeContext( ( SecureContextHandle_t ) ulR1, ( void * ) ulR0 );
1150 #endif /* configENABLE_TRUSTZONE */
1152 case portSVC_START_SCHEDULER:
1153 #if ( configENABLE_TRUSTZONE == 1 )
1155 /* De-prioritize the non-secure exceptions so that the
1156 * non-secure pendSV runs at the lowest priority. */
1157 SecureInit_DePrioritizeNSExceptions();
1159 /* Initialize the secure context management system. */
1160 SecureContext_Init();
1162 #endif /* configENABLE_TRUSTZONE */
1164 #if ( configENABLE_FPU == 1 )
1166 /* Setup the Floating Point Unit (FPU). */
1169 #endif /* configENABLE_FPU */
1171 /* Setup the context of the first task so that the first task starts
1173 vRestoreContextOfFirstTask();
1176 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) )
1177 case portSVC_RAISE_PRIVILEGE:
1179 /* Only raise the privilege, if the svc was raised from any of
1180 * the system calls. */
1181 if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) &&
1182 ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) )
1187 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 1 ) */
1189 #if ( configENABLE_MPU == 1 )
1193 #endif /* configENABLE_MPU == 1 */
1196 /* Incorrect SVC call. */
1197 configASSERT( pdFALSE );
1200 /*-----------------------------------------------------------*/
1202 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
1204 void vSystemCallEnter( uint32_t * pulTaskStack,
1206 uint8_t ucSystemCallNumber ) /* PRIVILEGED_FUNCTION */
1208 extern TaskHandle_t pxCurrentTCB;
1209 extern UBaseType_t uxSystemCallImplementations[ NUM_SYSTEM_CALLS ];
1210 xMPU_SETTINGS * pxMpuSettings;
1211 uint32_t * pulSystemCallStack;
1212 uint32_t ulStackFrameSize, ulSystemCallLocation, i;
1214 #if defined( __ARMCC_VERSION )
1215 /* Declaration when these variable are defined in code instead of being
1216 * exported from linker scripts. */
1217 extern uint32_t * __syscalls_flash_start__;
1218 extern uint32_t * __syscalls_flash_end__;
1220 /* Declaration when these variable are exported from linker scripts. */
1221 extern uint32_t __syscalls_flash_start__[];
1222 extern uint32_t __syscalls_flash_end__[];
1223 #endif /* #if defined( __ARMCC_VERSION ) */
1225 ulSystemCallLocation = pulTaskStack[ portOFFSET_TO_PC ];
1226 pxMpuSettings = xTaskGetMPUSettings( pxCurrentTCB );
1229 * 1. SVC is raised from the system call section (i.e. application is
1230 * not raising SVC directly).
1231 * 2. pxMpuSettings->xSystemCallStackInfo.pulTaskStack must be NULL as
1232 * it is non-NULL only during the execution of a system call (i.e.
1233 * between system call enter and exit).
1234 * 3. System call is not for a kernel API disabled by the configuration
1235 * in FreeRTOSConfig.h.
1236 * 4. We do not need to check that ucSystemCallNumber is within range
1237 * because the assembly SVC handler checks that before calling
1240 if( ( ulSystemCallLocation >= ( uint32_t ) __syscalls_flash_start__ ) &&
1241 ( ulSystemCallLocation <= ( uint32_t ) __syscalls_flash_end__ ) &&
1242 ( pxMpuSettings->xSystemCallStackInfo.pulTaskStack == NULL ) &&
1243 ( uxSystemCallImplementations[ ucSystemCallNumber ] != ( UBaseType_t ) 0 ) )
1245 pulSystemCallStack = pxMpuSettings->xSystemCallStackInfo.pulSystemCallStack;
1247 #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
1249 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
1251 /* Extended frame i.e. FPU in use. */
1252 ulStackFrameSize = 26;
1254 " vpush {s0} \n" /* Trigger lazy stacking. */
1255 " vpop {s0} \n" /* Nullify the affect of the above instruction. */
1261 /* Standard frame i.e. FPU not in use. */
1262 ulStackFrameSize = 8;
1265 #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
1267 ulStackFrameSize = 8;
1269 #endif /* configENABLE_FPU || configENABLE_MVE */
1271 /* Make space on the system call stack for the stack frame. */
1272 pulSystemCallStack = pulSystemCallStack - ulStackFrameSize;
1274 /* Copy the stack frame. */
1275 for( i = 0; i < ulStackFrameSize; i++ )
1277 pulSystemCallStack[ i ] = pulTaskStack[ i ];
1280 /* Store the value of the Link Register before the SVC was raised.
1281 * It contains the address of the caller of the System Call entry
1282 * point (i.e. the caller of the MPU_<API>). We need to restore it
1283 * when we exit from the system call. */
1284 pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry = pulTaskStack[ portOFFSET_TO_LR ];
1285 /* Store the value of the PSPLIM register before the SVC was raised.
1286 * We need to restore it when we exit from the system call. */
1287 #if ( portUSE_PSPLIM_REGISTER == 1 )
1289 __asm volatile ( "mrs %0, psplim" : "=r" ( pxMpuSettings->xSystemCallStackInfo.ulStackLimitRegisterAtSystemCallEntry ) );
1293 /* Use the pulSystemCallStack in thread mode. */
1294 __asm volatile ( "msr psp, %0" : : "r" ( pulSystemCallStack ) );
1295 #if ( portUSE_PSPLIM_REGISTER == 1 )
1297 __asm volatile ( "msr psplim, %0" : : "r" ( pxMpuSettings->xSystemCallStackInfo.pulSystemCallStackLimit ) );
1301 /* Start executing the system call upon returning from this handler. */
1302 pulSystemCallStack[ portOFFSET_TO_PC ] = uxSystemCallImplementations[ ucSystemCallNumber ];
1303 /* Raise a request to exit from the system call upon finishing the
1305 pulSystemCallStack[ portOFFSET_TO_LR ] = ( uint32_t ) vRequestSystemCallExit;
1307 /* Remember the location where we should copy the stack frame when we exit from
1308 * the system call. */
1309 pxMpuSettings->xSystemCallStackInfo.pulTaskStack = pulTaskStack + ulStackFrameSize;
1311 /* Record if the hardware used padding to force the stack pointer
1312 * to be double word aligned. */
1313 if( ( pulTaskStack[ portOFFSET_TO_PSR ] & portPSR_STACK_PADDING_MASK ) == portPSR_STACK_PADDING_MASK )
1315 pxMpuSettings->ulTaskFlags |= portSTACK_FRAME_HAS_PADDING_FLAG;
1319 pxMpuSettings->ulTaskFlags &= ( ~portSTACK_FRAME_HAS_PADDING_FLAG );
1322 /* We ensure in pxPortInitialiseStack that the system call stack is
1323 * double word aligned and therefore, there is no need of padding.
1324 * Clear the bit[9] of stacked xPSR. */
1325 pulSystemCallStack[ portOFFSET_TO_PSR ] &= ( ~portPSR_STACK_PADDING_MASK );
1327 /* Raise the privilege for the duration of the system call. */
1329 " mrs r0, control \n" /* Obtain current control value. */
1330 " movs r1, #1 \n" /* r1 = 1. */
1331 " bics r0, r1 \n" /* Clear nPRIV bit. */
1332 " msr control, r0 \n" /* Write back new control value. */
1333 ::: "r0", "r1", "memory"
1338 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
1339 /*-----------------------------------------------------------*/
1341 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
1343 void vRequestSystemCallExit( void ) /* __attribute__( ( naked ) ) PRIVILEGED_FUNCTION */
1345 __asm volatile ( "svc %0 \n" ::"i" ( portSVC_SYSTEM_CALL_EXIT ) : "memory" );
1348 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
1349 /*-----------------------------------------------------------*/
1351 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
1353 void vSystemCallExit( uint32_t * pulSystemCallStack,
1354 uint32_t ulLR ) /* PRIVILEGED_FUNCTION */
1356 extern TaskHandle_t pxCurrentTCB;
1357 xMPU_SETTINGS * pxMpuSettings;
1358 uint32_t * pulTaskStack;
1359 uint32_t ulStackFrameSize, ulSystemCallLocation, i;
1361 #if defined( __ARMCC_VERSION )
1362 /* Declaration when these variable are defined in code instead of being
1363 * exported from linker scripts. */
1364 extern uint32_t * __privileged_functions_start__;
1365 extern uint32_t * __privileged_functions_end__;
1367 /* Declaration when these variable are exported from linker scripts. */
1368 extern uint32_t __privileged_functions_start__[];
1369 extern uint32_t __privileged_functions_end__[];
1370 #endif /* #if defined( __ARMCC_VERSION ) */
1372 ulSystemCallLocation = pulSystemCallStack[ portOFFSET_TO_PC ];
1373 pxMpuSettings = xTaskGetMPUSettings( pxCurrentTCB );
1376 * 1. SVC is raised from the privileged code (i.e. application is not
1377 * raising SVC directly). This SVC is only raised from
1378 * vRequestSystemCallExit which is in the privileged code section.
1379 * 2. pxMpuSettings->xSystemCallStackInfo.pulTaskStack must not be NULL -
1380 * this means that we previously entered a system call and the
1381 * application is not attempting to exit without entering a system
1384 if( ( ulSystemCallLocation >= ( uint32_t ) __privileged_functions_start__ ) &&
1385 ( ulSystemCallLocation <= ( uint32_t ) __privileged_functions_end__ ) &&
1386 ( pxMpuSettings->xSystemCallStackInfo.pulTaskStack != NULL ) )
1388 pulTaskStack = pxMpuSettings->xSystemCallStackInfo.pulTaskStack;
1390 #if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) )
1392 if( ( ulLR & portEXC_RETURN_STACK_FRAME_TYPE_MASK ) == 0UL )
1394 /* Extended frame i.e. FPU in use. */
1395 ulStackFrameSize = 26;
1397 " vpush {s0} \n" /* Trigger lazy stacking. */
1398 " vpop {s0} \n" /* Nullify the affect of the above instruction. */
1404 /* Standard frame i.e. FPU not in use. */
1405 ulStackFrameSize = 8;
1408 #else /* if ( ( configENABLE_FPU == 1 ) || ( configENABLE_MVE == 1 ) ) */
1410 ulStackFrameSize = 8;
1412 #endif /* configENABLE_FPU || configENABLE_MVE */
1414 /* Make space on the task stack for the stack frame. */
1415 pulTaskStack = pulTaskStack - ulStackFrameSize;
1417 /* Copy the stack frame. */
1418 for( i = 0; i < ulStackFrameSize; i++ )
1420 pulTaskStack[ i ] = pulSystemCallStack[ i ];
1423 /* Use the pulTaskStack in thread mode. */
1424 __asm volatile ( "msr psp, %0" : : "r" ( pulTaskStack ) );
1426 /* Return to the caller of the System Call entry point (i.e. the
1427 * caller of the MPU_<API>). */
1428 pulTaskStack[ portOFFSET_TO_PC ] = pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry;
1429 /* Ensure that LR has a valid value.*/
1430 pulTaskStack[ portOFFSET_TO_LR ] = pxMpuSettings->xSystemCallStackInfo.ulLinkRegisterAtSystemCallEntry;
1432 /* Restore the PSPLIM register to what it was at the time of
1433 * system call entry. */
1434 #if ( portUSE_PSPLIM_REGISTER == 1 )
1436 __asm volatile ( "msr psplim, %0" : : "r" ( pxMpuSettings->xSystemCallStackInfo.ulStackLimitRegisterAtSystemCallEntry ) );
1440 /* If the hardware used padding to force the stack pointer
1441 * to be double word aligned, set the stacked xPSR bit[9],
1442 * otherwise clear it. */
1443 if( ( pxMpuSettings->ulTaskFlags & portSTACK_FRAME_HAS_PADDING_FLAG ) == portSTACK_FRAME_HAS_PADDING_FLAG )
1445 pulTaskStack[ portOFFSET_TO_PSR ] |= portPSR_STACK_PADDING_MASK;
1449 pulTaskStack[ portOFFSET_TO_PSR ] &= ( ~portPSR_STACK_PADDING_MASK );
1452 /* This is not NULL only for the duration of the system call. */
1453 pxMpuSettings->xSystemCallStackInfo.pulTaskStack = NULL;
1455 /* Drop the privilege before returning to the thread mode. */
1457 " mrs r0, control \n" /* Obtain current control value. */
1458 " movs r1, #1 \n" /* r1 = 1. */
1459 " orrs r0, r1 \n" /* Set nPRIV bit. */
1460 " msr control, r0 \n" /* Write back new control value. */
1461 ::: "r0", "r1", "memory"
1466 #endif /* ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
1467 /*-----------------------------------------------------------*/
1469 #if ( configENABLE_MPU == 1 )
1471 BaseType_t xPortIsTaskPrivileged( void ) /* PRIVILEGED_FUNCTION */
1473 BaseType_t xTaskIsPrivileged = pdFALSE;
1474 const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
1476 if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
1478 xTaskIsPrivileged = pdTRUE;
1481 return xTaskIsPrivileged;
1484 #endif /* configENABLE_MPU == 1 */
1485 /*-----------------------------------------------------------*/
1487 #if ( configENABLE_MPU == 1 )
1489 StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
1490 StackType_t * pxEndOfStack,
1491 TaskFunction_t pxCode,
1492 void * pvParameters,
1493 BaseType_t xRunPrivileged,
1494 xMPU_SETTINGS * xMPUSettings ) /* PRIVILEGED_FUNCTION */
1496 uint32_t ulIndex = 0;
1497 uint32_t ulControl = 0x0;
1499 xMPUSettings->ulContext[ ulIndex ] = 0x04040404; /* r4. */
1501 xMPUSettings->ulContext[ ulIndex ] = 0x05050505; /* r5. */
1503 xMPUSettings->ulContext[ ulIndex ] = 0x06060606; /* r6. */
1505 xMPUSettings->ulContext[ ulIndex ] = 0x07070707; /* r7. */
1507 xMPUSettings->ulContext[ ulIndex ] = 0x08080808; /* r8. */
1509 xMPUSettings->ulContext[ ulIndex ] = 0x09090909; /* r9. */
1511 xMPUSettings->ulContext[ ulIndex ] = 0x10101010; /* r10. */
1513 xMPUSettings->ulContext[ ulIndex ] = 0x11111111; /* r11. */
1516 xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pvParameters; /* r0. */
1518 xMPUSettings->ulContext[ ulIndex ] = 0x01010101; /* r1. */
1520 xMPUSettings->ulContext[ ulIndex ] = 0x02020202; /* r2. */
1522 xMPUSettings->ulContext[ ulIndex ] = 0x03030303; /* r3. */
1524 xMPUSettings->ulContext[ ulIndex ] = 0x12121212; /* r12. */
1526 xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) portTASK_RETURN_ADDRESS; /* LR. */
1528 xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxCode; /* PC. */
1530 xMPUSettings->ulContext[ ulIndex ] = portINITIAL_XPSR; /* xPSR. */
1533 #if ( configENABLE_TRUSTZONE == 1 )
1535 xMPUSettings->ulContext[ ulIndex ] = portNO_SECURE_CONTEXT; /* xSecureContext. */
1538 #endif /* configENABLE_TRUSTZONE */
1539 xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) ( pxTopOfStack - 8 ); /* PSP with the hardware saved stack. */
1541 xMPUSettings->ulContext[ ulIndex ] = ( uint32_t ) pxEndOfStack; /* PSPLIM. */
1544 #if ( portHAS_PACBTI_FEATURE == 1 )
1546 /* Check PACBTI security feature configuration before pushing the
1547 * CONTROL register's value on task's TCB. */
1548 ulControl = prvConfigurePACBTI( pdFALSE );
1550 #endif /* portHAS_PACBTI_FEATURE */
1552 if( xRunPrivileged == pdTRUE )
1554 xMPUSettings->ulTaskFlags |= portTASK_IS_PRIVILEGED_FLAG;
1555 xMPUSettings->ulContext[ ulIndex ] = ( ulControl | ( uint32_t ) portINITIAL_CONTROL_PRIVILEGED ); /* CONTROL. */
1560 xMPUSettings->ulTaskFlags &= ( ~portTASK_IS_PRIVILEGED_FLAG );
1561 xMPUSettings->ulContext[ ulIndex ] = ( ulControl | ( uint32_t ) portINITIAL_CONTROL_UNPRIVILEGED ); /* CONTROL. */
1565 xMPUSettings->ulContext[ ulIndex ] = portINITIAL_EXC_RETURN; /* LR (EXC_RETURN). */
1568 #if ( configUSE_MPU_WRAPPERS_V1 == 0 )
1570 /* Ensure that the system call stack is double word aligned. */
1571 xMPUSettings->xSystemCallStackInfo.pulSystemCallStack = &( xMPUSettings->xSystemCallStackInfo.ulSystemCallStackBuffer[ configSYSTEM_CALL_STACK_SIZE - 1 ] );
1572 xMPUSettings->xSystemCallStackInfo.pulSystemCallStack = ( uint32_t * ) ( ( uint32_t ) ( xMPUSettings->xSystemCallStackInfo.pulSystemCallStack ) &
1573 ( uint32_t ) ( ~( portBYTE_ALIGNMENT_MASK ) ) );
1575 xMPUSettings->xSystemCallStackInfo.pulSystemCallStackLimit = &( xMPUSettings->xSystemCallStackInfo.ulSystemCallStackBuffer[ 0 ] );
1576 xMPUSettings->xSystemCallStackInfo.pulSystemCallStackLimit = ( uint32_t * ) ( ( ( uint32_t ) ( xMPUSettings->xSystemCallStackInfo.pulSystemCallStackLimit ) +
1577 ( uint32_t ) ( portBYTE_ALIGNMENT - 1 ) ) &
1578 ( uint32_t ) ( ~( portBYTE_ALIGNMENT_MASK ) ) );
1580 /* This is not NULL only for the duration of a system call. */
1581 xMPUSettings->xSystemCallStackInfo.pulTaskStack = NULL;
1583 #endif /* configUSE_MPU_WRAPPERS_V1 == 0 */
1585 return &( xMPUSettings->ulContext[ ulIndex ] );
1588 #else /* configENABLE_MPU */
1590 StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
1591 StackType_t * pxEndOfStack,
1592 TaskFunction_t pxCode,
1593 void * pvParameters ) /* PRIVILEGED_FUNCTION */
1595 /* Simulate the stack frame as it would be created by a context switch
1597 #if ( portPRELOAD_REGISTERS == 0 )
1599 pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
1600 *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
1602 *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
1604 *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
1605 pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
1606 *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
1607 pxTopOfStack -= 9; /* R11..R4, EXC_RETURN. */
1608 *pxTopOfStack = portINITIAL_EXC_RETURN;
1610 *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
1612 #if ( configENABLE_TRUSTZONE == 1 )
1615 *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
1617 #endif /* configENABLE_TRUSTZONE */
1619 #else /* portPRELOAD_REGISTERS */
1621 pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */
1622 *pxTopOfStack = portINITIAL_XPSR; /* xPSR. */
1624 *pxTopOfStack = ( StackType_t ) pxCode; /* PC. */
1626 *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR. */
1628 *pxTopOfStack = ( StackType_t ) 0x12121212UL; /* R12. */
1630 *pxTopOfStack = ( StackType_t ) 0x03030303UL; /* R3. */
1632 *pxTopOfStack = ( StackType_t ) 0x02020202UL; /* R2. */
1634 *pxTopOfStack = ( StackType_t ) 0x01010101UL; /* R1. */
1636 *pxTopOfStack = ( StackType_t ) pvParameters; /* R0. */
1638 *pxTopOfStack = ( StackType_t ) 0x11111111UL; /* R11. */
1640 *pxTopOfStack = ( StackType_t ) 0x10101010UL; /* R10. */
1642 *pxTopOfStack = ( StackType_t ) 0x09090909UL; /* R09. */
1644 *pxTopOfStack = ( StackType_t ) 0x08080808UL; /* R08. */
1646 *pxTopOfStack = ( StackType_t ) 0x07070707UL; /* R07. */
1648 *pxTopOfStack = ( StackType_t ) 0x06060606UL; /* R06. */
1650 *pxTopOfStack = ( StackType_t ) 0x05050505UL; /* R05. */
1652 *pxTopOfStack = ( StackType_t ) 0x04040404UL; /* R04. */
1654 *pxTopOfStack = portINITIAL_EXC_RETURN; /* EXC_RETURN. */
1656 *pxTopOfStack = ( StackType_t ) pxEndOfStack; /* Slot used to hold this task's PSPLIM value. */
1658 #if ( configENABLE_TRUSTZONE == 1 )
1661 *pxTopOfStack = portNO_SECURE_CONTEXT; /* Slot used to hold this task's xSecureContext value. */
1663 #endif /* configENABLE_TRUSTZONE */
1665 #endif /* portPRELOAD_REGISTERS */
1667 return pxTopOfStack;
1670 #endif /* configENABLE_MPU */
1671 /*-----------------------------------------------------------*/
1673 BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */
1675 /* An application can install FreeRTOS interrupt handlers in one of the
1677 * 1. Direct Routing - Install the functions SVC_Handler and PendSV_Handler
1678 * for SVCall and PendSV interrupts respectively.
1679 * 2. Indirect Routing - Install separate handlers for SVCall and PendSV
1680 * interrupts and route program control from those handlers to
1681 * SVC_Handler and PendSV_Handler functions.
1683 * Applications that use Indirect Routing must set
1684 * configCHECK_HANDLER_INSTALLATION to 0 in their FreeRTOSConfig.h. Direct
1685 * routing, which is validated here when configCHECK_HANDLER_INSTALLATION
1686 * is 1, should be preferred when possible. */
1687 #if ( configCHECK_HANDLER_INSTALLATION == 1 )
1689 const portISR_t * const pxVectorTable = portSCB_VTOR_REG;
1691 /* Validate that the application has correctly installed the FreeRTOS
1692 * handlers for SVCall and PendSV interrupts. We do not check the
1693 * installation of the SysTick handler because the application may
1694 * choose to drive the RTOS tick using a timer other than the SysTick
1695 * timer by overriding the weak function vPortSetupTimerInterrupt().
1697 * Assertion failures here indicate incorrect installation of the
1698 * FreeRTOS handlers. For help installing the FreeRTOS handlers, see
1699 * https://www.freertos.org/Why-FreeRTOS/FAQs.
1701 * Systems with a configurable address for the interrupt vector table
1702 * can also encounter assertion failures or even system faults here if
1703 * VTOR is not set correctly to point to the application's vector table. */
1704 configASSERT( pxVectorTable[ portVECTOR_INDEX_SVC ] == SVC_Handler );
1705 configASSERT( pxVectorTable[ portVECTOR_INDEX_PENDSV ] == PendSV_Handler );
1707 #endif /* configCHECK_HANDLER_INSTALLATION */
1709 #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
1711 volatile uint32_t ulImplementedPrioBits = 0;
1712 volatile uint8_t ucMaxPriorityValue;
1714 /* Determine the maximum priority from which ISR safe FreeRTOS API
1715 * functions can be called. ISR safe functions are those that end in
1716 * "FromISR". FreeRTOS maintains separate thread and ISR API functions to
1717 * ensure interrupt entry is as fast and simple as possible.
1719 * First, determine the number of priority bits available. Write to all
1720 * possible bits in the priority setting for SVCall. */
1721 portNVIC_SHPR2_REG = 0xFF000000;
1723 /* Read the value back to see how many bits stuck. */
1724 ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 );
1726 /* Use the same mask on the maximum system call priority. */
1727 ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue;
1729 /* Check that the maximum system call priority is nonzero after
1730 * accounting for the number of priority bits supported by the
1731 * hardware. A priority of 0 is invalid because setting the BASEPRI
1732 * register to 0 unmasks all interrupts, and interrupts with priority 0
1733 * cannot be masked using BASEPRI.
1734 * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
1735 configASSERT( ucMaxSysCallPriority );
1737 /* Check that the bits not implemented in hardware are zero in
1738 * configMAX_SYSCALL_INTERRUPT_PRIORITY. */
1739 configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & ( uint8_t ) ( ~( uint32_t ) ucMaxPriorityValue ) ) == 0U );
1741 /* Calculate the maximum acceptable priority group value for the number
1742 * of bits read back. */
1743 while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE )
1745 ulImplementedPrioBits++;
1746 ucMaxPriorityValue <<= ( uint8_t ) 0x01;
1749 if( ulImplementedPrioBits == 8 )
1751 /* When the hardware implements 8 priority bits, there is no way for
1752 * the software to configure PRIGROUP to not have sub-priorities. As
1753 * a result, the least significant bit is always used for sub-priority
1754 * and there are 128 preemption priorities and 2 sub-priorities.
1756 * This may cause some confusion in some cases - for example, if
1757 * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4
1758 * priority interrupts will be masked in Critical Sections as those
1759 * are at the same preemption priority. This may appear confusing as
1760 * 4 is higher (numerically lower) priority than
1761 * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not
1762 * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY
1763 * to 4, this confusion does not happen and the behaviour remains the same.
1765 * The following assert ensures that the sub-priority bit in the
1766 * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned
1768 configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U );
1769 ulMaxPRIGROUPValue = 0;
1773 ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits;
1776 /* Shift the priority group value back to its position within the AIRCR
1778 ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT;
1779 ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK;
1781 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
1783 /* Make PendSV and SysTick the lowest priority interrupts, and make SVCall
1784 * the highest priority. */
1785 portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
1786 portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
1787 portNVIC_SHPR2_REG = 0;
1789 #if ( portHAS_PACBTI_FEATURE == 1 )
1791 /* Set the CONTROL register value based on PACBTI security feature
1792 * configuration before starting the first task. */
1793 ( void) prvConfigurePACBTI( pdTRUE );
1795 #endif /* portHAS_PACBTI_FEATURE */
1797 #if ( configENABLE_MPU == 1 )
1799 /* Setup the Memory Protection Unit (MPU). */
1802 #endif /* configENABLE_MPU */
1804 /* Start the timer that generates the tick ISR. Interrupts are disabled
1806 vPortSetupTimerInterrupt();
1808 /* Initialize the critical nesting count ready for the first task. */
1809 ulCriticalNesting = 0;
1811 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
1813 xSchedulerRunning = pdTRUE;
1815 #endif /* ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) */
1817 /* Start the first task. */
1820 /* Should never get here as the tasks will now be executing. Call the task
1821 * exit error function to prevent compiler warnings about a static function
1822 * not being called in the case that the application writer overrides this
1823 * functionality by defining configTASK_RETURN_ADDRESS. Call
1824 * vTaskSwitchContext() so link time optimization does not remove the
1826 vTaskSwitchContext();
1829 /* Should not get here. */
1832 /*-----------------------------------------------------------*/
1834 void vPortEndScheduler( void ) /* PRIVILEGED_FUNCTION */
1836 /* Not implemented in ports where there is nothing to return to.
1837 * Artificially force an assert. */
1838 configASSERT( ulCriticalNesting == 1000UL );
1840 /*-----------------------------------------------------------*/
1842 #if ( configENABLE_MPU == 1 )
1844 void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
1845 const struct xMEMORY_REGION * const xRegions,
1846 StackType_t * pxBottomOfStack,
1847 configSTACK_DEPTH_TYPE uxStackDepth )
1849 uint32_t ulRegionStartAddress, ulRegionEndAddress, ulRegionNumber;
1852 #if defined( __ARMCC_VERSION )
1854 /* Declaration when these variable are defined in code instead of being
1855 * exported from linker scripts. */
1856 extern uint32_t * __privileged_sram_start__;
1857 extern uint32_t * __privileged_sram_end__;
1859 /* Declaration when these variable are exported from linker scripts. */
1860 extern uint32_t __privileged_sram_start__[];
1861 extern uint32_t __privileged_sram_end__[];
1862 #endif /* defined( __ARMCC_VERSION ) */
1865 xMPUSettings->ulMAIR0 = ( ( portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE << portMPU_MAIR_ATTR0_POS ) & portMPU_MAIR_ATTR0_MASK );
1866 xMPUSettings->ulMAIR0 |= ( ( portMPU_DEVICE_MEMORY_nGnRE << portMPU_MAIR_ATTR1_POS ) & portMPU_MAIR_ATTR1_MASK );
1868 /* This function is called automatically when the task is created - in
1869 * which case the stack region parameters will be valid. At all other
1870 * times the stack parameters will not be valid and it is assumed that
1871 * the stack region has already been configured. */
1872 if( uxStackDepth > 0 )
1874 ulRegionStartAddress = ( uint32_t ) pxBottomOfStack;
1875 ulRegionEndAddress = ( uint32_t ) pxBottomOfStack + ( uxStackDepth * ( configSTACK_DEPTH_TYPE ) sizeof( StackType_t ) ) - 1;
1877 /* If the stack is within the privileged SRAM, do not protect it
1878 * using a separate MPU region. This is needed because privileged
1879 * SRAM is already protected using an MPU region and ARMv8-M does
1880 * not allow overlapping MPU regions. */
1881 if( ( ulRegionStartAddress >= ( uint32_t ) __privileged_sram_start__ ) &&
1882 ( ulRegionEndAddress <= ( uint32_t ) __privileged_sram_end__ ) )
1884 xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = 0;
1885 xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = 0;
1889 /* Define the region that allows access to the stack. */
1890 ulRegionStartAddress &= portMPU_RBAR_ADDRESS_MASK;
1891 ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
1893 xMPUSettings->xRegionsSettings[ 0 ].ulRBAR = ( ulRegionStartAddress ) |
1894 ( portMPU_REGION_NON_SHAREABLE ) |
1895 ( portMPU_REGION_READ_WRITE ) |
1896 ( portMPU_REGION_EXECUTE_NEVER );
1898 xMPUSettings->xRegionsSettings[ 0 ].ulRLAR = ( ulRegionEndAddress ) |
1899 ( portMPU_RLAR_ATTR_INDEX0 ) |
1900 ( portMPU_RLAR_REGION_ENABLE );
1904 /* User supplied configurable regions. */
1905 for( ulRegionNumber = 1; ulRegionNumber <= portNUM_CONFIGURABLE_REGIONS; ulRegionNumber++ )
1907 /* If xRegions is NULL i.e. the task has not specified any MPU
1908 * region, the else part ensures that all the configurable MPU
1909 * regions are invalidated. */
1910 if( ( xRegions != NULL ) && ( xRegions[ lIndex ].ulLengthInBytes > 0UL ) )
1912 /* Translate the generic region definition contained in xRegions
1913 * into the ARMv8 specific MPU settings that are then stored in
1915 ulRegionStartAddress = ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) & portMPU_RBAR_ADDRESS_MASK;
1916 ulRegionEndAddress = ( uint32_t ) xRegions[ lIndex ].pvBaseAddress + xRegions[ lIndex ].ulLengthInBytes - 1;
1917 ulRegionEndAddress &= portMPU_RLAR_ADDRESS_MASK;
1919 /* Start address. */
1920 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = ( ulRegionStartAddress ) |
1921 ( portMPU_REGION_NON_SHAREABLE );
1924 if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_READ_ONLY ) != 0 )
1926 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_ONLY );
1930 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_READ_WRITE );
1934 if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_EXECUTE_NEVER ) != 0 )
1936 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR |= ( portMPU_REGION_EXECUTE_NEVER );
1940 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = ( ulRegionEndAddress ) |
1941 ( portMPU_RLAR_REGION_ENABLE );
1944 #if ( portARMV8M_MINOR_VERSION >= 1 )
1946 if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_PRIVILEGED_EXECUTE_NEVER ) != 0 )
1948 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= ( portMPU_RLAR_PRIVILEGED_EXECUTE_NEVER );
1951 #endif /* portARMV8M_MINOR_VERSION >= 1 */
1953 /* Normal memory/ Device memory. */
1954 if( ( xRegions[ lIndex ].ulParameters & tskMPU_REGION_DEVICE_MEMORY ) != 0 )
1956 /* Attr1 in MAIR0 is configured as device memory. */
1957 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX1;
1961 /* Attr0 in MAIR0 is configured as normal memory. */
1962 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR |= portMPU_RLAR_ATTR_INDEX0;
1967 /* Invalidate the region. */
1968 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRBAR = 0UL;
1969 xMPUSettings->xRegionsSettings[ ulRegionNumber ].ulRLAR = 0UL;
1976 #endif /* configENABLE_MPU */
1977 /*-----------------------------------------------------------*/
1979 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
1981 BaseType_t xPortIsAuthorizedToAccessBuffer( const void * pvBuffer,
1982 uint32_t ulBufferLength,
1983 uint32_t ulAccessRequested ) /* PRIVILEGED_FUNCTION */
1986 uint32_t i, ulBufferStartAddress, ulBufferEndAddress;
1987 BaseType_t xAccessGranted = pdFALSE;
1988 const xMPU_SETTINGS * xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
1990 if( xSchedulerRunning == pdFALSE )
1992 /* Grant access to all the kernel objects before the scheduler
1993 * is started. It is necessary because there is no task running
1994 * yet and therefore, we cannot use the permissions of any
1996 xAccessGranted = pdTRUE;
1998 else if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
2000 xAccessGranted = pdTRUE;
2004 if( portADD_UINT32_WILL_OVERFLOW( ( ( uint32_t ) pvBuffer ), ( ulBufferLength - 1UL ) ) == pdFALSE )
2006 ulBufferStartAddress = ( uint32_t ) pvBuffer;
2007 ulBufferEndAddress = ( ( ( uint32_t ) pvBuffer ) + ulBufferLength - 1UL );
2009 for( i = 0; i < portTOTAL_NUM_REGIONS; i++ )
2011 /* Is the MPU region enabled? */
2012 if( ( xTaskMpuSettings->xRegionsSettings[ i ].ulRLAR & portMPU_RLAR_REGION_ENABLE ) == portMPU_RLAR_REGION_ENABLE )
2014 if( portIS_ADDRESS_WITHIN_RANGE( ulBufferStartAddress,
2015 portEXTRACT_FIRST_ADDRESS_FROM_RBAR( xTaskMpuSettings->xRegionsSettings[ i ].ulRBAR ),
2016 portEXTRACT_LAST_ADDRESS_FROM_RLAR( xTaskMpuSettings->xRegionsSettings[ i ].ulRLAR ) ) &&
2017 portIS_ADDRESS_WITHIN_RANGE( ulBufferEndAddress,
2018 portEXTRACT_FIRST_ADDRESS_FROM_RBAR( xTaskMpuSettings->xRegionsSettings[ i ].ulRBAR ),
2019 portEXTRACT_LAST_ADDRESS_FROM_RLAR( xTaskMpuSettings->xRegionsSettings[ i ].ulRLAR ) ) &&
2020 portIS_AUTHORIZED( ulAccessRequested,
2021 prvGetRegionAccessPermissions( xTaskMpuSettings->xRegionsSettings[ i ].ulRBAR ) ) )
2023 xAccessGranted = pdTRUE;
2031 return xAccessGranted;
2034 #endif /* #if ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) */
2035 /*-----------------------------------------------------------*/
2037 BaseType_t xPortIsInsideInterrupt( void )
2039 uint32_t ulCurrentInterrupt;
2042 /* Obtain the number of the currently executing interrupt. Interrupt Program
2043 * Status Register (IPSR) holds the exception number of the currently-executing
2044 * exception or zero for Thread mode.*/
2045 __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
2047 if( ulCurrentInterrupt == 0 )
2058 /*-----------------------------------------------------------*/
2060 #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) )
2062 void vPortValidateInterruptPriority( void )
2064 uint32_t ulCurrentInterrupt;
2065 uint8_t ucCurrentPriority;
2067 /* Obtain the number of the currently executing interrupt. */
2068 __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
2070 /* Is the interrupt number a user defined interrupt? */
2071 if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER )
2073 /* Look up the interrupt's priority. */
2074 ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ];
2076 /* The following assertion will fail if a service routine (ISR) for
2077 * an interrupt that has been assigned a priority above
2078 * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
2079 * function. ISR safe FreeRTOS API functions must *only* be called
2080 * from interrupts that have been assigned a priority at or below
2081 * configMAX_SYSCALL_INTERRUPT_PRIORITY.
2083 * Numerically low interrupt priority numbers represent logically high
2084 * interrupt priorities, therefore the priority of the interrupt must
2085 * be set to a value equal to or numerically *higher* than
2086 * configMAX_SYSCALL_INTERRUPT_PRIORITY.
2088 * Interrupts that use the FreeRTOS API must not be left at their
2089 * default priority of zero as that is the highest possible priority,
2090 * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY,
2091 * and therefore also guaranteed to be invalid.
2093 * FreeRTOS maintains separate thread and ISR API functions to ensure
2094 * interrupt entry is as fast and simple as possible.
2096 * The following links provide detailed information:
2097 * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html
2098 * https://www.freertos.org/Why-FreeRTOS/FAQs */
2099 configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );
2102 /* Priority grouping: The interrupt controller (NVIC) allows the bits
2103 * that define each interrupt's priority to be split between bits that
2104 * define the interrupt's pre-emption priority bits and bits that define
2105 * the interrupt's sub-priority. For simplicity all bits must be defined
2106 * to be pre-emption priority bits. The following assertion will fail if
2107 * this is not the case (if some bits represent a sub-priority).
2109 * If the application only uses CMSIS libraries for interrupt
2110 * configuration then the correct setting can be achieved on all Cortex-M
2111 * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the
2112 * scheduler. Note however that some vendor specific peripheral libraries
2113 * assume a non-zero priority group setting, in which cases using a value
2114 * of zero will result in unpredictable behaviour. */
2115 configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue );
2118 #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */
2119 /*-----------------------------------------------------------*/
2121 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
2123 void vPortGrantAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
2124 int32_t lInternalIndexOfKernelObject ) /* PRIVILEGED_FUNCTION */
2126 uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit;
2127 xMPU_SETTINGS * xTaskMpuSettings;
2129 ulAccessControlListEntryIndex = ( ( uint32_t ) lInternalIndexOfKernelObject / portACL_ENTRY_SIZE_BITS );
2130 ulAccessControlListEntryBit = ( ( uint32_t ) lInternalIndexOfKernelObject % portACL_ENTRY_SIZE_BITS );
2132 xTaskMpuSettings = xTaskGetMPUSettings( xInternalTaskHandle );
2134 xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] |= ( 1U << ulAccessControlListEntryBit );
2137 #endif /* #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) ) */
2138 /*-----------------------------------------------------------*/
2140 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) )
2142 void vPortRevokeAccessToKernelObject( TaskHandle_t xInternalTaskHandle,
2143 int32_t lInternalIndexOfKernelObject ) /* PRIVILEGED_FUNCTION */
2145 uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit;
2146 xMPU_SETTINGS * xTaskMpuSettings;
2148 ulAccessControlListEntryIndex = ( ( uint32_t ) lInternalIndexOfKernelObject / portACL_ENTRY_SIZE_BITS );
2149 ulAccessControlListEntryBit = ( ( uint32_t ) lInternalIndexOfKernelObject % portACL_ENTRY_SIZE_BITS );
2151 xTaskMpuSettings = xTaskGetMPUSettings( xInternalTaskHandle );
2153 xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] &= ~( 1U << ulAccessControlListEntryBit );
2156 #endif /* #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) && ( configENABLE_ACCESS_CONTROL_LIST == 1 ) ) */
2157 /*-----------------------------------------------------------*/
2159 #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) )
2161 #if ( configENABLE_ACCESS_CONTROL_LIST == 1 )
2163 BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject ) /* PRIVILEGED_FUNCTION */
2165 uint32_t ulAccessControlListEntryIndex, ulAccessControlListEntryBit;
2166 BaseType_t xAccessGranted = pdFALSE;
2167 const xMPU_SETTINGS * xTaskMpuSettings;
2169 if( xSchedulerRunning == pdFALSE )
2171 /* Grant access to all the kernel objects before the scheduler
2172 * is started. It is necessary because there is no task running
2173 * yet and therefore, we cannot use the permissions of any
2175 xAccessGranted = pdTRUE;
2179 xTaskMpuSettings = xTaskGetMPUSettings( NULL ); /* Calling task's MPU settings. */
2181 ulAccessControlListEntryIndex = ( ( uint32_t ) lInternalIndexOfKernelObject / portACL_ENTRY_SIZE_BITS );
2182 ulAccessControlListEntryBit = ( ( uint32_t ) lInternalIndexOfKernelObject % portACL_ENTRY_SIZE_BITS );
2184 if( ( xTaskMpuSettings->ulTaskFlags & portTASK_IS_PRIVILEGED_FLAG ) == portTASK_IS_PRIVILEGED_FLAG )
2186 xAccessGranted = pdTRUE;
2190 if( ( xTaskMpuSettings->ulAccessControlList[ ulAccessControlListEntryIndex ] & ( 1U << ulAccessControlListEntryBit ) ) != 0 )
2192 xAccessGranted = pdTRUE;
2197 return xAccessGranted;
2200 #else /* #if ( configENABLE_ACCESS_CONTROL_LIST == 1 ) */
2202 BaseType_t xPortIsAuthorizedToAccessKernelObject( int32_t lInternalIndexOfKernelObject ) /* PRIVILEGED_FUNCTION */
2204 ( void ) lInternalIndexOfKernelObject;
2206 /* If Access Control List feature is not used, all the tasks have
2207 * access to all the kernel objects. */
2211 #endif /* #if ( configENABLE_ACCESS_CONTROL_LIST == 1 ) */
2213 #endif /* #if ( ( configENABLE_MPU == 1 ) && ( configUSE_MPU_WRAPPERS_V1 == 0 ) ) */
2214 /*-----------------------------------------------------------*/
2216 #if ( portHAS_PACBTI_FEATURE == 1 )
2218 static uint32_t prvConfigurePACBTI( BaseType_t xWriteControlRegister )
2220 uint32_t ulControl = 0x0;
2222 /* Ensure that PACBTI is implemented. */
2223 configASSERT( portID_ISAR5_REG != 0x0 );
2225 /* Enable UsageFault exception if PAC or BTI is enabled. */
2226 #if( ( configENABLE_PAC == 1 ) || ( configENABLE_BTI == 1 ) )
2228 portSCB_SYS_HANDLER_CTRL_STATE_REG |= portSCB_USG_FAULT_ENABLE_BIT;
2232 #if( configENABLE_PAC == 1 )
2234 ulControl |= ( portCONTROL_UPAC_EN | portCONTROL_PAC_EN );
2238 #if( configENABLE_BTI == 1 )
2240 ulControl |= ( portCONTROL_UBTI_EN | portCONTROL_BTI_EN );
2244 if( xWriteControlRegister == pdTRUE )
2246 __asm volatile ( "msr control, %0" : : "r" ( ulControl ) );
2252 #endif /* #if ( portHAS_PACBTI_FEATURE == 1 ) */
2253 /*-----------------------------------------------------------*/