diff --git a/.github/lexicon.txt b/.github/lexicon.txt index 78c911c5d91..90452c54c56 100644 --- a/.github/lexicon.txt +++ b/.github/lexicon.txt @@ -1611,6 +1611,7 @@ putchar puxstackbuffer puxvariabletoincrement pv +pvallocatedmemory pvbuffer pvcallbackref pvcomparand diff --git a/include/newlib-freertos.h b/include/newlib-freertos.h index 497ca529990..a65e62e8ef7 100644 --- a/include/newlib-freertos.h +++ b/include/newlib-freertos.h @@ -52,7 +52,7 @@ #endif #ifndef configSET_TLS_BLOCK - #define configSET_TLS_BLOCK( xTLSBlock ) _impure_ptr = &( xTLSBlock ) + #define configSET_TLS_BLOCK( xTLSBlock ) ( _impure_ptr = &( xTLSBlock ) ) #endif #ifndef configDEINIT_TLS_BLOCK diff --git a/portable/ARMv8M/non_secure/port.c b/portable/ARMv8M/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/ARMv8M/non_secure/port.c +++ b/portable/ARMv8M/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 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 c6dad99857c..746f734b8ac 100644 --- a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM23/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -48,12 +48,17 @@ /** * Architecture specifics. */ -#define portARCH_NAME "Cortex-M23" -#define portDONT_DISCARD __attribute__( ( used ) ) -#define portNORETURN __attribute__( ( noreturn ) ) +#define portARCH_NAME "Cortex-M23" +#define portHAS_BASEPRI 0 +#define portDONT_DISCARD __attribute__( ( used ) ) +#define portNORETURN __attribute__( ( noreturn ) ) +/*-----------------------------------------------------------*/ + +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" /*-----------------------------------------------------------*/ -#if( configTOTAL_MPU_REGIONS == 16 ) +#if ( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif /*-----------------------------------------------------------*/ @@ -61,12 +66,14 @@ /** * @brief Critical section management. */ -#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) -#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) +#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) +#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ 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 c6dad99857c..746f734b8ac 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 @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -48,12 +48,17 @@ /** * Architecture specifics. */ -#define portARCH_NAME "Cortex-M23" -#define portDONT_DISCARD __attribute__( ( used ) ) -#define portNORETURN __attribute__( ( noreturn ) ) +#define portARCH_NAME "Cortex-M23" +#define portHAS_BASEPRI 0 +#define portDONT_DISCARD __attribute__( ( used ) ) +#define portNORETURN __attribute__( ( noreturn ) ) +/*-----------------------------------------------------------*/ + +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" /*-----------------------------------------------------------*/ -#if( configTOTAL_MPU_REGIONS == 16 ) +#if ( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif /*-----------------------------------------------------------*/ @@ -61,12 +66,14 @@ /** * @brief Critical section management. */ -#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) -#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) +#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) +#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ 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 4fe8c59147a..19da9b0ecfe 100644 --- a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM33/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM33/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -49,10 +49,15 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M33" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __attribute__( ( used ) ) #define portNORETURN __attribute__( ( noreturn ) ) /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + /** * @brief Critical section management. */ @@ -60,8 +65,10 @@ #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ 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 4fe8c59147a..19da9b0ecfe 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 @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -49,10 +49,15 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M33" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __attribute__( ( used ) ) #define portNORETURN __attribute__( ( noreturn ) ) /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + /** * @brief Critical section management. */ @@ -60,8 +65,10 @@ #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ 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 33bfb283461..cc643459770 100644 --- a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM35P/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM35P/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -49,10 +49,15 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M35P" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __attribute__( ( used ) ) #define portNORETURN __attribute__( ( noreturn ) ) /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + /** * @brief Critical section management. */ @@ -60,8 +65,10 @@ #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ 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 adb47d8420f..c9bad40cf98 100644 --- a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM55/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM55/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -54,10 +54,15 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M55" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __attribute__( ( used ) ) #define portNORETURN __attribute__( ( noreturn ) ) /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + /** * @brief Critical section management. */ @@ -65,8 +70,10 @@ #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ 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 fec6923394c..c45dd21c29e 100644 --- a/portable/ARMv8M/non_secure/portable/GCC/ARM_CM85/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/GCC/ARM_CM85/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -54,10 +54,15 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M85" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __attribute__( ( used ) ) #define portNORETURN __attribute__( ( noreturn ) ) /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + /** * @brief Critical section management. */ @@ -65,8 +70,10 @@ #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ 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 d845ac1caa0..9cf0e87fbc8 100644 --- a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM23/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM23/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -48,11 +48,16 @@ /** * Architecture specifics. */ -#define portARCH_NAME "Cortex-M23" -#define portDONT_DISCARD __root +#define portARCH_NAME "Cortex-M23" +#define portHAS_BASEPRI 0 +#define portDONT_DISCARD __root +/*-----------------------------------------------------------*/ + +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" /*-----------------------------------------------------------*/ -#if( configTOTAL_MPU_REGIONS == 16 ) +#if ( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif /*-----------------------------------------------------------*/ @@ -60,8 +65,8 @@ /** * @brief Critical section management. */ -#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) -#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) +#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) +#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) /*-----------------------------------------------------------*/ /* Suppress warnings that are generated by the IAR tools, but cannot be fixed in @@ -71,8 +76,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ 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 d845ac1caa0..9cf0e87fbc8 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 @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -48,11 +48,16 @@ /** * Architecture specifics. */ -#define portARCH_NAME "Cortex-M23" -#define portDONT_DISCARD __root +#define portARCH_NAME "Cortex-M23" +#define portHAS_BASEPRI 0 +#define portDONT_DISCARD __root +/*-----------------------------------------------------------*/ + +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" /*-----------------------------------------------------------*/ -#if( configTOTAL_MPU_REGIONS == 16 ) +#if ( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif /*-----------------------------------------------------------*/ @@ -60,8 +65,8 @@ /** * @brief Critical section management. */ -#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) -#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) +#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) +#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) /*-----------------------------------------------------------*/ /* Suppress warnings that are generated by the IAR tools, but cannot be fixed in @@ -71,8 +76,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ 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 b6df20eb88f..380768fc03b 100644 --- a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM33/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM33/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -49,6 +49,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M33" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ @@ -57,6 +58,10 @@ #endif /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + /** * @brief Critical section management. */ @@ -71,8 +76,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ 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 b6df20eb88f..815dca0861a 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 @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -49,9 +49,14 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M33" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + #if( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif @@ -71,8 +76,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ 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 a0efc1f9dcf..46bc4e24b56 100644 --- a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM35P/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM35P/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -49,9 +49,14 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M35P" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + #if( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif @@ -71,8 +76,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ 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 a3b510e282c..7829ee6186a 100644 --- a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM55/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM55/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -54,9 +54,14 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M55" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + #if( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif @@ -76,8 +81,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ 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 cfaae813eac..3b51cb5ff46 100644 --- a/portable/ARMv8M/non_secure/portable/IAR/ARM_CM85/portmacro.h +++ b/portable/ARMv8M/non_secure/portable/IAR/ARM_CM85/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -54,9 +54,14 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M85" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + #if( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif @@ -76,8 +81,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/ARMv8M/non_secure/portmacrocommon.h b/portable/ARMv8M/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/ARMv8M/non_secure/portmacrocommon.h +++ b/portable/ARMv8M/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/CCS/ARM_CM3/portmacro.h b/portable/CCS/ARM_CM3/portmacro.h index 7ac1d709caf..9c405d4c87f 100644 --- a/portable/CCS/ARM_CM3/portmacro.h +++ b/portable/CCS/ARM_CM3/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -166,8 +168,10 @@ /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/CCS/ARM_CM4F/portmacro.h b/portable/CCS/ARM_CM4F/portmacro.h index 34988c223f5..64c702c941c 100644 --- a/portable/CCS/ARM_CM4F/portmacro.h +++ b/portable/CCS/ARM_CM4F/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -160,8 +162,10 @@ /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/CCS/MSP430X/portext.asm b/portable/CCS/MSP430X/portext.asm index 9ebfa995016..9fe306e9401 100644 --- a/portable/CCS/MSP430X/portext.asm +++ b/portable/CCS/MSP430X/portext.asm @@ -48,7 +48,7 @@ portSAVE_CONTEXT .macro ;Save the remaining registers. pushm_x #12, r15 - mov.w &usCriticalNesting, r14 + movx.w &usCriticalNesting, r14 push_x r14 mov_x &pxCurrentTCB, r12 mov_x sp, 0( r12 ) @@ -60,7 +60,7 @@ portRESTORE_CONTEXT .macro mov_x &pxCurrentTCB, r12 mov_x @r12, sp pop_x r15 - mov.w r15, &usCriticalNesting + movx.w r15, &usCriticalNesting popm_x #12, r15 nop pop.w sr diff --git a/portable/CodeWarrior/ColdFire_V1/portmacro.h b/portable/CodeWarrior/ColdFire_V1/portmacro.h index edae69ab2b2..8acfcd04fdd 100644 --- a/portable/CodeWarrior/ColdFire_V1/portmacro.h +++ b/portable/CodeWarrior/ColdFire_V1/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -107,8 +109,10 @@ extern void vPortClearInterruptMaskFromISR( UBaseType_t ); #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired != pdFALSE ) { portYIELD(); } } while( 0 ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/CodeWarrior/ColdFire_V2/portmacro.h b/portable/CodeWarrior/ColdFire_V2/portmacro.h index 665ae4b304c..053b0adecb6 100644 --- a/portable/CodeWarrior/ColdFire_V2/portmacro.h +++ b/portable/CodeWarrior/ColdFire_V2/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -106,8 +108,10 @@ extern void vPortClearInterruptMaskFromISR( UBaseType_t ); #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired != pdFALSE ) { portYIELD(); } } while( 0 ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM7_AT91FR40008/portmacro.h b/portable/GCC/ARM7_AT91FR40008/portmacro.h index 69ee70f078c..201f3c7a795 100644 --- a/portable/GCC/ARM7_AT91FR40008/portmacro.h +++ b/portable/GCC/ARM7_AT91FR40008/portmacro.h @@ -52,9 +52,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -250,8 +252,10 @@ extern void vPortExitCritical( void ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM7_AT91SAM7S/portmacro.h b/portable/GCC/ARM7_AT91SAM7S/portmacro.h index 1a440a68c5f..b52fbe0aa45 100644 --- a/portable/GCC/ARM7_AT91SAM7S/portmacro.h +++ b/portable/GCC/ARM7_AT91SAM7S/portmacro.h @@ -52,9 +52,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -244,8 +246,10 @@ extern void vPortExitCritical( void ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM7_LPC2000/portmacro.h b/portable/GCC/ARM7_LPC2000/portmacro.h index 50922065441..6545e1127c4 100644 --- a/portable/GCC/ARM7_LPC2000/portmacro.h +++ b/portable/GCC/ARM7_LPC2000/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -221,8 +223,10 @@ extern void vPortExitCritical( void ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM7_LPC23xx/portmacro.h b/portable/GCC/ARM7_LPC23xx/portmacro.h index 768e86dbed1..f60cdde5331 100644 --- a/portable/GCC/ARM7_LPC23xx/portmacro.h +++ b/portable/GCC/ARM7_LPC23xx/portmacro.h @@ -52,9 +52,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -244,8 +246,10 @@ extern void vPortExitCritical( void ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CA53_64_BIT/portmacro.h b/portable/GCC/ARM_CA53_64_BIT/portmacro.h index 1b2e277cf05..00fc061644b 100644 --- a/portable/GCC/ARM_CA53_64_BIT/portmacro.h +++ b/portable/GCC/ARM_CA53_64_BIT/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -165,11 +167,6 @@ void vPortTaskUsesFPU( void ); #define portNOP() __asm volatile( "NOP" ) #define portINLINE __inline -#ifdef __cplusplus - } /* extern C */ -#endif - - /* The number of bits to shift for an interrupt priority is dependent on the number of bits implemented by the interrupt controller. */ #if configUNIQUE_INTERRUPT_PRIORITIES == 16 @@ -208,4 +205,10 @@ number of bits implemented by the interrupt controller. */ #define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ + #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CA53_64_BIT_SRE/portmacro.h b/portable/GCC/ARM_CA53_64_BIT_SRE/portmacro.h index d8d911f4f75..0199288824c 100644 --- a/portable/GCC/ARM_CA53_64_BIT_SRE/portmacro.h +++ b/portable/GCC/ARM_CA53_64_BIT_SRE/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -165,11 +167,6 @@ void vPortTaskUsesFPU( void ); #define portNOP() __asm volatile( "NOP" ) #define portINLINE __inline -#ifdef __cplusplus - } /* extern C */ -#endif - - /* The number of bits to shift for an interrupt priority is dependent on the number of bits implemented by the interrupt controller. */ #if configUNIQUE_INTERRUPT_PRIORITIES == 16 @@ -193,4 +190,10 @@ number of bits implemented by the interrupt controller. */ #define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ + #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CA9/portmacro.h b/portable/GCC/ARM_CA9/portmacro.h index d97fb535f71..6f1f2272456 100644 --- a/portable/GCC/ARM_CA9/portmacro.h +++ b/portable/GCC/ARM_CA9/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -162,11 +164,6 @@ by default. */ #define portNOP() __asm volatile( "NOP" ) #define portINLINE __inline -#ifdef __cplusplus - } /* extern C */ -#endif - - /* The number of bits to shift for an interrupt priority is dependent on the number of bits implemented by the interrupt controller. */ #if configUNIQUE_INTERRUPT_PRIORITIES == 16 @@ -205,4 +202,10 @@ number of bits implemented by the interrupt controller. */ #define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ + #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM0/portmacro.h b/portable/GCC/ARM_CM0/portmacro.h index b9e9ef6623f..dc7f54578e2 100644 --- a/portable/GCC/ARM_CM0/portmacro.h +++ b/portable/GCC/ARM_CM0/portmacro.h @@ -156,7 +156,6 @@ portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void ) /*-----------------------------------------------------------*/ - /* *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 9976daee49a..7bbe1b7bc53 100644 --- a/portable/GCC/ARM_CM23/non_secure/port.c +++ b/portable/GCC/ARM_CM23/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM23/non_secure/portmacro.h b/portable/GCC/ARM_CM23/non_secure/portmacro.h index c6dad99857c..746f734b8ac 100644 --- a/portable/GCC/ARM_CM23/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM23/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -48,12 +48,17 @@ /** * Architecture specifics. */ -#define portARCH_NAME "Cortex-M23" -#define portDONT_DISCARD __attribute__( ( used ) ) -#define portNORETURN __attribute__( ( noreturn ) ) +#define portARCH_NAME "Cortex-M23" +#define portHAS_BASEPRI 0 +#define portDONT_DISCARD __attribute__( ( used ) ) +#define portNORETURN __attribute__( ( noreturn ) ) +/*-----------------------------------------------------------*/ + +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" /*-----------------------------------------------------------*/ -#if( configTOTAL_MPU_REGIONS == 16 ) +#if ( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif /*-----------------------------------------------------------*/ @@ -61,12 +66,14 @@ /** * @brief Critical section management. */ -#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) -#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) +#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) +#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM23/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM23/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/GCC/ARM_CM23/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM23/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/GCC/ARM_CM23_NTZ/non_secure/port.c b/portable/GCC/ARM_CM23_NTZ/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/GCC/ARM_CM23_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM23_NTZ/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM23_NTZ/non_secure/portmacro.h b/portable/GCC/ARM_CM23_NTZ/non_secure/portmacro.h index c6dad99857c..746f734b8ac 100644 --- a/portable/GCC/ARM_CM23_NTZ/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM23_NTZ/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -48,12 +48,17 @@ /** * Architecture specifics. */ -#define portARCH_NAME "Cortex-M23" -#define portDONT_DISCARD __attribute__( ( used ) ) -#define portNORETURN __attribute__( ( noreturn ) ) +#define portARCH_NAME "Cortex-M23" +#define portHAS_BASEPRI 0 +#define portDONT_DISCARD __attribute__( ( used ) ) +#define portNORETURN __attribute__( ( noreturn ) ) +/*-----------------------------------------------------------*/ + +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" /*-----------------------------------------------------------*/ -#if( configTOTAL_MPU_REGIONS == 16 ) +#if ( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif /*-----------------------------------------------------------*/ @@ -61,12 +66,14 @@ /** * @brief Critical section management. */ -#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) -#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) +#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) +#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM23_NTZ/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM23_NTZ/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/GCC/ARM_CM23_NTZ/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM23_NTZ/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/GCC/ARM_CM3/portmacro.h b/portable/GCC/ARM_CM3/portmacro.h index dd729f13f2c..36e38f75d21 100644 --- a/portable/GCC/ARM_CM3/portmacro.h +++ b/portable/GCC/ARM_CM3/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -243,8 +245,10 @@ #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM33/non_secure/port.c b/portable/GCC/ARM_CM33/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/GCC/ARM_CM33/non_secure/port.c +++ b/portable/GCC/ARM_CM33/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33/non_secure/portmacro.h b/portable/GCC/ARM_CM33/non_secure/portmacro.h index 4fe8c59147a..19da9b0ecfe 100644 --- a/portable/GCC/ARM_CM33/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM33/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -49,10 +49,15 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M33" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __attribute__( ( used ) ) #define portNORETURN __attribute__( ( noreturn ) ) /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + /** * @brief Critical section management. */ @@ -60,8 +65,10 @@ #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM33/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM33/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/GCC/ARM_CM33/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM33/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/GCC/ARM_CM33_NTZ/non_secure/port.c b/portable/GCC/ARM_CM33_NTZ/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/GCC/ARM_CM33_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM33_NTZ/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM33_NTZ/non_secure/portmacro.h b/portable/GCC/ARM_CM33_NTZ/non_secure/portmacro.h index 4fe8c59147a..19da9b0ecfe 100644 --- a/portable/GCC/ARM_CM33_NTZ/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM33_NTZ/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -49,10 +49,15 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M33" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __attribute__( ( used ) ) #define portNORETURN __attribute__( ( noreturn ) ) /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + /** * @brief Critical section management. */ @@ -60,8 +65,10 @@ #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM33_NTZ/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM33_NTZ/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/GCC/ARM_CM33_NTZ/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM33_NTZ/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/GCC/ARM_CM35P/non_secure/port.c b/portable/GCC/ARM_CM35P/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/GCC/ARM_CM35P/non_secure/port.c +++ b/portable/GCC/ARM_CM35P/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM35P/non_secure/portmacro.h b/portable/GCC/ARM_CM35P/non_secure/portmacro.h index 33bfb283461..cc643459770 100644 --- a/portable/GCC/ARM_CM35P/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM35P/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -49,10 +49,15 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M35P" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __attribute__( ( used ) ) #define portNORETURN __attribute__( ( noreturn ) ) /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + /** * @brief Critical section management. */ @@ -60,8 +65,10 @@ #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM35P/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM35P/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/GCC/ARM_CM35P/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM35P/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c b/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM35P_NTZ/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM35P_NTZ/non_secure/portmacro.h b/portable/GCC/ARM_CM35P_NTZ/non_secure/portmacro.h index 33bfb283461..cc643459770 100644 --- a/portable/GCC/ARM_CM35P_NTZ/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM35P_NTZ/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -49,10 +49,15 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M35P" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __attribute__( ( used ) ) #define portNORETURN __attribute__( ( noreturn ) ) /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + /** * @brief Critical section management. */ @@ -60,8 +65,10 @@ #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM35P_NTZ/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM35P_NTZ/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/GCC/ARM_CM35P_NTZ/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM35P_NTZ/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/GCC/ARM_CM3_MPU/portmacro.h b/portable/GCC/ARM_CM3_MPU/portmacro.h index 25058026973..b15193f1ee5 100644 --- a/portable/GCC/ARM_CM3_MPU/portmacro.h +++ b/portable/GCC/ARM_CM3_MPU/portmacro.h @@ -28,11 +28,13 @@ #ifndef PORTMACRO_H - #define PORTMACRO_H +#define PORTMACRO_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -301,12 +303,15 @@ #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) #ifndef configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY - #warning "configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY is not defined. We recommend defining it to 1 in FreeRTOSConfig.h for better security. https://www.FreeRTOS.org/FreeRTOS-V10.3.x.html" + #warning "configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY is not defined. We recommend defining it to 1 in FreeRTOSConfig.h for better security. *www.FreeRTOS.org/FreeRTOS-V10.3.x.html" #define configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY 0 #endif /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif + +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM4F/portmacro.h b/portable/GCC/ARM_CM4F/portmacro.h index a3b2b46c989..443661a6d3a 100644 --- a/portable/GCC/ARM_CM4F/portmacro.h +++ b/portable/GCC/ARM_CM4F/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -244,8 +246,10 @@ #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM55/non_secure/port.c b/portable/GCC/ARM_CM55/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/GCC/ARM_CM55/non_secure/port.c +++ b/portable/GCC/ARM_CM55/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM55/non_secure/portmacro.h b/portable/GCC/ARM_CM55/non_secure/portmacro.h index adb47d8420f..c9bad40cf98 100644 --- a/portable/GCC/ARM_CM55/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM55/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -54,10 +54,15 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M55" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __attribute__( ( used ) ) #define portNORETURN __attribute__( ( noreturn ) ) /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + /** * @brief Critical section management. */ @@ -65,8 +70,10 @@ #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM55/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM55/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/GCC/ARM_CM55/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM55/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/GCC/ARM_CM55_NTZ/non_secure/port.c b/portable/GCC/ARM_CM55_NTZ/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/GCC/ARM_CM55_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM55_NTZ/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM55_NTZ/non_secure/portmacro.h b/portable/GCC/ARM_CM55_NTZ/non_secure/portmacro.h index adb47d8420f..c9bad40cf98 100644 --- a/portable/GCC/ARM_CM55_NTZ/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM55_NTZ/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -54,10 +54,15 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M55" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __attribute__( ( used ) ) #define portNORETURN __attribute__( ( noreturn ) ) /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + /** * @brief Critical section management. */ @@ -65,8 +70,10 @@ #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM55_NTZ/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM55_NTZ/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/GCC/ARM_CM55_NTZ/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM55_NTZ/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/GCC/ARM_CM7/r0p1/portmacro.h b/portable/GCC/ARM_CM7/r0p1/portmacro.h index 897fef5f468..82529f998ad 100644 --- a/portable/GCC/ARM_CM7/r0p1/portmacro.h +++ b/portable/GCC/ARM_CM7/r0p1/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -245,8 +247,10 @@ #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM85/non_secure/port.c b/portable/GCC/ARM_CM85/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/GCC/ARM_CM85/non_secure/port.c +++ b/portable/GCC/ARM_CM85/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM85/non_secure/portmacro.h b/portable/GCC/ARM_CM85/non_secure/portmacro.h index fec6923394c..c45dd21c29e 100644 --- a/portable/GCC/ARM_CM85/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM85/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -54,10 +54,15 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M85" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __attribute__( ( used ) ) #define portNORETURN __attribute__( ( noreturn ) ) /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + /** * @brief Critical section management. */ @@ -65,8 +70,10 @@ #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM85/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM85/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/GCC/ARM_CM85/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM85/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/GCC/ARM_CM85_NTZ/non_secure/port.c b/portable/GCC/ARM_CM85_NTZ/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/GCC/ARM_CM85_NTZ/non_secure/port.c +++ b/portable/GCC/ARM_CM85_NTZ/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/GCC/ARM_CM85_NTZ/non_secure/portmacro.h b/portable/GCC/ARM_CM85_NTZ/non_secure/portmacro.h index fec6923394c..c45dd21c29e 100644 --- a/portable/GCC/ARM_CM85_NTZ/non_secure/portmacro.h +++ b/portable/GCC/ARM_CM85_NTZ/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -54,10 +54,15 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M85" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __attribute__( ( used ) ) #define portNORETURN __attribute__( ( noreturn ) ) /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + /** * @brief Critical section management. */ @@ -65,8 +70,10 @@ #define portENABLE_INTERRUPTS() vClearInterruptMask( 0 ) /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ARM_CM85_NTZ/non_secure/portmacrocommon.h b/portable/GCC/ARM_CM85_NTZ/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/GCC/ARM_CM85_NTZ/non_secure/portmacrocommon.h +++ b/portable/GCC/ARM_CM85_NTZ/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/GCC/ARM_CRx_No_GIC/portmacro.h b/portable/GCC/ARM_CRx_No_GIC/portmacro.h index be5c6121e40..e8e54103439 100644 --- a/portable/GCC/ARM_CRx_No_GIC/portmacro.h +++ b/portable/GCC/ARM_CRx_No_GIC/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -173,9 +175,10 @@ void vPortTaskUsesFPU( void ); #define portMEMORY_BARRIER() __asm volatile( "" ::: "memory" ) +/* *INDENT-OFF* */ #ifdef __cplusplus - } /* extern C */ + } #endif - +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ATMega323/portmacro.h b/portable/GCC/ATMega323/portmacro.h index c22706de5d4..a9f317e6d65 100644 --- a/portable/GCC/ATMega323/portmacro.h +++ b/portable/GCC/ATMega323/portmacro.h @@ -36,9 +36,11 @@ Changes from V1.2.3 #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -104,8 +106,10 @@ extern void vPortYield( void ) __attribute__ ( ( naked ) ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/AVR32_UC3/portmacro.h b/portable/GCC/AVR32_UC3/portmacro.h index 86014a135b5..5bc7c8b0877 100644 --- a/portable/GCC/AVR32_UC3/portmacro.h +++ b/portable/GCC/AVR32_UC3/portmacro.h @@ -85,9 +85,11 @@ #include "intc.h" #include "compiler.h" +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /* Type definitions. */ @@ -691,8 +693,10 @@ extern void *pvPortRealloc( void *pv, size_t xSize ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/CORTUS_APS3/portmacro.h b/portable/GCC/CORTUS_APS3/portmacro.h index 86000665681..37e739bb55f 100644 --- a/portable/GCC/CORTUS_APS3/portmacro.h +++ b/portable/GCC/CORTUS_APS3/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ #include @@ -148,8 +150,10 @@ extern void vTaskExitCritical( void ); #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) /*---------------------------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/ColdFire_V2/portmacro.h b/portable/GCC/ColdFire_V2/portmacro.h index 9b4c1da8833..14d318b7b94 100644 --- a/portable/GCC/ColdFire_V2/portmacro.h +++ b/portable/GCC/ColdFire_V2/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -106,8 +108,10 @@ extern void vPortClearInterruptMaskFromISR( UBaseType_t ); #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired != pdFALSE ) { portYIELD(); } } while( 0 ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/H8S2329/portmacro.h b/portable/GCC/H8S2329/portmacro.h index 4c87abd163c..829ff9f9b64 100644 --- a/portable/GCC/H8S2329/portmacro.h +++ b/portable/GCC/H8S2329/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -133,8 +135,10 @@ extern void* pxCurrentTCB; \ #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/HCS12/portmacro.h b/portable/GCC/HCS12/portmacro.h index 9202510ccc8..a864419899f 100644 --- a/portable/GCC/HCS12/portmacro.h +++ b/portable/GCC/HCS12/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -241,8 +243,10 @@ typedef unsigned char UBaseType_t; #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/IA32_flat/portmacro.h b/portable/GCC/IA32_flat/portmacro.h index 060eb4daa69..3a0cd287c8e 100644 --- a/portable/GCC/IA32_flat/portmacro.h +++ b/portable/GCC/IA32_flat/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -284,8 +286,10 @@ above the max system call interrupt priority. */ #define portAPIC_PROCESSOR_PRIORITY ( *( ( volatile uint32_t * ) ( configAPIC_BASE + 0xA0UL ) ) ) #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() configASSERT( ( portAPIC_PROCESSOR_PRIORITY ) <= ( portMAX_API_CALL_PRIORITY ) ) +/* *INDENT-OFF* */ #ifdef __cplusplus - } /* extern C */ + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/MSP430F449/portmacro.h b/portable/GCC/MSP430F449/portmacro.h index 8d6827a57e9..5a6e1db9c94 100644 --- a/portable/GCC/MSP430F449/portmacro.h +++ b/portable/GCC/MSP430F449/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -122,8 +124,10 @@ extern void vPortYield( void ) __attribute__ ( ( naked ) ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/MicroBlaze/portmacro.h b/portable/GCC/MicroBlaze/portmacro.h index c646496ab3f..b04c526a42d 100644 --- a/portable/GCC/MicroBlaze/portmacro.h +++ b/portable/GCC/MicroBlaze/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -122,8 +124,10 @@ void vTaskSwitchContext(); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/MicroBlazeV8/portmacro.h b/portable/GCC/MicroBlazeV8/portmacro.h index be9dfacc42f..3ade98795df 100644 --- a/portable/GCC/MicroBlazeV8/portmacro.h +++ b/portable/GCC/MicroBlazeV8/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /* BSP includes. */ #include @@ -365,8 +367,10 @@ void vPortExceptionsInstallHandlers( void ); void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump ); +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/MicroBlazeV9/portmacro.h b/portable/GCC/MicroBlazeV9/portmacro.h index c26daa79fc2..9d10b5e5beb 100644 --- a/portable/GCC/MicroBlazeV9/portmacro.h +++ b/portable/GCC/MicroBlazeV9/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /* BSP includes. */ #include @@ -370,8 +372,10 @@ void vPortExceptionsInstallHandlers( void ); void vApplicationExceptionRegisterDump( xPortRegisterDump *xRegisterDump ); +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/NiosII/portmacro.h b/portable/GCC/NiosII/portmacro.h index 7a159925db2..3ac552dd8fa 100644 --- a/portable/GCC/NiosII/portmacro.h +++ b/portable/GCC/NiosII/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ #include "sys/alt_irq.h" @@ -104,8 +106,10 @@ extern void vTaskExitCritical( void ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/PPC405_Xilinx/portmacro.h b/portable/GCC/PPC405_Xilinx/portmacro.h index d7f32944c40..e6f1c06c845 100644 --- a/portable/GCC/PPC405_Xilinx/portmacro.h +++ b/portable/GCC/PPC405_Xilinx/portmacro.h @@ -31,9 +31,11 @@ #include "xexception_l.h" +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -113,8 +115,10 @@ void vPortYield( void ); void vPortSetupInterruptController( void ); BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef ); +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/PPC440_Xilinx/portmacro.h b/portable/GCC/PPC440_Xilinx/portmacro.h index d7f32944c40..e6f1c06c845 100644 --- a/portable/GCC/PPC440_Xilinx/portmacro.h +++ b/portable/GCC/PPC440_Xilinx/portmacro.h @@ -31,9 +31,11 @@ #include "xexception_l.h" +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -113,8 +115,10 @@ void vPortYield( void ); void vPortSetupInterruptController( void ); BaseType_t xPortInstallInterruptHandler( uint8_t ucInterruptID, XInterruptHandler pxHandler, void *pvCallBackRef ); +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/RISC-V/portmacro.h b/portable/GCC/RISC-V/portmacro.h index 1e72b1af547..727273aca5c 100644 --- a/portable/GCC/RISC-V/portmacro.h +++ b/portable/GCC/RISC-V/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -184,8 +186,10 @@ extern size_t xCriticalNesting; #error configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. Set them to zero if there is no MTIME (machine time) clock. See https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html #endif +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/RX100/portmacro.h b/portable/GCC/RX100/portmacro.h index 863596685aa..4556e147a5e 100644 --- a/portable/GCC/RX100/portmacro.h +++ b/portable/GCC/RX100/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -144,8 +146,10 @@ void vPortSetIPL( uint32_t ulNewIPL ) __attribute__((naked)); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/RX200/portmacro.h b/portable/GCC/RX200/portmacro.h index 80fc8c8041d..40682825dd1 100644 --- a/portable/GCC/RX200/portmacro.h +++ b/portable/GCC/RX200/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -139,8 +141,10 @@ void vPortSetIPL( uint32_t ulNewIPL ) __attribute__((naked)); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/RX600/portmacro.h b/portable/GCC/RX600/portmacro.h index 7e1fd1e0c92..7e7bbe88b3c 100644 --- a/portable/GCC/RX600/portmacro.h +++ b/portable/GCC/RX600/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -139,8 +141,10 @@ void vPortSetIPL( uint32_t ulNewIPL ) __attribute__((naked)); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/RX600v2/portmacro.h b/portable/GCC/RX600v2/portmacro.h index 7e1fd1e0c92..7e7bbe88b3c 100644 --- a/portable/GCC/RX600v2/portmacro.h +++ b/portable/GCC/RX600v2/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -139,8 +141,10 @@ void vPortSetIPL( uint32_t ulNewIPL ) __attribute__((naked)); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/RX700v3_DPFPU/portmacro.h b/portable/GCC/RX700v3_DPFPU/portmacro.h index 6b76374c882..881610515ee 100644 --- a/portable/GCC/RX700v3_DPFPU/portmacro.h +++ b/portable/GCC/RX700v3_DPFPU/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -182,8 +184,10 @@ /* Definition to allow compatibility with existing FreeRTOS Demo using flop.c. */ #define portTASK_USES_FLOATING_POINT() vPortTaskUsesDPFPU() - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/STR75x/portmacro.h b/portable/GCC/STR75x/portmacro.h index 85262dac4d5..8d5e832c59e 100644 --- a/portable/GCC/STR75x/portmacro.h +++ b/portable/GCC/STR75x/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -135,8 +137,10 @@ extern void vTaskSwitchContext( void ); \ #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/GCC/TriCore_1782/portmacro.h b/portable/GCC/TriCore_1782/portmacro.h index 734abc5949c..d17c7bc6882 100644 --- a/portable/GCC/TriCore_1782/portmacro.h +++ b/portable/GCC/TriCore_1782/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /* System Includes. */ #include @@ -169,8 +171,10 @@ extern uint32_t uxPortSetInterruptMaskFromISR( void ); void vPortReclaimCSA( uint32_t *pxTCB ); #define portCLEAN_UP_TCB( pxTCB ) vPortReclaimCSA( ( uint32_t * ) ( pxTCB ) ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/78K0R/portmacro.h b/portable/IAR/78K0R/portmacro.h index e6f67cdd3b7..4ccc083c080 100644 --- a/portable/IAR/78K0R/portmacro.h +++ b/portable/IAR/78K0R/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -140,8 +142,10 @@ static __interrupt void P0_isr (void); #define OCD_ENABLED 0x81 #define OCD_ENABLED_ERASE 0x80 +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ARM_CA5_No_GIC/portmacro.h b/portable/IAR/ARM_CA5_No_GIC/portmacro.h index 3d73f83fd16..b1dcf3878fb 100644 --- a/portable/IAR/ARM_CA5_No_GIC/portmacro.h +++ b/portable/IAR/ARM_CA5_No_GIC/portmacro.h @@ -29,14 +29,18 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ + /* IAR includes. */ #ifdef __ICCARM__ #include - #ifdef __cplusplus - extern "C" { - #endif + /*----------------------------------------------------------- * Port specific definitions. @@ -146,11 +150,6 @@ #define portNOP() __asm volatile( "NOP" ) - - #ifdef __cplusplus - } /* extern C */ - #endif - /* Suppress warnings that are generated by the IAR tools, but cannot be fixed in the source code because to do so would cause other compilers to generate warnings. */ @@ -159,4 +158,10 @@ #endif /* __ICCARM__ */ +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ + #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ARM_CA9/portmacro.h b/portable/IAR/ARM_CA9/portmacro.h index 87c83eaa05c..bce3013b5b4 100644 --- a/portable/IAR/ARM_CA9/portmacro.h +++ b/portable/IAR/ARM_CA9/portmacro.h @@ -29,15 +29,17 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ + /* IAR includes. */ #ifdef __ICCARM__ #include - #ifdef __cplusplus - extern "C" { - #endif - /*----------------------------------------------------------- * Port specific definitions. * @@ -156,11 +158,6 @@ #define portNOP() __asm volatile( "NOP" ) - - #ifdef __cplusplus - } /* extern C */ - #endif - /* Suppress warnings that are generated by the IAR tools, but cannot be fixed in the source code because to do so would cause other compilers to generate warnings. */ @@ -206,4 +203,10 @@ number of bits implemented by the interrupt controller. */ #define portICCBPR_BINARY_POINT_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCBPR_BINARY_POINT_OFFSET ) ) ) #define portICCRPR_RUNNING_PRIORITY_REGISTER ( *( ( const volatile uint32_t * ) ( portINTERRUPT_CONTROLLER_CPU_INTERFACE_ADDRESS + portICCRPR_RUNNING_PRIORITY_OFFSET ) ) ) +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ + #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ARM_CM23/non_secure/port.c b/portable/IAR/ARM_CM23/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/IAR/ARM_CM23/non_secure/port.c +++ b/portable/IAR/ARM_CM23/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM23/non_secure/portmacro.h b/portable/IAR/ARM_CM23/non_secure/portmacro.h index d845ac1caa0..9cf0e87fbc8 100644 --- a/portable/IAR/ARM_CM23/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM23/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -48,11 +48,16 @@ /** * Architecture specifics. */ -#define portARCH_NAME "Cortex-M23" -#define portDONT_DISCARD __root +#define portARCH_NAME "Cortex-M23" +#define portHAS_BASEPRI 0 +#define portDONT_DISCARD __root +/*-----------------------------------------------------------*/ + +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" /*-----------------------------------------------------------*/ -#if( configTOTAL_MPU_REGIONS == 16 ) +#if ( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif /*-----------------------------------------------------------*/ @@ -60,8 +65,8 @@ /** * @brief Critical section management. */ -#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) -#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) +#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) +#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) /*-----------------------------------------------------------*/ /* Suppress warnings that are generated by the IAR tools, but cannot be fixed in @@ -71,8 +76,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ARM_CM23/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM23/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/IAR/ARM_CM23/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM23/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/IAR/ARM_CM23_NTZ/non_secure/port.c b/portable/IAR/ARM_CM23_NTZ/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/IAR/ARM_CM23_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM23_NTZ/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM23_NTZ/non_secure/portmacro.h b/portable/IAR/ARM_CM23_NTZ/non_secure/portmacro.h index d845ac1caa0..9cf0e87fbc8 100644 --- a/portable/IAR/ARM_CM23_NTZ/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM23_NTZ/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -48,11 +48,16 @@ /** * Architecture specifics. */ -#define portARCH_NAME "Cortex-M23" -#define portDONT_DISCARD __root +#define portARCH_NAME "Cortex-M23" +#define portHAS_BASEPRI 0 +#define portDONT_DISCARD __root +/*-----------------------------------------------------------*/ + +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" /*-----------------------------------------------------------*/ -#if( configTOTAL_MPU_REGIONS == 16 ) +#if ( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif /*-----------------------------------------------------------*/ @@ -60,8 +65,8 @@ /** * @brief Critical section management. */ -#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) -#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) +#define portDISABLE_INTERRUPTS() __asm volatile ( " cpsid i " ::: "memory" ) +#define portENABLE_INTERRUPTS() __asm volatile ( " cpsie i " ::: "memory" ) /*-----------------------------------------------------------*/ /* Suppress warnings that are generated by the IAR tools, but cannot be fixed in @@ -71,8 +76,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ARM_CM23_NTZ/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM23_NTZ/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/IAR/ARM_CM23_NTZ/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM23_NTZ/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/IAR/ARM_CM3/portmacro.h b/portable/IAR/ARM_CM3/portmacro.h index c334978ea73..92763ac7809 100644 --- a/portable/IAR/ARM_CM3/portmacro.h +++ b/portable/IAR/ARM_CM3/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -203,8 +205,10 @@ #pragma diag_suppress=Pe191 #pragma diag_suppress=Pa082 - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ARM_CM33/non_secure/port.c b/portable/IAR/ARM_CM33/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/IAR/ARM_CM33/non_secure/port.c +++ b/portable/IAR/ARM_CM33/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM33/non_secure/portmacro.h b/portable/IAR/ARM_CM33/non_secure/portmacro.h index b6df20eb88f..380768fc03b 100644 --- a/portable/IAR/ARM_CM33/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM33/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -49,6 +49,7 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M33" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ @@ -57,6 +58,10 @@ #endif /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + /** * @brief Critical section management. */ @@ -71,8 +76,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ARM_CM33/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM33/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/IAR/ARM_CM33/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM33/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/IAR/ARM_CM33_NTZ/non_secure/port.c b/portable/IAR/ARM_CM33_NTZ/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/IAR/ARM_CM33_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM33_NTZ/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM33_NTZ/non_secure/portmacro.h b/portable/IAR/ARM_CM33_NTZ/non_secure/portmacro.h index b6df20eb88f..815dca0861a 100644 --- a/portable/IAR/ARM_CM33_NTZ/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM33_NTZ/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -49,9 +49,14 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M33" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + #if( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif @@ -71,8 +76,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ARM_CM33_NTZ/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM33_NTZ/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/IAR/ARM_CM33_NTZ/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM33_NTZ/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/IAR/ARM_CM35P/non_secure/port.c b/portable/IAR/ARM_CM35P/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/IAR/ARM_CM35P/non_secure/port.c +++ b/portable/IAR/ARM_CM35P/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM35P/non_secure/portmacro.h b/portable/IAR/ARM_CM35P/non_secure/portmacro.h index a0efc1f9dcf..46bc4e24b56 100644 --- a/portable/IAR/ARM_CM35P/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM35P/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -49,9 +49,14 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M35P" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + #if( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif @@ -71,8 +76,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ARM_CM35P/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM35P/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/IAR/ARM_CM35P/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM35P/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c b/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM35P_NTZ/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM35P_NTZ/non_secure/portmacro.h b/portable/IAR/ARM_CM35P_NTZ/non_secure/portmacro.h index a0efc1f9dcf..46bc4e24b56 100644 --- a/portable/IAR/ARM_CM35P_NTZ/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM35P_NTZ/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -49,9 +49,14 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M35P" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + #if( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif @@ -71,8 +76,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ARM_CM35P_NTZ/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM35P_NTZ/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/IAR/ARM_CM35P_NTZ/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM35P_NTZ/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/IAR/ARM_CM4F/portmacro.h b/portable/IAR/ARM_CM4F/portmacro.h index 148c81d14ee..02f1d6ff038 100644 --- a/portable/IAR/ARM_CM4F/portmacro.h +++ b/portable/IAR/ARM_CM4F/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -202,8 +204,10 @@ #pragma diag_suppress=Pe191 #pragma diag_suppress=Pa082 - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ARM_CM55/non_secure/port.c b/portable/IAR/ARM_CM55/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/IAR/ARM_CM55/non_secure/port.c +++ b/portable/IAR/ARM_CM55/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM55/non_secure/portmacro.h b/portable/IAR/ARM_CM55/non_secure/portmacro.h index a3b510e282c..7829ee6186a 100644 --- a/portable/IAR/ARM_CM55/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM55/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -54,9 +54,14 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M55" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + #if( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif @@ -76,8 +81,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ARM_CM55/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM55/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/IAR/ARM_CM55/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM55/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/IAR/ARM_CM55_NTZ/non_secure/port.c b/portable/IAR/ARM_CM55_NTZ/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/IAR/ARM_CM55_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM55_NTZ/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM55_NTZ/non_secure/portmacro.h b/portable/IAR/ARM_CM55_NTZ/non_secure/portmacro.h index a3b510e282c..7829ee6186a 100644 --- a/portable/IAR/ARM_CM55_NTZ/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM55_NTZ/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -54,9 +54,14 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M55" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + #if( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif @@ -76,8 +81,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ARM_CM55_NTZ/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM55_NTZ/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/IAR/ARM_CM55_NTZ/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM55_NTZ/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/IAR/ARM_CM7/r0p1/portmacro.h b/portable/IAR/ARM_CM7/r0p1/portmacro.h index 08867c289c3..a2a2d878868 100644 --- a/portable/IAR/ARM_CM7/r0p1/portmacro.h +++ b/portable/IAR/ARM_CM7/r0p1/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -205,8 +207,10 @@ #pragma diag_suppress=Pe191 #pragma diag_suppress=Pa082 - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ARM_CM85/non_secure/port.c b/portable/IAR/ARM_CM85/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/IAR/ARM_CM85/non_secure/port.c +++ b/portable/IAR/ARM_CM85/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM85/non_secure/portmacro.h b/portable/IAR/ARM_CM85/non_secure/portmacro.h index cfaae813eac..3b51cb5ff46 100644 --- a/portable/IAR/ARM_CM85/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM85/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -54,9 +54,14 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M85" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + #if( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif @@ -76,8 +81,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ARM_CM85/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM85/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/IAR/ARM_CM85/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM85/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/IAR/ARM_CM85_NTZ/non_secure/port.c b/portable/IAR/ARM_CM85_NTZ/non_secure/port.c index 9976daee49a..7bbe1b7bc53 100644 --- a/portable/IAR/ARM_CM85_NTZ/non_secure/port.c +++ b/portable/IAR/ARM_CM85_NTZ/non_secure/port.c @@ -94,6 +94,19 @@ #define portSCB_MEM_FAULT_ENABLE_BIT ( 1UL << 16UL ) /*-----------------------------------------------------------*/ +/** + * @brief Constants required to check the validity of an interrupt priority. + */ +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xE000ED1C ) ) +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portTOP_BIT_OF_BYTE ( ( uint8_t ) 0x80 ) +#define portMAX_PRIGROUP_BITS ( ( uint8_t ) 7 ) +#define portPRIORITY_GROUP_MASK ( 0x07UL << 8UL ) +#define portPRIGROUP_SHIFT ( 8UL ) +/*-----------------------------------------------------------*/ + /** * @brief Constants required to manipulate the FPU. */ @@ -369,6 +382,19 @@ PRIVILEGED_DATA static volatile uint32_t ulCriticalNesting = 0xaaaaaaaaUL; PRIVILEGED_DATA portDONT_DISCARD volatile SecureContextHandle_t xSecureContext = portNO_SECURE_CONTEXT; #endif /* configENABLE_TRUSTZONE */ +/** + * @brief Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure + * 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 ) ) + + 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 ) ) */ + #if ( configUSE_TICKLESS_IDLE == 1 ) /** @@ -944,6 +970,7 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO } } /*-----------------------------------------------------------*/ + /* *INDENT-OFF* */ #if ( configENABLE_MPU == 1 ) StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, @@ -1069,6 +1096,114 @@ void vPortSVCHandler_C( uint32_t * pulCallerStackAddress ) /* PRIVILEGED_FUNCTIO BaseType_t xPortStartScheduler( void ) /* PRIVILEGED_FUNCTION */ { + #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t ucMaxPriorityValue; + + /* Determine the maximum priority from which ISR safe FreeRTOS API + * functions can be called. ISR safe functions are those that end in + * "FromISR". FreeRTOS maintains separate thread and ISR API functions to + * ensure interrupt entry is as fast and simple as possible. + * + * Save the interrupt priority value that is about to be clobbered. */ + ulOriginalPriority = portNVIC_SHPR2_REG; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + portNVIC_SHPR2_REG = 0xFF000000; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = ( uint8_t ) ( ( portNVIC_SHPR2_REG & 0xFF000000 ) >> 24 ); + + /* Use the same mask on the maximum system call priority. */ + ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + + /* Check that the maximum system call priority is nonzero after + * accounting for the number of priority bits supported by the + * hardware. A priority of 0 is invalid because setting the BASEPRI + * register to 0 unmasks all interrupts, and interrupts with priority 0 + * cannot be masked using BASEPRI. + * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ + configASSERT( ucMaxSysCallPriority ); + + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ + + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } + + if( ulImplementedPrioBits == 8 ) + { + /* When the hardware implements 8 priority bits, there is no way for + * the software to configure PRIGROUP to not have sub-priorities. As + * a result, the least significant bit is always used for sub-priority + * and there are 128 preemption priorities and 2 sub-priorities. + * + * This may cause some confusion in some cases - for example, if + * configMAX_SYSCALL_INTERRUPT_PRIORITY is set to 5, both 5 and 4 + * priority interrupts will be masked in Critical Sections as those + * are at the same preemption priority. This may appear confusing as + * 4 is higher (numerically lower) priority than + * configMAX_SYSCALL_INTERRUPT_PRIORITY and therefore, should not + * have been masked. Instead, if we set configMAX_SYSCALL_INTERRUPT_PRIORITY + * to 4, this confusion does not happen and the behaviour remains the same. + * + * The following assert ensures that the sub-priority bit in the + * configMAX_SYSCALL_INTERRUPT_PRIORITY is clear to avoid the above mentioned + * confusion. */ + configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY & 0x1U ) == 0U ); + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + /* The interrupt priority bits are not modelled in QEMU and the assert that + * checks the number of implemented bits and __NVIC_PRIO_BITS will always fail. + * Therefore, this assert is not adding any value for QEMU targets. The config + * option `configDISABLE_INTERRUPT_PRIO_BITS_CHECK` should be defined in the + * `FreeRTOSConfig.h` for QEMU targets. */ + #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK + { + #ifdef __NVIC_PRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the CMSIS __NVIC_PRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif /* __NVIC_PRIO_BITS */ + + #ifdef configPRIO_BITS + { + /* + * Check that the number of implemented priority bits queried from + * hardware is equal to the FreeRTOS configPRIO_BITS configuration macro. + */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif /* configPRIO_BITS */ + } + #endif /* #ifndef configDISABLE_INTERRUPT_PRIO_BITS_CHECK */ + + /* Shift the priority group value back to its position within the AIRCR + * register. */ + ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; + ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + + /* Restore the clobbered interrupt priority register to its original + * value. */ + portNVIC_SHPR2_REG = ulOriginalPriority; + } + #endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ + /* Make PendSV, CallSV and SysTick the same priority as the kernel. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; @@ -1259,3 +1394,64 @@ BaseType_t xPortIsInsideInterrupt( void ) return xReturn; } /*-----------------------------------------------------------*/ + +#if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) + + void vPortValidateInterruptPriority( void ) + { + uint32_t ulCurrentInterrupt; + uint8_t ucCurrentPriority; + + /* Obtain the number of the currently executing interrupt. */ + __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" ); + + /* Is the interrupt number a user defined interrupt? */ + if( ulCurrentInterrupt >= portFIRST_USER_INTERRUPT_NUMBER ) + { + /* Look up the interrupt's priority. */ + ucCurrentPriority = pcInterruptPriorityRegisters[ ulCurrentInterrupt ]; + + /* The following assertion will fail if a service routine (ISR) for + * an interrupt that has been assigned a priority above + * configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API + * function. ISR safe FreeRTOS API functions must *only* be called + * from interrupts that have been assigned a priority at or below + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Numerically low interrupt priority numbers represent logically high + * interrupt priorities, therefore the priority of the interrupt must + * be set to a value equal to or numerically *higher* than + * configMAX_SYSCALL_INTERRUPT_PRIORITY. + * + * Interrupts that use the FreeRTOS API must not be left at their + * default priority of zero as that is the highest possible priority, + * which is guaranteed to be above configMAX_SYSCALL_INTERRUPT_PRIORITY, + * and therefore also guaranteed to be invalid. + * + * FreeRTOS maintains separate thread and ISR API functions to ensure + * interrupt entry is as fast and simple as possible. + * + * The following links provide detailed information: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html + * https://www.FreeRTOS.org/FAQHelp.html */ + configASSERT( ucCurrentPriority >= ucMaxSysCallPriority ); + } + + /* Priority grouping: The interrupt controller (NVIC) allows the bits + * that define each interrupt's priority to be split between bits that + * define the interrupt's pre-emption priority bits and bits that define + * the interrupt's sub-priority. For simplicity all bits must be defined + * to be pre-emption priority bits. The following assertion will fail if + * this is not the case (if some bits represent a sub-priority). + * + * If the application only uses CMSIS libraries for interrupt + * configuration then the correct setting can be achieved on all Cortex-M + * devices by calling NVIC_SetPriorityGrouping( 0 ); before starting the + * scheduler. Note however that some vendor specific peripheral libraries + * assume a non-zero priority group setting, in which cases using a value + * of zero will result in unpredictable behaviour. */ + configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); + } + +#endif /* #if ( ( configASSERT_DEFINED == 1 ) && ( portHAS_BASEPRI == 1 ) ) */ +/*-----------------------------------------------------------*/ diff --git a/portable/IAR/ARM_CM85_NTZ/non_secure/portmacro.h b/portable/IAR/ARM_CM85_NTZ/non_secure/portmacro.h index cfaae813eac..3b51cb5ff46 100644 --- a/portable/IAR/ARM_CM85_NTZ/non_secure/portmacro.h +++ b/portable/IAR/ARM_CM85_NTZ/non_secure/portmacro.h @@ -29,11 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif - -#include "portmacrocommon.h" +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -54,9 +54,14 @@ * Architecture specifics. */ #define portARCH_NAME "Cortex-M85" +#define portHAS_BASEPRI 1 #define portDONT_DISCARD __root /*-----------------------------------------------------------*/ +/* ARMv8-M common port configurations. */ +#include "portmacrocommon.h" +/*-----------------------------------------------------------*/ + #if( configTOTAL_MPU_REGIONS == 16 ) #error 16 MPU regions are not yet supported for this port. #endif @@ -76,8 +81,10 @@ #pragma diag_suppress=Pa082 /*-----------------------------------------------------------*/ +/* *INDENT-OFF* */ #ifdef __cplusplus } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ARM_CM85_NTZ/non_secure/portmacrocommon.h b/portable/IAR/ARM_CM85_NTZ/non_secure/portmacrocommon.h index ca7e9225c05..c2ca5fa7730 100644 --- a/portable/IAR/ARM_CM85_NTZ/non_secure/portmacrocommon.h +++ b/portable/IAR/ARM_CM85_NTZ/non_secure/portmacrocommon.h @@ -27,11 +27,13 @@ */ #ifndef PORTMACROCOMMON_H - #define PORTMACROCOMMON_H +#define PORTMACROCOMMON_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*------------------------------------------------------------------------------ * Port specific definitions. @@ -43,114 +45,114 @@ *------------------------------------------------------------------------------ */ - #ifndef configENABLE_FPU - #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. - #endif /* configENABLE_FPU */ +#ifndef configENABLE_FPU + #error configENABLE_FPU must be defined in FreeRTOSConfig.h. Set configENABLE_FPU to 1 to enable the FPU or 0 to disable the FPU. +#endif /* configENABLE_FPU */ - #ifndef configENABLE_MPU - #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. - #endif /* configENABLE_MPU */ +#ifndef configENABLE_MPU + #error configENABLE_MPU must be defined in FreeRTOSConfig.h. Set configENABLE_MPU to 1 to enable the MPU or 0 to disable the MPU. +#endif /* configENABLE_MPU */ - #ifndef configENABLE_TRUSTZONE - #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. - #endif /* configENABLE_TRUSTZONE */ +#ifndef configENABLE_TRUSTZONE + #error configENABLE_TRUSTZONE must be defined in FreeRTOSConfig.h. Set configENABLE_TRUSTZONE to 1 to enable TrustZone or 0 to disable TrustZone. +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ /** * @brief Type definitions. */ - #define portCHAR char - #define portFLOAT float - #define portDOUBLE double - #define portLONG long - #define portSHORT short - #define portSTACK_TYPE uint32_t - #define portBASE_TYPE long - - typedef portSTACK_TYPE StackType_t; - typedef long BaseType_t; - typedef unsigned long UBaseType_t; - - #if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + 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. */ - #define portTICK_TYPE_IS_ATOMIC 1 - #else - #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. - #endif + #define portTICK_TYPE_IS_ATOMIC 1 +#else + #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. +#endif /*-----------------------------------------------------------*/ /** * Architecture specifics. */ - #define portSTACK_GROWTH ( -1 ) - #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) - #define portBYTE_ALIGNMENT 8 - #define portNOP() - #define portINLINE __inline - #ifndef portFORCE_INLINE - #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) - #endif - #define portHAS_STACK_OVERFLOW_CHECKING 1 +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portNOP() +#define portINLINE __inline +#ifndef portFORCE_INLINE + #define portFORCE_INLINE inline __attribute__( ( always_inline ) ) +#endif +#define portHAS_STACK_OVERFLOW_CHECKING 1 /*-----------------------------------------------------------*/ /** * @brief Extern declarations. */ - extern BaseType_t xPortIsInsideInterrupt( void ); +extern BaseType_t xPortIsInsideInterrupt( void ); - extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortYield( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; - extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortEnterCritical( void ) /* PRIVILEGED_FUNCTION */; +extern void vPortExitCritical( void ) /* PRIVILEGED_FUNCTION */; - extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern uint32_t ulSetInterruptMask( void ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; +extern void vClearInterruptMask( uint32_t ulMask ) /* __attribute__(( naked )) PRIVILEGED_FUNCTION */; - #if ( configENABLE_TRUSTZONE == 1 ) - extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ - extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; - #endif /* configENABLE_TRUSTZONE */ +#if ( configENABLE_TRUSTZONE == 1 ) + extern void vPortAllocateSecureContext( uint32_t ulSecureStackSize ); /* __attribute__ (( naked )) */ + extern void vPortFreeSecureContext( uint32_t * pulTCB ) /* __attribute__ (( naked )) PRIVILEGED_FUNCTION */; +#endif /* configENABLE_TRUSTZONE */ - #if ( configENABLE_MPU == 1 ) - extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; - extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + extern BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */; + extern void vResetPrivilege( void ) /* __attribute__ (( naked )) */; +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief MPU specific constants. */ - #if ( configENABLE_MPU == 1 ) - #define portUSING_MPU_WRAPPERS 1 - #define portPRIVILEGE_BIT ( 0x80000000UL ) - #else - #define portPRIVILEGE_BIT ( 0x0UL ) - #endif /* configENABLE_MPU */ +#if ( configENABLE_MPU == 1 ) + #define portUSING_MPU_WRAPPERS 1 + #define portPRIVILEGE_BIT ( 0x80000000UL ) +#else + #define portPRIVILEGE_BIT ( 0x0UL ) +#endif /* configENABLE_MPU */ /* MPU settings that can be overriden in FreeRTOSConfig.h. */ #ifndef configTOTAL_MPU_REGIONS /* Define to 8 for backward compatibility. */ - #define configTOTAL_MPU_REGIONS ( 8UL ) + #define configTOTAL_MPU_REGIONS ( 8UL ) #endif /* MPU regions. */ - #define portPRIVILEGED_FLASH_REGION ( 0UL ) - #define portUNPRIVILEGED_FLASH_REGION ( 1UL ) - #define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) - #define portPRIVILEGED_RAM_REGION ( 3UL ) - #define portSTACK_REGION ( 4UL ) - #define portFIRST_CONFIGURABLE_REGION ( 5UL ) - #define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) - #define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) - #define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ +#define portPRIVILEGED_FLASH_REGION ( 0UL ) +#define portUNPRIVILEGED_FLASH_REGION ( 1UL ) +#define portUNPRIVILEGED_SYSCALLS_REGION ( 2UL ) +#define portPRIVILEGED_RAM_REGION ( 3UL ) +#define portSTACK_REGION ( 4UL ) +#define portFIRST_CONFIGURABLE_REGION ( 5UL ) +#define portLAST_CONFIGURABLE_REGION ( configTOTAL_MPU_REGIONS - 1UL ) +#define portNUM_CONFIGURABLE_REGIONS ( ( portLAST_CONFIGURABLE_REGION - portFIRST_CONFIGURABLE_REGION ) + 1 ) +#define portTOTAL_NUM_REGIONS ( portNUM_CONFIGURABLE_REGIONS + 1 ) /* Plus one to make space for the stack region. */ /* Device memory attributes used in MPU_MAIR registers. * @@ -162,92 +164,105 @@ * 11 --> Device-GRE * Bit[1:0] - 00, Reserved. */ - #define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ - #define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ - #define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ - #define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ +#define portMPU_DEVICE_MEMORY_nGnRnE ( 0x00 ) /* 0000 0000 */ +#define portMPU_DEVICE_MEMORY_nGnRE ( 0x04 ) /* 0000 0100 */ +#define portMPU_DEVICE_MEMORY_nGRE ( 0x08 ) /* 0000 1000 */ +#define portMPU_DEVICE_MEMORY_GRE ( 0x0C ) /* 0000 1100 */ /* Normal memory attributes used in MPU_MAIR registers. */ - #define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ - #define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ +#define portMPU_NORMAL_MEMORY_NON_CACHEABLE ( 0x44 ) /* Non-cacheable. */ +#define portMPU_NORMAL_MEMORY_BUFFERABLE_CACHEABLE ( 0xFF ) /* Non-Transient, Write-back, Read-Allocate and Write-Allocate. */ /* Attributes used in MPU_RBAR registers. */ - #define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) - #define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) - #define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) +#define portMPU_REGION_NON_SHAREABLE ( 0UL << 3UL ) +#define portMPU_REGION_INNER_SHAREABLE ( 1UL << 3UL ) +#define portMPU_REGION_OUTER_SHAREABLE ( 2UL << 3UL ) - #define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) - #define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) - #define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) - #define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_WRITE ( 0UL << 1UL ) +#define portMPU_REGION_READ_WRITE ( 1UL << 1UL ) +#define portMPU_REGION_PRIVILEGED_READ_ONLY ( 2UL << 1UL ) +#define portMPU_REGION_READ_ONLY ( 3UL << 1UL ) - #define portMPU_REGION_EXECUTE_NEVER ( 1UL ) +#define portMPU_REGION_EXECUTE_NEVER ( 1UL ) /*-----------------------------------------------------------*/ /** * @brief Settings to define an MPU region. */ - typedef struct MPURegionSettings - { - uint32_t ulRBAR; /**< RBAR for the region. */ - uint32_t ulRLAR; /**< RLAR for the region. */ - } MPURegionSettings_t; +typedef struct MPURegionSettings +{ + uint32_t ulRBAR; /**< RBAR for the region. */ + uint32_t ulRLAR; /**< RLAR for the region. */ +} MPURegionSettings_t; /** * @brief MPU settings as stored in the TCB. */ - typedef struct MPU_SETTINGS - { - uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ - MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ - } xMPU_SETTINGS; +typedef struct MPU_SETTINGS +{ + uint32_t ulMAIR0; /**< MAIR0 for the task containing attributes for all the 4 per task regions. */ + MPURegionSettings_t xRegionsSettings[ portTOTAL_NUM_REGIONS ]; /**< Settings for 4 per task regions. */ +} xMPU_SETTINGS; /*-----------------------------------------------------------*/ +/** + * @brief Validate priority of ISRs that are allowed to call FreeRTOS + * system calls. + */ +#ifdef configASSERT + #if ( portHAS_BASEPRI == 1 ) + void vPortValidateInterruptPriority( void ); + #define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() vPortValidateInterruptPriority() + #endif +#endif + /** * @brief SVC numbers. */ - #define portSVC_ALLOCATE_SECURE_CONTEXT 0 - #define portSVC_FREE_SECURE_CONTEXT 1 - #define portSVC_START_SCHEDULER 2 - #define portSVC_RAISE_PRIVILEGE 3 +#define portSVC_ALLOCATE_SECURE_CONTEXT 0 +#define portSVC_FREE_SECURE_CONTEXT 1 +#define portSVC_START_SCHEDULER 2 +#define portSVC_RAISE_PRIVILEGE 3 /*-----------------------------------------------------------*/ /** * @brief Scheduler utilities. */ - #define portYIELD() vPortYield() - #define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) - #define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) - #define portEND_SWITCHING_ISR( xSwitchRequired ) do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } while( 0 ) - #define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) +#define portYIELD() vPortYield() +#define portNVIC_INT_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed04 ) ) +#define portNVIC_PENDSVSET_BIT ( 1UL << 28UL ) +#define portEND_SWITCHING_ISR( xSwitchRequired ) \ + do { if( xSwitchRequired ) portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } \ + while( 0 ) +#define portYIELD_FROM_ISR( x ) portEND_SWITCHING_ISR( x ) /*-----------------------------------------------------------*/ /** * @brief Critical section management. */ - #define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() - #define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) - #define portENTER_CRITICAL() vPortEnterCritical() - #define portEXIT_CRITICAL() vPortExitCritical() +#define portSET_INTERRUPT_MASK_FROM_ISR() ulSetInterruptMask() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) vClearInterruptMask( x ) +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /** * @brief Tickless idle/low power functionality. */ - #ifndef portSUPPRESS_TICKS_AND_SLEEP - extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); - #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) - #endif +#ifndef portSUPPRESS_TICKS_AND_SLEEP + extern void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ); + #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif /*-----------------------------------------------------------*/ /** * @brief Task function macros as described on the FreeRTOS.org WEB site. */ - #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) - #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) /*-----------------------------------------------------------*/ - #if ( configENABLE_TRUSTZONE == 1 ) +#if ( configENABLE_TRUSTZONE == 1 ) /** * @brief Allocate a secure context for the task. @@ -258,7 +273,7 @@ * * @param[in] ulSecureStackSize The size of the secure stack to be allocated. */ - #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) + #define portALLOCATE_SECURE_CONTEXT( ulSecureStackSize ) vPortAllocateSecureContext( ulSecureStackSize ) /** * @brief Called when a task is deleted to delete the task's secure context, @@ -266,18 +281,18 @@ * * @param[in] pxTCB The TCB of the task being deleted. */ - #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) - #endif /* configENABLE_TRUSTZONE */ + #define portCLEAN_UP_TCB( pxTCB ) vPortFreeSecureContext( ( uint32_t * ) pxTCB ) +#endif /* configENABLE_TRUSTZONE */ /*-----------------------------------------------------------*/ - #if ( configENABLE_MPU == 1 ) +#if ( configENABLE_MPU == 1 ) /** * @brief Checks whether or not the processor is privileged. * * @return 1 if the processor is already privileged, 0 otherwise. */ - #define portIS_PRIVILEGED() xIsPrivileged() + #define portIS_PRIVILEGED() xIsPrivileged() /** * @brief Raise an SVC request to raise privilege. @@ -286,28 +301,30 @@ * 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" ); + #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. */ - #define portRESET_PRIVILEGE() vResetPrivilege() - #else - #define portIS_PRIVILEGED() - #define portRAISE_PRIVILEGE() - #define portRESET_PRIVILEGE() - #endif /* configENABLE_MPU */ + #define portRESET_PRIVILEGE() vResetPrivilege() +#else + #define portIS_PRIVILEGED() + #define portRAISE_PRIVILEGE() + #define portRESET_PRIVILEGE() +#endif /* configENABLE_MPU */ /*-----------------------------------------------------------*/ /** * @brief Barriers. */ - #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) +#define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACROCOMMON_H */ diff --git a/portable/IAR/ARM_CRx_No_GIC/portmacro.h b/portable/IAR/ARM_CRx_No_GIC/portmacro.h index fbe4e166a59..82853af3ccf 100644 --- a/portable/IAR/ARM_CRx_No_GIC/portmacro.h +++ b/portable/IAR/ARM_CRx_No_GIC/portmacro.h @@ -31,9 +31,11 @@ #include +/* *INDENT-OFF* */ #ifdef __cplusplus extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -173,9 +175,10 @@ warnings. */ #pragma diag_suppress=Pe191 #pragma diag_suppress=Pa082 +/* *INDENT-OFF* */ #ifdef __cplusplus - } /* extern C */ + } #endif - +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/ATMega323/portmacro.h b/portable/IAR/ATMega323/portmacro.h index 111f4d02667..69ba2f1d9ac 100644 --- a/portable/IAR/ATMega323/portmacro.h +++ b/portable/IAR/ATMega323/portmacro.h @@ -36,9 +36,11 @@ Changes from V1.2.3 #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -106,8 +108,10 @@ void vPortYield( void ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/AVR32_UC3/portmacro.h b/portable/IAR/AVR32_UC3/portmacro.h index eb48b59b589..73c206ca5f8 100644 --- a/portable/IAR/AVR32_UC3/portmacro.h +++ b/portable/IAR/AVR32_UC3/portmacro.h @@ -87,9 +87,11 @@ #include "intc.h" #include "compiler.h" +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /* Type definitions. */ @@ -679,8 +681,10 @@ extern void *pvPortRealloc( void *pv, size_t xSize ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/AtmelSAM7S64/portmacro.h b/portable/IAR/AtmelSAM7S64/portmacro.h index 173d3fbaa2d..01c6eed6aad 100644 --- a/portable/IAR/AtmelSAM7S64/portmacro.h +++ b/portable/IAR/AtmelSAM7S64/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -105,8 +107,10 @@ extern void vTaskSwitchContext( void ); \ #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/AtmelSAM9XE/portmacro.h b/portable/IAR/AtmelSAM9XE/portmacro.h index 3d1d82ec17b..db6f10cca85 100644 --- a/portable/IAR/AtmelSAM9XE/portmacro.h +++ b/portable/IAR/AtmelSAM9XE/portmacro.h @@ -32,9 +32,11 @@ #include +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -108,8 +110,10 @@ extern void vTaskSwitchContext( void ); \ #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/LPC2000/portmacro.h b/portable/IAR/LPC2000/portmacro.h index f41d8b3445e..8fdf1fe75a3 100644 --- a/portable/IAR/LPC2000/portmacro.h +++ b/portable/IAR/LPC2000/portmacro.h @@ -32,9 +32,11 @@ #include +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -107,8 +109,10 @@ extern void vTaskSwitchContext( void ); \ #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/RISC-V/portmacro.h b/portable/IAR/RISC-V/portmacro.h index 42def7367aa..5dddb454c79 100644 --- a/portable/IAR/RISC-V/portmacro.h +++ b/portable/IAR/RISC-V/portmacro.h @@ -32,9 +32,11 @@ #include "intrinsics.h" +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -176,8 +178,10 @@ extern size_t xCriticalNesting; #error configMTIME_BASE_ADDRESS and configMTIMECMP_BASE_ADDRESS must be defined in FreeRTOSConfig.h. Set them to zero if there is no MTIME (machine time) clock. See https://www.FreeRTOS.org/Using-FreeRTOS-on-RISC-V.html #endif +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/RL78/portmacro.h b/portable/IAR/RL78/portmacro.h index 9c74a3f0452..9685b569d5d 100644 --- a/portable/IAR/RL78/portmacro.h +++ b/portable/IAR/RL78/portmacro.h @@ -31,9 +31,11 @@ #ifdef __IAR_SYSTEMS_ICC__ +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -141,9 +143,11 @@ extern volatile uint16_t usCriticalNesting; \ #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} -#endif /* __cplusplus */ + } +#endif +/* *INDENT-ON* */ #endif /* __IAR_SYSTEMS_ICC__ */ diff --git a/portable/IAR/RX100/portmacro.h b/portable/IAR/RX100/portmacro.h index d408a1389a5..e53c43e4ce5 100644 --- a/portable/IAR/RX100/portmacro.h +++ b/portable/IAR/RX100/portmacro.h @@ -32,9 +32,11 @@ #include +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /* Hardware specifics. */ #include "machine.h" @@ -145,8 +147,10 @@ undefined - all warnings have been manually checked and are not an issue, and the warnings cannot be prevent by code changes without undesirable effects. */ #pragma diag_suppress=Pa082 +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/RX600/portmacro.h b/portable/IAR/RX600/portmacro.h index e5decdaf34a..1b1bec3fc51 100644 --- a/portable/IAR/RX600/portmacro.h +++ b/portable/IAR/RX600/portmacro.h @@ -32,9 +32,11 @@ #include +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -134,8 +136,10 @@ extern void vTaskExitCritical( void ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/RX700v3_DPFPU/portmacro.h b/portable/IAR/RX700v3_DPFPU/portmacro.h index e0204fa0c3c..f8fde27908e 100644 --- a/portable/IAR/RX700v3_DPFPU/portmacro.h +++ b/portable/IAR/RX700v3_DPFPU/portmacro.h @@ -33,9 +33,11 @@ /* Hardware specifics. */ #include - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -191,8 +193,10 @@ * the warnings cannot be prevent by code changes without undesirable effects. */ #pragma diag_suppress=Pa082 - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/RXv2/portmacro.h b/portable/IAR/RXv2/portmacro.h index 984a4fb50e2..3f84484487d 100644 --- a/portable/IAR/RXv2/portmacro.h +++ b/portable/IAR/RXv2/portmacro.h @@ -32,9 +32,11 @@ #include +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -139,8 +141,10 @@ undefined - all warnings have been manually checked and are not an issue, and the warnings cannot be prevent by code changes without undesirable effects. */ #pragma diag_suppress=Pa082 +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/STR71x/portmacro.h b/portable/IAR/STR71x/portmacro.h index 119eec84786..1fbadff3ebe 100644 --- a/portable/IAR/STR71x/portmacro.h +++ b/portable/IAR/STR71x/portmacro.h @@ -42,9 +42,11 @@ #include +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /* Type definitions. */ @@ -115,8 +117,10 @@ extern void vTaskSwitchContext( void ); \ #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/STR75x/portmacro.h b/portable/IAR/STR75x/portmacro.h index 674505d3f0c..94a7b72ed0b 100644 --- a/portable/IAR/STR75x/portmacro.h +++ b/portable/IAR/STR75x/portmacro.h @@ -42,9 +42,11 @@ #include +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /* Type definitions. */ #define portCHAR char @@ -106,8 +108,10 @@ extern void vTaskSwitchContext( void ); \ #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/STR91x/portmacro.h b/portable/IAR/STR91x/portmacro.h index 43ea6d7e8dc..b5429b57dbc 100644 --- a/portable/IAR/STR91x/portmacro.h +++ b/portable/IAR/STR91x/portmacro.h @@ -42,9 +42,11 @@ #include +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /* Type definitions. */ #define portCHAR char @@ -108,8 +110,10 @@ extern void vTaskSwitchContext( void ); \ #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/IAR/V850ES/portmacro.h b/portable/IAR/V850ES/portmacro.h index 76b1186761d..cfae9ae7ca9 100644 --- a/portable/IAR/V850ES/portmacro.h +++ b/portable/IAR/V850ES/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -130,8 +132,10 @@ extern void vTaskSwitchContext( void ); #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/MPLAB/PIC24_dsPIC/portmacro.h b/portable/MPLAB/PIC24_dsPIC/portmacro.h index 83b695a43bb..0cc26f20633 100644 --- a/portable/MPLAB/PIC24_dsPIC/portmacro.h +++ b/portable/MPLAB/PIC24_dsPIC/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -108,8 +110,10 @@ extern void vPortYield( void ); #define portNOP() asm volatile ( "NOP" ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/MPLAB/PIC32MEC14xx/portmacro.h b/portable/MPLAB/PIC32MEC14xx/portmacro.h index d9aad5df0aa..9e00a1c05cc 100644 --- a/portable/MPLAB/PIC32MEC14xx/portmacro.h +++ b/portable/MPLAB/PIC32MEC14xx/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -244,8 +246,10 @@ extern volatile UBaseType_t uxInterruptNesting; #define portREMOVE_STATIC_QUALIFIER #endif +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/MPLAB/PIC32MX/portmacro.h b/portable/MPLAB/PIC32MX/portmacro.h index e2a1078e631..e0bf8dbd130 100644 --- a/portable/MPLAB/PIC32MX/portmacro.h +++ b/portable/MPLAB/PIC32MX/portmacro.h @@ -32,9 +32,11 @@ /* System include files */ #include +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -196,8 +198,10 @@ extern volatile UBaseType_t uxInterruptNesting; #define portREMOVE_STATIC_QUALIFIER #endif +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/MPLAB/PIC32MZ/portmacro.h b/portable/MPLAB/PIC32MZ/portmacro.h index 17b266e1124..371bcab6f26 100644 --- a/portable/MPLAB/PIC32MZ/portmacro.h +++ b/portable/MPLAB/PIC32MZ/portmacro.h @@ -32,9 +32,11 @@ /* System include files */ #include +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -207,8 +209,10 @@ extern volatile UBaseType_t uxInterruptNesting; #define portREMOVE_STATIC_QUALIFIER #endif +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/MikroC/ARM_CM4F/portmacro.h b/portable/MikroC/ARM_CM4F/portmacro.h index fa614c31488..b67a0a9d6a4 100644 --- a/portable/MikroC/ARM_CM4F/portmacro.h +++ b/portable/MikroC/ARM_CM4F/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -185,8 +187,10 @@ } /*-----------------------------------------------------------*/ - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/Paradigm/Tern_EE/large_untested/portmacro.h b/portable/Paradigm/Tern_EE/large_untested/portmacro.h index ed513309c7c..292c9e260d6 100644 --- a/portable/Paradigm/Tern_EE/large_untested/portmacro.h +++ b/portable/Paradigm/Tern_EE/large_untested/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -100,9 +102,11 @@ typedef unsigned short UBaseType_t; #define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters ) #define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/Paradigm/Tern_EE/small/portmacro.h b/portable/Paradigm/Tern_EE/small/portmacro.h index 9eb5b863023..ff0b34b2065 100644 --- a/portable/Paradigm/Tern_EE/small/portmacro.h +++ b/portable/Paradigm/Tern_EE/small/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -102,8 +104,10 @@ typedef void ( __interrupt __far *pxISR )(); #define portTASK_FUNCTION_PROTO( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters ) #define portTASK_FUNCTION( vTaskFunction, vParameters ) void vTaskFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/RVDS/ARM_CA9/portmacro.h b/portable/RVDS/ARM_CA9/portmacro.h index 65dd8174f7c..1351dae9f60 100644 --- a/portable/RVDS/ARM_CA9/portmacro.h +++ b/portable/RVDS/ARM_CA9/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -158,8 +160,10 @@ void vPortTaskUsesFPU( void ); #define portNOP() __nop() +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/Renesas/RX100/portmacro.h b/portable/Renesas/RX100/portmacro.h index 9bcbd3c8c3d..b82fdca2440 100644 --- a/portable/Renesas/RX100/portmacro.h +++ b/portable/Renesas/RX100/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /* Hardware specifics. */ #include "machine.h" @@ -146,8 +148,10 @@ extern void vTaskExitCritical( void ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/Renesas/RX200/portmacro.h b/portable/Renesas/RX200/portmacro.h index 62a085023e2..55278dacb15 100644 --- a/portable/Renesas/RX200/portmacro.h +++ b/portable/Renesas/RX200/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /* Hardware specifics. */ #include "machine.h" @@ -136,8 +138,10 @@ extern void vTaskExitCritical( void ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/Renesas/RX600/portmacro.h b/portable/Renesas/RX600/portmacro.h index 3b29cbddb50..60106ae13e7 100644 --- a/portable/Renesas/RX600/portmacro.h +++ b/portable/Renesas/RX600/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /* Hardware specifics. */ #include "machine.h" @@ -137,8 +139,10 @@ extern void vTaskExitCritical( void ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/Renesas/RX600v2/portmacro.h b/portable/Renesas/RX600v2/portmacro.h index d67a8f892aa..6efba647dbd 100644 --- a/portable/Renesas/RX600v2/portmacro.h +++ b/portable/Renesas/RX600v2/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /* Hardware specifics. */ #include "machine.h" @@ -137,8 +139,10 @@ extern void vTaskExitCritical( void ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/Renesas/RX700v3_DPFPU/portmacro.h b/portable/Renesas/RX700v3_DPFPU/portmacro.h index 12657ee82bf..fef13556e0d 100644 --- a/portable/Renesas/RX700v3_DPFPU/portmacro.h +++ b/portable/Renesas/RX700v3_DPFPU/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /* Hardware specifics. */ #include @@ -181,8 +183,10 @@ /* Definition to allow compatibility with existing FreeRTOS Demo using flop.c. */ #define portTASK_USES_FLOATING_POINT() vPortTaskUsesDPFPU() - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/Renesas/SH2A_FPU/portmacro.h b/portable/Renesas/SH2A_FPU/portmacro.h index 422cd59ed48..0ff2e323afa 100644 --- a/portable/Renesas/SH2A_FPU/portmacro.h +++ b/portable/Renesas/SH2A_FPU/portmacro.h @@ -32,9 +32,11 @@ #include +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -132,8 +134,10 @@ extern void vTaskExitCritical( void ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/Tasking/ARM_CM4F/portmacro.h b/portable/Tasking/ARM_CM4F/portmacro.h index 3371f34f47a..1c3588b8630 100644 --- a/portable/Tasking/ARM_CM4F/portmacro.h +++ b/portable/Tasking/ARM_CM4F/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -128,8 +130,10 @@ #define portNOP() - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/ThirdParty/CDK/T-HEAD_CK802/portmacro.h b/portable/ThirdParty/CDK/T-HEAD_CK802/portmacro.h index b82e48695d9..2c6979faf53 100644 --- a/portable/ThirdParty/CDK/T-HEAD_CK802/portmacro.h +++ b/portable/ThirdParty/CDK/T-HEAD_CK802/portmacro.h @@ -30,10 +30,13 @@ #include extern void vPortYield(void); + +/* *INDENT-OFF* */ #ifdef __cplusplus -class vPortYield; -extern "C" { + class vPortYield; + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- @@ -154,8 +157,10 @@ extern portLONG pendsvflag; +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/ThirdParty/GCC/ARC_v1/portmacro.h b/portable/ThirdParty/GCC/ARC_v1/portmacro.h index 72fbb49759e..137cbc05d93 100644 --- a/portable/ThirdParty/GCC/ARC_v1/portmacro.h +++ b/portable/ThirdParty/GCC/ARC_v1/portmacro.h @@ -30,9 +30,11 @@ #define PORTMACRO_H #include "embARC.h" - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ /* record stack high address for stack check */ #ifndef configRECORD_STACK_HIGH_ADDRESS @@ -143,8 +145,10 @@ void vPortYield( void ); void vPortYieldFromIsr( void ); - #ifdef __cplusplus -} - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/ThirdParty/GCC/ATmega/portmacro.h b/portable/ThirdParty/GCC/ATmega/portmacro.h index 3e7714eb836..8292f2d7ed9 100644 --- a/portable/ThirdParty/GCC/ATmega/portmacro.h +++ b/portable/ThirdParty/GCC/ATmega/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -152,8 +154,10 @@ extern void vPortYieldFromISR( void ) __attribute__ ( ( naked ) ); #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/ThirdParty/GCC/Posix/port.c b/portable/ThirdParty/GCC/Posix/port.c index d634c8b264e..5ac570d9a59 100644 --- a/portable/ThirdParty/GCC/Posix/port.c +++ b/portable/ThirdParty/GCC/Posix/port.c @@ -61,6 +61,10 @@ #include #include +#ifdef __APPLE__ + #include +#endif + /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" @@ -146,6 +150,11 @@ portSTACK_TYPE * pxPortInitialiseStack( StackType_t * pxTopOfStack, pxTopOfStack = ( portSTACK_TYPE * ) thread - 1; ulStackSize = ( size_t )( pxTopOfStack + 1 - pxEndOfStack ) * sizeof( *pxTopOfStack ); + #ifdef __APPLE__ + pxEndOfStack = mach_vm_round_page ( pxEndOfStack ); + ulStackSize = mach_vm_trunc_page ( ulStackSize ); + #endif + thread->pxCode = pxCode; thread->pvParams = pvParameters; thread->xDying = pdFALSE; diff --git a/portable/ThirdParty/GCC/Posix/portmacro.h b/portable/ThirdParty/GCC/Posix/portmacro.h index 68655861202..a3ab7d32393 100644 --- a/portable/ThirdParty/GCC/Posix/portmacro.h +++ b/portable/ThirdParty/GCC/Posix/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ #include @@ -130,8 +132,10 @@ extern unsigned long ulPortGetRunTime( void ); #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() /* no-op */ #define portGET_RUN_TIME_COUNTER_VALUE() ulPortGetRunTime() +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/ThirdParty/GCC/RP2040/include/portmacro.h b/portable/ThirdParty/GCC/RP2040/include/portmacro.h index 6ad352a04ba..cec4f7fedeb 100644 --- a/portable/ThirdParty/GCC/RP2040/include/portmacro.h +++ b/portable/ThirdParty/GCC/RP2040/include/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ #include "pico.h" #include "hardware/sync.h" @@ -257,8 +259,10 @@ #define portMEMORY_BARRIER() __asm volatile ( "" ::: "memory" ) - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/ThirdParty/GCC/RP2040/include/rp2040_config.h b/portable/ThirdParty/GCC/RP2040/include/rp2040_config.h index c383188a2a9..35c6f246352 100644 --- a/portable/ThirdParty/GCC/RP2040/include/rp2040_config.h +++ b/portable/ThirdParty/GCC/RP2040/include/rp2040_config.h @@ -29,9 +29,11 @@ #ifndef RP2040_CONFIG_H #define RP2040_CONFIG_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /* configUSE_DYNAMIC_EXCEPTION_HANDLERS == 1 means set the exception handlers dynamically on cores * that need them in case the user has set up distinct vector table offsets per core @@ -82,8 +84,10 @@ extern "C" { #define configSMP_SPINLOCK_1 PICO_SPINLOCK_ID_OS2 #endif +/* *INDENT-OFF* */ #ifdef __cplusplus -}; + } #endif +/* *INDENT-ON* */ #endif diff --git a/portable/ThirdParty/GCC/Xtensa_ESP32/include/port_systick.h b/portable/ThirdParty/GCC/Xtensa_ESP32/include/port_systick.h index 18b47f3154e..738b5a18001 100644 --- a/portable/ThirdParty/GCC/Xtensa_ESP32/include/port_systick.h +++ b/portable/ThirdParty/GCC/Xtensa_ESP32/include/port_systick.h @@ -6,15 +6,19 @@ #pragma once +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /** * @brief Set up the SysTick interrupt */ void vPortSetupTimer(void); +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ diff --git a/portable/ThirdParty/GCC/Xtensa_ESP32/include/xtensa_config.h b/portable/ThirdParty/GCC/Xtensa_ESP32/include/xtensa_config.h index cb20b188504..78ef67da888 100644 --- a/portable/ThirdParty/GCC/Xtensa_ESP32/include/xtensa_config.h +++ b/portable/ThirdParty/GCC/Xtensa_ESP32/include/xtensa_config.h @@ -42,9 +42,11 @@ #ifndef XTENSA_CONFIG_H #define XTENSA_CONFIG_H - #ifdef __cplusplus - extern "C" { - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + extern "C" { +#endif +/* *INDENT-ON* */ #include #include @@ -146,9 +148,10 @@ #define XT_STACK_EXTRA ( XT_XTRA_SIZE ) #define XT_STACK_EXTRA_CLIB ( XT_XTRA_SIZE + XT_CLIB_CONTEXT_AREA_SIZE ) - - #ifdef __cplusplus - } - #endif +/* *INDENT-OFF* */ +#ifdef __cplusplus + } +#endif +/* *INDENT-ON* */ #endif /* XTENSA_CONFIG_H */ diff --git a/portable/ThirdParty/XCC/Xtensa/portmacro.h b/portable/ThirdParty/XCC/Xtensa/portmacro.h index c81576c9f78..f84e4335e1e 100644 --- a/portable/ThirdParty/XCC/Xtensa/portmacro.h +++ b/portable/ThirdParty/XCC/Xtensa/portmacro.h @@ -30,9 +30,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ #ifndef __ASSEMBLER__ @@ -204,8 +206,10 @@ static inline void vPortCleanUpTcbClib(struct _reent *ptr) #endif // __ASSEMBLER__ +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/ThirdParty/XCC/Xtensa/xtensa_config.h b/portable/ThirdParty/XCC/Xtensa/xtensa_config.h index 18f3e82c555..a5efcda5898 100644 --- a/portable/ThirdParty/XCC/Xtensa/xtensa_config.h +++ b/portable/ThirdParty/XCC/Xtensa/xtensa_config.h @@ -39,9 +39,11 @@ #ifndef XTENSA_CONFIG_H #define XTENSA_CONFIG_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ #include #include @@ -180,8 +182,10 @@ extern "C" { #define XT_STACK_EXTRA_CLIB (XT_XTRA_SIZE + XT_CLIB_CONTEXT_AREA_SIZE) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* XTENSA_CONFIG_H */ diff --git a/portable/oWatcom/16BitDOS/Flsh186/portmacro.h b/portable/oWatcom/16BitDOS/Flsh186/portmacro.h index a2b4c16a40b..952e3f68021 100644 --- a/portable/oWatcom/16BitDOS/Flsh186/portmacro.h +++ b/portable/oWatcom/16BitDOS/Flsh186/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -105,8 +107,10 @@ void portENABLE_INTERRUPTS( void ); #define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) #define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/portable/oWatcom/16BitDOS/PC/portmacro.h b/portable/oWatcom/16BitDOS/PC/portmacro.h index ab4eea87210..2fb7534117a 100644 --- a/portable/oWatcom/16BitDOS/PC/portmacro.h +++ b/portable/oWatcom/16BitDOS/PC/portmacro.h @@ -29,9 +29,11 @@ #ifndef PORTMACRO_H #define PORTMACRO_H +/* *INDENT-OFF* */ #ifdef __cplusplus -extern "C" { + extern "C" { #endif +/* *INDENT-ON* */ /*----------------------------------------------------------- * Port specific definitions. @@ -106,9 +108,11 @@ void portENABLE_INTERRUPTS( void ); #define portTASK_FUNCTION_PROTO( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters ) #define portTASK_FUNCTION( vTaskFunction, pvParameters ) void vTaskFunction( void *pvParameters ) +/* *INDENT-OFF* */ #ifdef __cplusplus -} + } #endif +/* *INDENT-ON* */ #endif /* PORTMACRO_H */ diff --git a/stream_buffer.c b/stream_buffer.c index e3c62ab1da2..890202e601a 100644 --- a/stream_buffer.c +++ b/stream_buffer.c @@ -324,7 +324,7 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, StreamBufferCallbackFunction_t pxSendCompletedCallback, StreamBufferCallbackFunction_t pxReceiveCompletedCallback ) { - uint8_t * pucAllocatedMemory; + void * pvAllocatedMemory; uint8_t ucFlags; /* In case the stream buffer is going to be used as a message buffer @@ -364,31 +364,31 @@ static void prvInitialiseNewStreamBuffer( StreamBuffer_t * const pxStreamBuffer, if( xBufferSizeBytes < ( xBufferSizeBytes + 1 + sizeof( StreamBuffer_t ) ) ) { xBufferSizeBytes++; - pucAllocatedMemory = ( uint8_t * ) pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) ); /*lint !e9079 malloc() only returns void*. */ + pvAllocatedMemory = pvPortMalloc( xBufferSizeBytes + sizeof( StreamBuffer_t ) ); } else { - pucAllocatedMemory = NULL; + pvAllocatedMemory = NULL; } - if( pucAllocatedMemory != NULL ) + if( pvAllocatedMemory != NULL ) { - prvInitialiseNewStreamBuffer( ( StreamBuffer_t * ) pucAllocatedMemory, /* Structure at the start of the allocated memory. */ /*lint !e9087 Safe cast as allocated memory is aligned. */ /*lint !e826 Area is not too small and alignment is guaranteed provided malloc() behaves as expected and returns aligned buffer. */ - pucAllocatedMemory + sizeof( StreamBuffer_t ), /* Storage area follows. */ /*lint !e9016 Indexing past structure valid for uint8_t pointer, also storage area has no alignment requirement. */ + prvInitialiseNewStreamBuffer( ( StreamBuffer_t * ) pvAllocatedMemory, /* Structure at the start of the allocated memory. */ /*lint !e9087 Safe cast as allocated memory is aligned. */ /*lint !e826 Area is not too small and alignment is guaranteed provided malloc() behaves as expected and returns aligned buffer. */ + ( ( uint8_t * ) pvAllocatedMemory ) + sizeof( StreamBuffer_t ), /* Storage area follows. */ /*lint !e9016 Indexing past structure valid for uint8_t pointer, also storage area has no alignment requirement. */ xBufferSizeBytes, xTriggerLevelBytes, ucFlags, pxSendCompletedCallback, pxReceiveCompletedCallback ); - traceSTREAM_BUFFER_CREATE( ( ( StreamBuffer_t * ) pucAllocatedMemory ), xIsMessageBuffer ); + traceSTREAM_BUFFER_CREATE( ( ( StreamBuffer_t * ) pvAllocatedMemory ), xIsMessageBuffer ); } else { traceSTREAM_BUFFER_CREATE_FAILED( xIsMessageBuffer ); } - return ( StreamBufferHandle_t ) pucAllocatedMemory; /*lint !e9087 !e826 Safe cast as allocated memory is aligned. */ + return ( StreamBufferHandle_t ) pvAllocatedMemory; /*lint !e9087 !e826 Safe cast as allocated memory is aligned. */ } #endif /* configSUPPORT_DYNAMIC_ALLOCATION */ /*-----------------------------------------------------------*/ diff --git a/tasks.c b/tasks.c index 5d8d3233ee3..0a4a1fe672b 100644 --- a/tasks.c +++ b/tasks.c @@ -451,7 +451,7 @@ const volatile UBaseType_t uxTopUsedPriority = configMAX_PRIORITIES - 1U; * Updates to uxSchedulerSuspended must be protected by both the task lock and the ISR lock * and must not be done from an ISR. Reads must be protected by either lock and may be done * from either an ISR or a task. */ -PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) pdFALSE; +PRIVILEGED_DATA static volatile UBaseType_t uxSchedulerSuspended = ( UBaseType_t ) 0U; #if ( configGENERATE_RUN_TIME_STATS == 1 ) @@ -3012,7 +3012,7 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode, traceTASK_RESUME_FROM_ISR( pxTCB ); /* Check the ready lists can be accessed. */ - if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) { #if ( configNUMBER_OF_CORES == 1 ) { @@ -3511,7 +3511,7 @@ BaseType_t xTaskResumeAll( void ) --uxSchedulerSuspended; portRELEASE_TASK_LOCK(); - if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) { if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U ) { @@ -4050,7 +4050,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char /* Arrange for xTickCount to reach xNextTaskUnblockTime in * xTaskIncrementTick() when the scheduler resumes. This ensures * that any delayed tasks are resumed at the correct time. */ - configASSERT( uxSchedulerSuspended ); + configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U ); configASSERT( xTicksToJump != ( TickType_t ) 0 ); /* Prevent the tick interrupt modifying xPendedTicks simultaneously. */ @@ -4079,7 +4079,7 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) /* Must not be called with the scheduler suspended as the implementation * relies on xPendedTicks being wound down to 0 in xTaskResumeAll(). */ - configASSERT( uxSchedulerSuspended == 0 ); + configASSERT( uxSchedulerSuspended == ( UBaseType_t ) 0U ); /* Use xPendedTicks to mimic xTicksToCatchUp number of ticks occurring when * the scheduler is suspended so the ticks are executed in xTaskResumeAll(). */ @@ -4208,7 +4208,7 @@ BaseType_t xTaskIncrementTick( void ) * responsibility to increment the tick, or increment the pended ticks if the * scheduler is suspended. If pended ticks is greater than zero, the core that * calls xTaskResumeAll has the responsibility to increment the tick. */ - if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) { /* Minor optimisation. The tick count cannot change in this * block. */ @@ -4551,7 +4551,7 @@ BaseType_t xTaskIncrementTick( void ) #if ( configNUMBER_OF_CORES == 1 ) void vTaskSwitchContext( void ) { - if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE ) + if( uxSchedulerSuspended != ( UBaseType_t ) 0U ) { /* The scheduler is currently suspended - do not allow a context * switch. */ @@ -4640,7 +4640,7 @@ BaseType_t xTaskIncrementTick( void ) * SMP port. */ configASSERT( portGET_CRITICAL_NESTING_COUNT() == 0 ); - if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE ) + if( uxSchedulerSuspended != ( UBaseType_t ) 0U ) { /* The scheduler is currently suspended - do not allow a context * switch. */ @@ -4748,7 +4748,7 @@ void vTaskPlaceOnUnorderedEventList( List_t * pxEventList, /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by * the event groups implementation. */ - configASSERT( uxSchedulerSuspended != 0 ); + configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U ); /* Store the item value in the event list item. It is safe to access the * event list item here as interrupts won't access the event list item of a @@ -4823,7 +4823,7 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList ) configASSERT( pxUnblockedTCB ); listREMOVE_ITEM( &( pxUnblockedTCB->xEventListItem ) ); - if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) { listREMOVE_ITEM( &( pxUnblockedTCB->xStateListItem ) ); prvAddTaskToReadyList( pxUnblockedTCB ); @@ -4895,7 +4895,7 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem, /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. It is used by * the event flags implementation. */ - configASSERT( uxSchedulerSuspended != pdFALSE ); + configASSERT( uxSchedulerSuspended != ( UBaseType_t ) 0U ); /* Store the new item value in the event list. */ listSET_LIST_ITEM_VALUE( pxEventListItem, xItemValue | taskEVENT_LIST_ITEM_VALUE_IN_USE ); @@ -5890,7 +5890,7 @@ static void prvResetNextTaskUnblockTime( void ) taskENTER_CRITICAL(); #endif { - if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) { xReturn = taskSCHEDULER_RUNNING; } @@ -7174,7 +7174,7 @@ TickType_t uxTaskResetEventItemValue( void ) /* The task should not have been on an event list. */ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); - if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) { listREMOVE_ITEM( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB ); @@ -7285,7 +7285,7 @@ TickType_t uxTaskResetEventItemValue( void ) /* The task should not have been on an event list. */ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); - if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE ) + if( uxSchedulerSuspended == ( UBaseType_t ) 0U ) { listREMOVE_ITEM( &( pxTCB->xStateListItem ) ); prvAddTaskToReadyList( pxTCB );