diff --git a/portable/ARMv8M/non_secure/port.c b/portable/ARMv8M/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/ARMv8M/non_secure/port.c +++ b/portable/ARMv8M/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23/portmacro.h b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23/portmacro.h index 5fd94c1c3..233ea5a57 100644 --- a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23/portmacro.h @@ -48,9 +48,9 @@ /** * Architecture specifics. */ -#define portARCH_NAME "Cortex-M23" -#define portHAS_BASEPRI 0 -#define portDONT_DISCARD __attribute__( ( used ) ) +#define portARCH_NAME "Cortex-M23" +#define portHAS_ARMV8M_MAIN_EXTENSION 0 +#define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ /* ARMv8-M common port configurations. */ diff --git a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23_NTZ/portmacro.h b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23_NTZ/portmacro.h index 5fd94c1c3..233ea5a57 100644 --- a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23_NTZ/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23_NTZ/portmacro.h @@ -48,9 +48,9 @@ /** * Architecture specifics. */ -#define portARCH_NAME "Cortex-M23" -#define portHAS_BASEPRI 0 -#define portDONT_DISCARD __attribute__( ( used ) ) +#define portARCH_NAME "Cortex-M23" +#define portHAS_ARMV8M_MAIN_EXTENSION 0 +#define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ /* ARMv8-M common port configurations. */ diff --git a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM33/portmacro.h b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM33/portmacro.h index b9efb07dd..428d38f0a 100644 --- a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM33/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM33/portmacro.h @@ -49,7 +49,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M33" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ diff --git a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM33_NTZ/portmacro.h b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM33_NTZ/portmacro.h index b9efb07dd..428d38f0a 100644 --- a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM33_NTZ/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM33_NTZ/portmacro.h @@ -49,7 +49,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M33" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ diff --git a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM35P/portmacro.h b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM35P/portmacro.h index 9545737c5..6e4fe5a3d 100644 --- a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM35P/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM35P/portmacro.h @@ -49,7 +49,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M35P" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ diff --git a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM55/portmacro.h b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM55/portmacro.h index 12bb5e7c4..cce022882 100644 --- a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM55/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM55/portmacro.h @@ -54,7 +54,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M55" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ diff --git a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM85/portmacro.h b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM85/portmacro.h index 99f913d34..d14448927 100644 --- a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM85/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM85/portmacro.h @@ -54,7 +54,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M85" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ diff --git a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM23/portmacro.h b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM23/portmacro.h index 9cf0e87fb..76ba7172e 100644 --- a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM23/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM23/portmacro.h @@ -48,9 +48,9 @@ /** * Architecture specifics. */ -#define portARCH_NAME "Cortex-M23" -#define portHAS_BASEPRI 0 -#define portDONT_DISCARD __root +#define portARCH_NAME "Cortex-M23" +#define portHAS_ARMV8M_MAIN_EXTENSION 0 +#define portDONT_DISCARD __root /*-----------------------------------------------------------*/ /* ARMv8-M common port configurations. */ diff --git a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM23_NTZ/portmacro.h b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM23_NTZ/portmacro.h index 9cf0e87fb..76ba7172e 100644 --- a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM23_NTZ/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM23_NTZ/portmacro.h @@ -48,9 +48,9 @@ /** * Architecture specifics. */ -#define portARCH_NAME "Cortex-M23" -#define portHAS_BASEPRI 0 -#define portDONT_DISCARD __root +#define portARCH_NAME "Cortex-M23" +#define portHAS_ARMV8M_MAIN_EXTENSION 0 +#define portDONT_DISCARD __root /*-----------------------------------------------------------*/ /* ARMv8-M common port configurations. */ diff --git a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM33/portmacro.h b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM33/portmacro.h index 380768fc0..145f5246e 100644 --- a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM33/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM33/portmacro.h @@ -49,7 +49,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M33" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ diff --git a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM33_NTZ/portmacro.h b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM33_NTZ/portmacro.h index 815dca086..445f0765a 100644 --- a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM33_NTZ/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM33_NTZ/portmacro.h @@ -49,7 +49,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M33" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ diff --git a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM35P/portmacro.h b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM35P/portmacro.h index 46bc4e24b..5669c1f60 100644 --- a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM35P/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM35P/portmacro.h @@ -49,7 +49,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M35P" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ diff --git a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM55/portmacro.h b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM55/portmacro.h index 7829ee618..10596e8e5 100644 --- a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM55/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM55/portmacro.h @@ -54,7 +54,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M55" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ diff --git a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM85/portmacro.h b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM85/portmacro.h index 3b51cb5ff..374150262 100644 --- a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM85/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM85/portmacro.h @@ -54,7 +54,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M85" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ diff --git a/portable/ARMv8M/non_secure/portmacrocommon.h b/portable/ARMv8M/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/ARMv8M/non_secure/portmacrocommon.h +++ b/portable/ARMv8M/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/GCC/ARM_CM23/non_secure/port.c b/portable/GCC/ARM_CM23/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/GCC/ARM_CM23/non_secure/port.c +++ b/portable/GCC/ARM_CM23/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM23/non_secure/portmacro.h b/portable/GCC/ARM_CM23/non_secure/portmacro.h index 5fd94c1c3..233ea5a57 100644 --- a/portable/GCC/ARM_CM23/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM23/non_secure/portmacro.h @@ -48,9 +48,9 @@ /** * Architecture specifics. */ -#define portARCH_NAME "Cortex-M23" -#define portHAS_BASEPRI 0 -#define portDONT_DISCARD __attribute__( ( used ) ) +#define portARCH_NAME "Cortex-M23" +#define portHAS_ARMV8M_MAIN_EXTENSION 0 +#define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ /* ARMv8-M common port configurations. */ diff --git a/portable/GCC/ARM_CM23/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM23/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/GCC/ARM_CM23/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM23/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/GCC/ARM_CM23_NTZ/non_secure/port.c b/portable/GCC/ARM_CM23_NTZ/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/GCC/ARM_CM23_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM23_NTZ/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM23_NTZ/non_secure/portmacro.h b/portable/GCC/ARM_CM23_NTZ/non_secure/portmacro.h index 5fd94c1c3..233ea5a57 100644 --- a/portable/GCC/ARM_CM23_NTZ/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM23_NTZ/non_secure/portmacro.h @@ -48,9 +48,9 @@ /** * Architecture specifics. */ -#define portARCH_NAME "Cortex-M23" -#define portHAS_BASEPRI 0 -#define portDONT_DISCARD __attribute__( ( used ) ) +#define portARCH_NAME "Cortex-M23" +#define portHAS_ARMV8M_MAIN_EXTENSION 0 +#define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ /* ARMv8-M common port configurations. */ diff --git a/portable/GCC/ARM_CM23_NTZ/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM23_NTZ/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/GCC/ARM_CM23_NTZ/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM23_NTZ/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/GCC/ARM_CM33/non_secure/port.c b/portable/GCC/ARM_CM33/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/GCC/ARM_CM33/non_secure/port.c +++ b/portable/GCC/ARM_CM33/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33/non_secure/portmacro.h b/portable/GCC/ARM_CM33/non_secure/portmacro.h index b9efb07dd..428d38f0a 100644 --- a/portable/GCC/ARM_CM33/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM33/non_secure/portmacro.h @@ -49,7 +49,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M33" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM33/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/GCC/ARM_CM33/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM33/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/GCC/ARM_CM33_NTZ/non_secure/port.c b/portable/GCC/ARM_CM33_NTZ/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/GCC/ARM_CM33_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM33_NTZ/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33_NTZ/non_secure/portmacro.h b/portable/GCC/ARM_CM33_NTZ/non_secure/portmacro.h index b9efb07dd..428d38f0a 100644 --- a/portable/GCC/ARM_CM33_NTZ/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM33_NTZ/non_secure/portmacro.h @@ -49,7 +49,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M33" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33_NTZ/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM33_NTZ/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/GCC/ARM_CM33_NTZ/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM33_NTZ/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/GCC/ARM_CM35P/non_secure/port.c b/portable/GCC/ARM_CM35P/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/GCC/ARM_CM35P/non_secure/port.c +++ b/portable/GCC/ARM_CM35P/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM35P/non_secure/portmacro.h b/portable/GCC/ARM_CM35P/non_secure/portmacro.h index 9545737c5..6e4fe5a3d 100644 --- a/portable/GCC/ARM_CM35P/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM35P/non_secure/portmacro.h @@ -49,7 +49,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M35P" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM35P/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM35P/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/GCC/ARM_CM35P/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM35P/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c b/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM35P_NTZ/non_secure/portmacro.h b/portable/GCC/ARM_CM35P_NTZ/non_secure/portmacro.h index 9545737c5..6e4fe5a3d 100644 --- a/portable/GCC/ARM_CM35P_NTZ/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM35P_NTZ/non_secure/portmacro.h @@ -49,7 +49,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M35P" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM35P_NTZ/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM35P_NTZ/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/GCC/ARM_CM35P_NTZ/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM35P_NTZ/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/GCC/ARM_CM55/non_secure/port.c b/portable/GCC/ARM_CM55/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/GCC/ARM_CM55/non_secure/port.c +++ b/portable/GCC/ARM_CM55/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM55/non_secure/portmacro.h b/portable/GCC/ARM_CM55/non_secure/portmacro.h index 12bb5e7c4..cce022882 100644 --- a/portable/GCC/ARM_CM55/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM55/non_secure/portmacro.h @@ -54,7 +54,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M55" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM55/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM55/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/GCC/ARM_CM55/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM55/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/GCC/ARM_CM55_NTZ/non_secure/port.c b/portable/GCC/ARM_CM55_NTZ/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/GCC/ARM_CM55_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM55_NTZ/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM55_NTZ/non_secure/portmacro.h b/portable/GCC/ARM_CM55_NTZ/non_secure/portmacro.h index 12bb5e7c4..cce022882 100644 --- a/portable/GCC/ARM_CM55_NTZ/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM55_NTZ/non_secure/portmacro.h @@ -54,7 +54,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M55" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM55_NTZ/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM55_NTZ/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/GCC/ARM_CM55_NTZ/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM55_NTZ/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/GCC/ARM_CM85/non_secure/port.c b/portable/GCC/ARM_CM85/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/GCC/ARM_CM85/non_secure/port.c +++ b/portable/GCC/ARM_CM85/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM85/non_secure/portmacro.h b/portable/GCC/ARM_CM85/non_secure/portmacro.h index 99f913d34..d14448927 100644 --- a/portable/GCC/ARM_CM85/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM85/non_secure/portmacro.h @@ -54,7 +54,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M85" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM85/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM85/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/GCC/ARM_CM85/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM85/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/GCC/ARM_CM85_NTZ/non_secure/port.c b/portable/GCC/ARM_CM85_NTZ/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/GCC/ARM_CM85_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM85_NTZ/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM85_NTZ/non_secure/portmacro.h b/portable/GCC/ARM_CM85_NTZ/non_secure/portmacro.h index 99f913d34..d14448927 100644 --- a/portable/GCC/ARM_CM85_NTZ/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM85_NTZ/non_secure/portmacro.h @@ -54,7 +54,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M85" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __attribute__( ( used ) ) /*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM85_NTZ/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM85_NTZ/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/GCC/ARM_CM85_NTZ/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM85_NTZ/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/IAR/ARM_CM23/non_secure/port.c b/portable/IAR/ARM_CM23/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/IAR/ARM_CM23/non_secure/port.c +++ b/portable/IAR/ARM_CM23/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM23/non_secure/portmacro.h b/portable/IAR/ARM_CM23/non_secure/portmacro.h index 9cf0e87fb..76ba7172e 100644 --- a/portable/IAR/ARM_CM23/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM23/non_secure/portmacro.h @@ -48,9 +48,9 @@ /** * Architecture specifics. */ -#define portARCH_NAME "Cortex-M23" -#define portHAS_BASEPRI 0 -#define portDONT_DISCARD __root +#define portARCH_NAME "Cortex-M23" +#define portHAS_ARMV8M_MAIN_EXTENSION 0 +#define portDONT_DISCARD __root /*-----------------------------------------------------------*/ /* ARMv8-M common port configurations. */ diff --git a/portable/IAR/ARM_CM23/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM23/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/IAR/ARM_CM23/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM23/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/IAR/ARM_CM23_NTZ/non_secure/port.c b/portable/IAR/ARM_CM23_NTZ/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/IAR/ARM_CM23_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM23_NTZ/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM23_NTZ/non_secure/portmacro.h b/portable/IAR/ARM_CM23_NTZ/non_secure/portmacro.h index 9cf0e87fb..76ba7172e 100644 --- a/portable/IAR/ARM_CM23_NTZ/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM23_NTZ/non_secure/portmacro.h @@ -48,9 +48,9 @@ /** * Architecture specifics. */ -#define portARCH_NAME "Cortex-M23" -#define portHAS_BASEPRI 0 -#define portDONT_DISCARD __root +#define portARCH_NAME "Cortex-M23" +#define portHAS_ARMV8M_MAIN_EXTENSION 0 +#define portDONT_DISCARD __root /*-----------------------------------------------------------*/ /* ARMv8-M common port configurations. */ diff --git a/portable/IAR/ARM_CM23_NTZ/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM23_NTZ/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/IAR/ARM_CM23_NTZ/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM23_NTZ/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/IAR/ARM_CM33/non_secure/port.c b/portable/IAR/ARM_CM33/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/IAR/ARM_CM33/non_secure/port.c +++ b/portable/IAR/ARM_CM33/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM33/non_secure/portmacro.h b/portable/IAR/ARM_CM33/non_secure/portmacro.h index 380768fc0..145f5246e 100644 --- a/portable/IAR/ARM_CM33/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM33/non_secure/portmacro.h @@ -49,7 +49,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M33" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM33/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM33/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/IAR/ARM_CM33/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM33/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/IAR/ARM_CM33_NTZ/non_secure/port.c b/portable/IAR/ARM_CM33_NTZ/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/IAR/ARM_CM33_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM33_NTZ/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM33_NTZ/non_secure/portmacro.h b/portable/IAR/ARM_CM33_NTZ/non_secure/portmacro.h index 815dca086..445f0765a 100644 --- a/portable/IAR/ARM_CM33_NTZ/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM33_NTZ/non_secure/portmacro.h @@ -49,7 +49,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M33" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM33_NTZ/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM33_NTZ/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/IAR/ARM_CM33_NTZ/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM33_NTZ/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/IAR/ARM_CM35P/non_secure/port.c b/portable/IAR/ARM_CM35P/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/IAR/ARM_CM35P/non_secure/port.c +++ b/portable/IAR/ARM_CM35P/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM35P/non_secure/portmacro.h b/portable/IAR/ARM_CM35P/non_secure/portmacro.h index 46bc4e24b..5669c1f60 100644 --- a/portable/IAR/ARM_CM35P/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM35P/non_secure/portmacro.h @@ -49,7 +49,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M35P" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM35P/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM35P/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/IAR/ARM_CM35P/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM35P/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c b/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM35P_NTZ/non_secure/portmacro.h b/portable/IAR/ARM_CM35P_NTZ/non_secure/portmacro.h index 46bc4e24b..5669c1f60 100644 --- a/portable/IAR/ARM_CM35P_NTZ/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM35P_NTZ/non_secure/portmacro.h @@ -49,7 +49,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M35P" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM35P_NTZ/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM35P_NTZ/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/IAR/ARM_CM35P_NTZ/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM35P_NTZ/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/IAR/ARM_CM55/non_secure/port.c b/portable/IAR/ARM_CM55/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/IAR/ARM_CM55/non_secure/port.c +++ b/portable/IAR/ARM_CM55/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM55/non_secure/portmacro.h b/portable/IAR/ARM_CM55/non_secure/portmacro.h index 7829ee618..10596e8e5 100644 --- a/portable/IAR/ARM_CM55/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM55/non_secure/portmacro.h @@ -54,7 +54,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M55" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM55/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM55/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/IAR/ARM_CM55/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM55/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/IAR/ARM_CM55_NTZ/non_secure/port.c b/portable/IAR/ARM_CM55_NTZ/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/IAR/ARM_CM55_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM55_NTZ/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM55_NTZ/non_secure/portmacro.h b/portable/IAR/ARM_CM55_NTZ/non_secure/portmacro.h index 7829ee618..10596e8e5 100644 --- a/portable/IAR/ARM_CM55_NTZ/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM55_NTZ/non_secure/portmacro.h @@ -54,7 +54,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M55" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM55_NTZ/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM55_NTZ/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/IAR/ARM_CM55_NTZ/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM55_NTZ/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/IAR/ARM_CM85/non_secure/port.c b/portable/IAR/ARM_CM85/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/IAR/ARM_CM85/non_secure/port.c +++ b/portable/IAR/ARM_CM85/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM85/non_secure/portmacro.h b/portable/IAR/ARM_CM85/non_secure/portmacro.h index 3b51cb5ff..374150262 100644 --- a/portable/IAR/ARM_CM85/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM85/non_secure/portmacro.h @@ -54,7 +54,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M85" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM85/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM85/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/IAR/ARM_CM85/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM85/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/portable/IAR/ARM_CM85_NTZ/non_secure/port.c b/portable/IAR/ARM_CM85_NTZ/non_secure/port.c index cab1b3668..04901015f 100644 --- a/portable/IAR/ARM_CM85_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM85_NTZ/non_secure/port.c @@ -495,13 +495,13 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; * FreeRTOS API functions are not called from interrupts that have been assigned * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. */ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) static uint8_t ucMaxSysCallPriority = 0; static uint32_t ulMaxPRIGROUPValue = 0; static const volatile uint8_t * const pcInterruptPriorityRegisters = ( const volatile uint8_t * ) portNVIC_IP_REGISTERS_OFFSET_16; -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ #if ( configUSE_TICKLESS_IDLE == 1 ) @@ -1614,7 +1614,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { - #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; @@ -1695,7 +1695,7 @@ BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ * value. */ portNVIC_SHPR2_REG = ulOriginalPriority; } - #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; @@ -1936,7 +1936,7 @@ BaseType_t xPortIsInsideInterrupt( void ) } /*-----------------------------------------------------------*/ -#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) void vPortValidateInterruptPriority( void ) { @@ -1994,5 +1994,5 @@ BaseType_t xPortIsInsideInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) ) */ /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM85_NTZ/non_secure/portmacro.h b/portable/IAR/ARM_CM85_NTZ/non_secure/portmacro.h index 3b51cb5ff..374150262 100644 --- a/portable/IAR/ARM_CM85_NTZ/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM85_NTZ/non_secure/portmacro.h @@ -54,7 +54,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M85" -#define portHAS_BASEPRI 1 +#define portHAS_ARMV8M_MAIN_EXTENSION 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM85_NTZ/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM85_NTZ/non_secure/portmacrocommon.h index 65ac109c8..e5ffdb48b 100644 --- a/portable/IAR/ARM_CM85_NTZ/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM85_NTZ/non_secure/portmacrocommon.h @@ -81,8 +81,8 @@ typedef unsigned long UBaseType_t; typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -307,7 +307,7 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P * system calls. */ #ifdef configASSERT - #if ( portHAS_BASEPRI == 1 ) + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) void vPortValidateInterruptPriority( void ); #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() #endif @@ -364,49 +364,49 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #if ( configENABLE_TRUSTZONE == 1 ) -/** - * @brief Allocate a secure context for the task. - * - * Tasks are not created with a secure context. Any task that is going to call - * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a - * secure context before it calls any secure function. - * - * @param[in] ulSecureStackSize The size of the secure stack to be allocated. - */ + /** + * @brief Allocate a secure context for the task. + * + * Tasks are not created with a secure context. Any task that is going to call + * secure functions must call portALLOCATE_SECURE_CONTEXT() to allocate itself a + * secure context before it calls any secure function. + * + * @param[in] ulSecureStackSize The size of the secure stack to be allocated. + */ #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) -/** - * @brief Called when a task is deleted to delete the task's secure context, - * if it has one. - * - * @param[in] pxTCB The TCB of the task being deleted. - */ + /** + * @brief Called when a task is deleted to delete the task's secure context, + * if it has one. + * + * @param[in] pxTCB The TCB of the task being deleted. + */ #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) #endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ #if ( configENABLE_MPU == 1 ) -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. - */ + /** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ #define portIS_PRIVILEGED() xIsPrivileged() -/** - * @brief Raise an SVC request to raise privilege. - * - * The SVC handler checks that the SVC was raised from a system call and only - * then it raises the privilege. If this is called from any other place, - * the privilege is not raised. - */ + /** + * @brief Raise an SVC request to raise privilege. + * + * The SVC handler checks that the SVC was raised from a system call and only + * then it raises the privilege. If this is called from any other place, + * the privilege is not raised. + */ #define portRAISE_PRIVILEGE() __asm volatile ( "svc %0 \n" ::"i" ( portSVC_RAISE_PRIVILEGE ) : "memory" ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - */ + /** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + */ #define portRESET_PRIVILEGE() vResetPrivilege() #else #define portIS_PRIVILEGED() @@ -435,6 +435,56 @@ extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) P #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ +/* Select correct value of configUSE_PORT_OPTIMISED_TASK_SELECTION + * based on whether or not Mainline extension is implemented. */ +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 1 ) + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #else + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + #endif +#endif /* #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION */ + +/** + * @brief Port-optimised task selection. + */ +#if ( configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 ) + + /** + * @brief Count the number of leading zeros in a 32-bit value. + */ + static portFORCE_INLINE uint32_t ulPortCountLeadingZeros( uint32_t ulBitmap ) + { + uint32_t ulReturn; + + __asm volatile ( "clz %0, %1" : "=r" ( ulReturn ) : "r" ( ulBitmap ) : "memory" ); + + return ulReturn; + } + + /* Check the configuration. */ + #if ( configMAX_PRIORITIES > 32 ) + #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice. + #endif + + #if ( portHAS_ARMV8M_MAIN_EXTENSION == 0 ) + #error ARMv8-M baseline implementations (such as Cortex-M23) do not support port-optimised task selection. Please set configUSE_PORT_OPTIMISED_TASK_SELECTION to 0 or leave it undefined. + #endif + + /** + * @brief Store/clear the ready priorities in a bit map. + */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + + /** + * @brief Get the priority of the highest-priority task that is ready to execute. + */ + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - ulPortCountLeadingZeros( ( uxReadyPriorities ) ) ) + +#endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */ +/*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #ifdef __cplusplus }