From c6edb3375024b5aef702fd66a565be634ee306cc Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Mon, 6 Mar 2023 05:24:00 +0000 Subject: [PATCH 01/21] Cortex-M Assert when NVIC implements 8 PRIO bits --- portable/CCS/ARM_CM3/port.c | 18 +++-- portable/CCS/ARM_CM4F/port.c | 18 +++-- portable/GCC/ARM_CM3/port.c | 20 +++-- portable/GCC/ARM_CM3_MPU/port.c | 128 ++++++++++++++++-------------- portable/GCC/ARM_CM4F/port.c | 20 +++-- portable/GCC/ARM_CM4_MPU/port.c | 128 ++++++++++++++++-------------- portable/GCC/ARM_CM7/r0p1/port.c | 20 +++-- portable/MikroC/ARM_CM4F/port.c | 20 +++-- portable/RVDS/ARM_CM3/port.c | 18 +++-- portable/RVDS/ARM_CM4F/port.c | 18 +++-- portable/RVDS/ARM_CM4_MPU/port.c | 128 ++++++++++++++++-------------- portable/RVDS/ARM_CM7/r0p1/port.c | 18 +++-- portable/Tasking/ARM_CM4F/port.c | 79 ++++++++++++++++++ 13 files changed, 404 insertions(+), 229 deletions(-) mode change 100644 => 100755 portable/CCS/ARM_CM3/port.c mode change 100644 => 100755 portable/CCS/ARM_CM4F/port.c mode change 100644 => 100755 portable/GCC/ARM_CM3/port.c mode change 100644 => 100755 portable/GCC/ARM_CM3_MPU/port.c mode change 100644 => 100755 portable/GCC/ARM_CM4F/port.c mode change 100644 => 100755 portable/GCC/ARM_CM4_MPU/port.c mode change 100644 => 100755 portable/GCC/ARM_CM7/r0p1/port.c mode change 100644 => 100755 portable/MikroC/ARM_CM4F/port.c mode change 100644 => 100755 portable/RVDS/ARM_CM3/port.c mode change 100644 => 100755 portable/RVDS/ARM_CM4F/port.c mode change 100644 => 100755 portable/RVDS/ARM_CM4_MPU/port.c mode change 100644 => 100755 portable/RVDS/ARM_CM7/r0p1/port.c mode change 100644 => 100755 portable/Tasking/ARM_CM4F/port.c diff --git a/portable/CCS/ARM_CM3/port.c b/portable/CCS/ARM_CM3/port.c old mode 100644 new mode 100755 index dfdb240ed2..22c3882e46 --- a/portable/CCS/ARM_CM3/port.c +++ b/portable/CCS/ARM_CM3/port.c @@ -218,7 +218,7 @@ BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority; + volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; @@ -250,20 +250,28 @@ BaseType_t xPortStartScheduler( void ) /* Calculate the maximum acceptable priority group value for the number * of bits read back. */ - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) { - ulMaxPRIGROUPValue--; + ulImplementedPrioBits++; ucMaxPriorityValue <<= ( uint8_t ) 0x01; } + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + #ifdef __NVIC_PRIO_BITS { /* Check the CMSIS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); } #endif @@ -272,7 +280,7 @@ BaseType_t xPortStartScheduler( void ) /* Check the FreeRTOS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); } #endif diff --git a/portable/CCS/ARM_CM4F/port.c b/portable/CCS/ARM_CM4F/port.c old mode 100644 new mode 100755 index 360e83d700..79d24f8062 --- a/portable/CCS/ARM_CM4F/port.c +++ b/portable/CCS/ARM_CM4F/port.c @@ -237,7 +237,7 @@ BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority; + volatile uint32_t ulOriginalPriority, ulImplementedPrioBits = 0; volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; @@ -269,20 +269,28 @@ BaseType_t xPortStartScheduler( void ) /* Calculate the maximum acceptable priority group value for the number * of bits read back. */ - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) { - ulMaxPRIGROUPValue--; + ulImplementedPrioBits++; ucMaxPriorityValue <<= ( uint8_t ) 0x01; } + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + #ifdef __NVIC_PRIO_BITS { /* Check the CMSIS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); } #endif @@ -291,7 +299,7 @@ BaseType_t xPortStartScheduler( void ) /* Check the FreeRTOS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); } #endif diff --git a/portable/GCC/ARM_CM3/port.c b/portable/GCC/ARM_CM3/port.c old mode 100644 new mode 100755 index a5cea1e1e1..250fa2c750 --- a/portable/GCC/ARM_CM3/port.c +++ b/portable/GCC/ARM_CM3/port.c @@ -261,8 +261,8 @@ BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority; - volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API @@ -293,20 +293,28 @@ BaseType_t xPortStartScheduler( void ) /* Calculate the maximum acceptable priority group value for the number * of bits read back. */ - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) { - ulMaxPRIGROUPValue--; + ulImplementedPrioBits++; ucMaxPriorityValue <<= ( uint8_t ) 0x01; } + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + #ifdef __NVIC_PRIO_BITS { /* Check the CMSIS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); } #endif @@ -315,7 +323,7 @@ BaseType_t xPortStartScheduler( void ) /* Check the FreeRTOS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); } #endif diff --git a/portable/GCC/ARM_CM3_MPU/port.c b/portable/GCC/ARM_CM3_MPU/port.c old mode 100644 new mode 100755 index 5f7d2c8111..6ac436f2b3 --- a/portable/GCC/ARM_CM3_MPU/port.c +++ b/portable/GCC/ARM_CM3_MPU/port.c @@ -383,74 +383,82 @@ static void prvRestoreContextOfFirstTask( void ) BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) - { - volatile uint32_t ulOriginalPriority; - volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); - 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 = *pucFirstUserPriorityRegister; + { + volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + 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 = *pucFirstUserPriorityRegister; - /* Determine the number of priority bits available. First write to all - * possible bits. */ - *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + /* Determine the number of priority bits available. First write to all + * possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; - /* Read the value back to see how many bits stuck. */ - ucMaxPriorityValue = *pucFirstUserPriorityRegister; + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; - /* Use the same mask on the maximum system call priority. */ - ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + /* 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 ); + /* 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. */ - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ - while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) - { - ulMaxPRIGROUPValue--; - ucMaxPriorityValue <<= ( uint8_t ) 0x01; - } + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } - #ifdef __NVIC_PRIO_BITS - { - /* Check the CMSIS configuration that defines the number of - * priority bits matches the number of priority bits actually queried - * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); - } - #endif - - #ifdef configPRIO_BITS - { - /* Check the FreeRTOS configuration that defines the number of - * priority bits matches the number of priority bits actually queried - * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); - } - #endif - - /* 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. */ - *pucFirstUserPriorityRegister = ulOriginalPriority; + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; } + + #ifdef __NVIC_PRIO_BITS + { + /* Check the CMSIS configuration that defines the number of + * priority bits matches the number of priority bits actually queried + * from the hardware. */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif + + #ifdef configPRIO_BITS + { + /* Check the FreeRTOS configuration that defines the number of + * priority bits matches the number of priority bits actually queried + * from the hardware. */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif + + /* 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. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } #endif /* configASSERT_DEFINED */ /* Make PendSV and SysTick the same priority as the kernel, and the SVC diff --git a/portable/GCC/ARM_CM4F/port.c b/portable/GCC/ARM_CM4F/port.c old mode 100644 new mode 100755 index b978f0af54..9db50a7334 --- a/portable/GCC/ARM_CM4F/port.c +++ b/portable/GCC/ARM_CM4F/port.c @@ -304,8 +304,8 @@ BaseType_t xPortStartScheduler( void ) #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority; - volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API @@ -336,20 +336,28 @@ BaseType_t xPortStartScheduler( void ) /* Calculate the maximum acceptable priority group value for the number * of bits read back. */ - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) { - ulMaxPRIGROUPValue--; + ulImplementedPrioBits++; ucMaxPriorityValue <<= ( uint8_t ) 0x01; } + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + #ifdef __NVIC_PRIO_BITS { /* Check the CMSIS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); } #endif @@ -358,7 +366,7 @@ BaseType_t xPortStartScheduler( void ) /* Check the FreeRTOS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); } #endif diff --git a/portable/GCC/ARM_CM4_MPU/port.c b/portable/GCC/ARM_CM4_MPU/port.c old mode 100644 new mode 100755 index 57d0ea5a2f..36c9775005 --- a/portable/GCC/ARM_CM4_MPU/port.c +++ b/portable/GCC/ARM_CM4_MPU/port.c @@ -426,74 +426,82 @@ BaseType_t xPortStartScheduler( void ) #endif #if ( configASSERT_DEFINED == 1 ) - { - volatile uint32_t ulOriginalPriority; - volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); - 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 = *pucFirstUserPriorityRegister; + { + volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + 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 = *pucFirstUserPriorityRegister; - /* Determine the number of priority bits available. First write to all - * possible bits. */ - *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + /* Determine the number of priority bits available. First write to all + * possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; - /* Read the value back to see how many bits stuck. */ - ucMaxPriorityValue = *pucFirstUserPriorityRegister; + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; - /* Use the same mask on the maximum system call priority. */ - ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + /* 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 ); + /* 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. */ - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ - while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) - { - ulMaxPRIGROUPValue--; - ucMaxPriorityValue <<= ( uint8_t ) 0x01; - } + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } - #ifdef __NVIC_PRIO_BITS - { - /* Check the CMSIS configuration that defines the number of - * priority bits matches the number of priority bits actually queried - * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); - } - #endif - - #ifdef configPRIO_BITS - { - /* Check the FreeRTOS configuration that defines the number of - * priority bits matches the number of priority bits actually queried - * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); - } - #endif - - /* 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. */ - *pucFirstUserPriorityRegister = ulOriginalPriority; + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; } + + #ifdef __NVIC_PRIO_BITS + { + /* Check the CMSIS configuration that defines the number of + * priority bits matches the number of priority bits actually queried + * from the hardware. */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif + + #ifdef configPRIO_BITS + { + /* Check the FreeRTOS configuration that defines the number of + * priority bits matches the number of priority bits actually queried + * from the hardware. */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif + + /* 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. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } #endif /* configASSERT_DEFINED */ /* Make PendSV and SysTick the same priority as the kernel, and the SVC diff --git a/portable/GCC/ARM_CM7/r0p1/port.c b/portable/GCC/ARM_CM7/r0p1/port.c old mode 100644 new mode 100755 index c602bd297c..cf3696bedd --- a/portable/GCC/ARM_CM7/r0p1/port.c +++ b/portable/GCC/ARM_CM7/r0p1/port.c @@ -292,8 +292,8 @@ BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority; - volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API @@ -324,20 +324,28 @@ BaseType_t xPortStartScheduler( void ) /* Calculate the maximum acceptable priority group value for the number * of bits read back. */ - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) { - ulMaxPRIGROUPValue--; + ulImplementedPrioBits++; ucMaxPriorityValue <<= ( uint8_t ) 0x01; } + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + #ifdef __NVIC_PRIO_BITS { /* Check the CMSIS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); } #endif @@ -346,7 +354,7 @@ BaseType_t xPortStartScheduler( void ) /* Check the FreeRTOS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); } #endif diff --git a/portable/MikroC/ARM_CM4F/port.c b/portable/MikroC/ARM_CM4F/port.c old mode 100644 new mode 100755 index 886913fbc4..1106e83a8e --- a/portable/MikroC/ARM_CM4F/port.c +++ b/portable/MikroC/ARM_CM4F/port.c @@ -298,8 +298,8 @@ BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority; - volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API @@ -330,20 +330,28 @@ BaseType_t xPortStartScheduler( void ) /* Calculate the maximum acceptable priority group value for the number * of bits read back. */ - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) { - ulMaxPRIGROUPValue--; + ulImplementedPrioBits++; ucMaxPriorityValue <<= ( uint8_t ) 0x01; } + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + #ifdef __NVIC_PRIO_BITS { /* Check the CMSIS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); } #endif @@ -352,7 +360,7 @@ BaseType_t xPortStartScheduler( void ) /* Check the FreeRTOS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); } #endif diff --git a/portable/RVDS/ARM_CM3/port.c b/portable/RVDS/ARM_CM3/port.c old mode 100644 new mode 100755 index ac4bef2957..50d6b3d1fa --- a/portable/RVDS/ARM_CM3/port.c +++ b/portable/RVDS/ARM_CM3/port.c @@ -263,7 +263,7 @@ BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority; + volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; @@ -295,20 +295,28 @@ BaseType_t xPortStartScheduler( void ) /* Calculate the maximum acceptable priority group value for the number * of bits read back. */ - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) { - ulMaxPRIGROUPValue--; + ulImplementedPrioBits++; ucMaxPriorityValue <<= ( uint8_t ) 0x01; } + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + #ifdef __NVIC_PRIO_BITS { /* Check the CMSIS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); } #endif @@ -317,7 +325,7 @@ BaseType_t xPortStartScheduler( void ) /* Check the FreeRTOS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); } #endif diff --git a/portable/RVDS/ARM_CM4F/port.c b/portable/RVDS/ARM_CM4F/port.c old mode 100644 new mode 100755 index cdc063dc9f..12f545c081 --- a/portable/RVDS/ARM_CM4F/port.c +++ b/portable/RVDS/ARM_CM4F/port.c @@ -329,7 +329,7 @@ BaseType_t xPortStartScheduler( void ) #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority; + volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; @@ -361,20 +361,28 @@ BaseType_t xPortStartScheduler( void ) /* Calculate the maximum acceptable priority group value for the number * of bits read back. */ - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) { - ulMaxPRIGROUPValue--; + ulImplementedPrioBits++; ucMaxPriorityValue <<= ( uint8_t ) 0x01; } + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + #ifdef __NVIC_PRIO_BITS { /* Check the CMSIS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); } #endif @@ -383,7 +391,7 @@ BaseType_t xPortStartScheduler( void ) /* Check the FreeRTOS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); } #endif diff --git a/portable/RVDS/ARM_CM4_MPU/port.c b/portable/RVDS/ARM_CM4_MPU/port.c old mode 100644 new mode 100755 index b9c7f90b44..f270ec8a6e --- a/portable/RVDS/ARM_CM4_MPU/port.c +++ b/portable/RVDS/ARM_CM4_MPU/port.c @@ -420,74 +420,82 @@ BaseType_t xPortStartScheduler( void ) #endif #if ( configASSERT_DEFINED == 1 ) - { - volatile uint32_t ulOriginalPriority; - volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); - 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 = *pucFirstUserPriorityRegister; + { + volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + 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 = *pucFirstUserPriorityRegister; - /* Determine the number of priority bits available. First write to all - * possible bits. */ - *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + /* Determine the number of priority bits available. First write to all + * possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; - /* Read the value back to see how many bits stuck. */ - ucMaxPriorityValue = *pucFirstUserPriorityRegister; + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; - /* Use the same mask on the maximum system call priority. */ - ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + /* 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 ); + /* 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. */ - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ - while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) - { - ulMaxPRIGROUPValue--; - ucMaxPriorityValue <<= ( uint8_t ) 0x01; - } + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } - #ifdef __NVIC_PRIO_BITS - { - /* Check the CMSIS configuration that defines the number of - * priority bits matches the number of priority bits actually queried - * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); - } - #endif - - #ifdef configPRIO_BITS - { - /* Check the FreeRTOS configuration that defines the number of - * priority bits matches the number of priority bits actually queried - * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); - } - #endif - - /* 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. */ - *pucFirstUserPriorityRegister = ulOriginalPriority; + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; } + else + { + ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + #ifdef __NVIC_PRIO_BITS + { + /* Check the CMSIS configuration that defines the number of + * priority bits matches the number of priority bits actually queried + * from the hardware. */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif + + #ifdef configPRIO_BITS + { + /* Check the FreeRTOS configuration that defines the number of + * priority bits matches the number of priority bits actually queried + * from the hardware. */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif + + /* 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. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } #endif /* configASSERT_DEFINED */ /* Make PendSV and SysTick the same priority as the kernel, and the SVC diff --git a/portable/RVDS/ARM_CM7/r0p1/port.c b/portable/RVDS/ARM_CM7/r0p1/port.c old mode 100644 new mode 100755 index 7dadb9adb3..ae04395004 --- a/portable/RVDS/ARM_CM7/r0p1/port.c +++ b/portable/RVDS/ARM_CM7/r0p1/port.c @@ -313,7 +313,7 @@ BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority; + volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; @@ -345,20 +345,28 @@ BaseType_t xPortStartScheduler( void ) /* Calculate the maximum acceptable priority group value for the number * of bits read back. */ - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) { - ulMaxPRIGROUPValue--; + ulImplementedPrioBits++; ucMaxPriorityValue <<= ( uint8_t ) 0x01; } + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + #ifdef __NVIC_PRIO_BITS { /* Check the CMSIS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); } #endif @@ -367,7 +375,7 @@ BaseType_t xPortStartScheduler( void ) /* Check the FreeRTOS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); } #endif diff --git a/portable/Tasking/ARM_CM4F/port.c b/portable/Tasking/ARM_CM4F/port.c old mode 100644 new mode 100755 index 66b0d62946..f6d161a54a --- a/portable/Tasking/ARM_CM4F/port.c +++ b/portable/Tasking/ARM_CM4F/port.c @@ -165,6 +165,85 @@ BaseType_t xPortStartScheduler( void ) * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ); + #if ( configASSERT_DEFINED == 1 ) + { + volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + 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 = *pucFirstUserPriorityRegister; + + /* Determine the number of priority bits available. First write to all + * possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; + + /* 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 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + #ifdef __NVIC_PRIO_BITS + { + /* Check the CMSIS configuration that defines the number of + * priority bits matches the number of priority bits actually queried + * from the hardware. */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif + + #ifdef configPRIO_BITS + { + /* Check the FreeRTOS configuration that defines the number of + * priority bits matches the number of priority bits actually queried + * from the hardware. */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif + + /* 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. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } + #endif /* configASSERT_DEFINED */ + /* Make PendSV and SysTick the lowest priority interrupts. */ *( portNVIC_SHPR3_REG ) |= portNVIC_PENDSV_PRI; *( portNVIC_SHPR3_REG ) |= portNVIC_SYSTICK_PRI; From 336655bda13d516c88f07b373dce2c3c395d1fa6 Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Mon, 13 Mar 2023 09:51:56 +0000 Subject: [PATCH 02/21] Fix CM3 ports --- portable/CCS/ARM_CM3/port.c | 33 ++--- portable/CCS/ARM_CM4F/port.c | 33 ++--- portable/GCC/ARM_CM3/port.c | 35 ++--- portable/GCC/ARM_CM3_MPU/port.c | 224 ++++++++++++++++---------------- portable/IAR/ARM_CM3/port.c | 19 ++- portable/RVDS/ARM_CM3/port.c | 5 +- 6 files changed, 182 insertions(+), 167 deletions(-) mode change 100755 => 100644 portable/CCS/ARM_CM3/port.c mode change 100755 => 100644 portable/CCS/ARM_CM4F/port.c mode change 100755 => 100644 portable/GCC/ARM_CM3/port.c mode change 100755 => 100644 portable/GCC/ARM_CM3_MPU/port.c mode change 100644 => 100755 portable/IAR/ARM_CM3/port.c diff --git a/portable/CCS/ARM_CM3/port.c b/portable/CCS/ARM_CM3/port.c old mode 100755 new mode 100644 index 22c3882e46..8a0cceaa23 --- a/portable/CCS/ARM_CM3/port.c +++ b/portable/CCS/ARM_CM3/port.c @@ -218,7 +218,8 @@ BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; @@ -263,7 +264,7 @@ BaseType_t xPortStartScheduler( void ) } else { - ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; } #ifdef __NVIC_PRIO_BITS @@ -387,9 +388,9 @@ void xPortSysTickHandler( void ) /* Enter a critical section but don't use the taskENTER_CRITICAL() * method as that will mask interrupts that should exit sleep mode. */ - __asm( " cpsid i"); - __asm( " dsb"); - __asm( " isb"); + __asm( " cpsid i" ); + __asm( " dsb" ); + __asm( " isb" ); /* If a context switch is pending or a task is waiting for the scheduler * to be unsuspended then abandon the low power entry. */ @@ -397,7 +398,7 @@ void xPortSysTickHandler( void ) { /* Re-enable interrupts - see comments above the cpsid instruction * above. */ - __asm( " cpsie i"); + __asm( " cpsie i" ); } else { @@ -458,9 +459,9 @@ void xPortSysTickHandler( void ) if( xModifiableIdleTime > 0 ) { - __asm( " dsb"); - __asm( " wfi"); - __asm( " isb"); + __asm( " dsb" ); + __asm( " wfi" ); + __asm( " isb" ); } configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); @@ -468,17 +469,17 @@ void xPortSysTickHandler( void ) /* Re-enable interrupts to allow the interrupt that brought the MCU * out of sleep mode to execute immediately. See comments above * the cpsid instruction above. */ - __asm( " cpsie i"); - __asm( " dsb"); - __asm( " isb"); + __asm( " cpsie i" ); + __asm( " dsb" ); + __asm( " isb" ); /* Disable interrupts again because the clock is about to be stopped * and interrupts that execute while the clock is stopped will increase * any slippage between the time maintained by the RTOS and calendar * time. */ - __asm( " cpsid i"); - __asm( " dsb"); - __asm( " isb"); + __asm( " cpsid i" ); + __asm( " dsb" ); + __asm( " isb" ); /* Disable the SysTick clock without reading the * portNVIC_SYSTICK_CTRL_REG register to ensure the @@ -586,7 +587,7 @@ void xPortSysTickHandler( void ) vTaskStepTick( ulCompleteTickPeriods ); /* Exit with interrupts enabled. */ - __asm( " cpsie i"); + __asm( " cpsie i" ); } } diff --git a/portable/CCS/ARM_CM4F/port.c b/portable/CCS/ARM_CM4F/port.c old mode 100755 new mode 100644 index 79d24f8062..3f5b0a40a4 --- a/portable/CCS/ARM_CM4F/port.c +++ b/portable/CCS/ARM_CM4F/port.c @@ -237,7 +237,8 @@ BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority, ulImplementedPrioBits = 0; + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; @@ -282,7 +283,7 @@ BaseType_t xPortStartScheduler( void ) } else { - ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; } #ifdef __NVIC_PRIO_BITS @@ -412,9 +413,9 @@ void xPortSysTickHandler( void ) /* Enter a critical section but don't use the taskENTER_CRITICAL() * method as that will mask interrupts that should exit sleep mode. */ - __asm( " cpsid i"); - __asm( " dsb"); - __asm( " isb"); + __asm( " cpsid i" ); + __asm( " dsb" ); + __asm( " isb" ); /* If a context switch is pending or a task is waiting for the scheduler * to be unsuspended then abandon the low power entry. */ @@ -422,7 +423,7 @@ void xPortSysTickHandler( void ) { /* Re-enable interrupts - see comments above the cpsid instruction * above. */ - __asm( " cpsie i"); + __asm( " cpsie i" ); } else { @@ -483,9 +484,9 @@ void xPortSysTickHandler( void ) if( xModifiableIdleTime > 0 ) { - __asm( " dsb"); - __asm( " wfi"); - __asm( " isb"); + __asm( " dsb" ); + __asm( " wfi" ); + __asm( " isb" ); } configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); @@ -493,17 +494,17 @@ void xPortSysTickHandler( void ) /* Re-enable interrupts to allow the interrupt that brought the MCU * out of sleep mode to execute immediately. See comments above * the cpsid instruction above. */ - __asm( " cpsie i"); - __asm( " dsb"); - __asm( " isb"); + __asm( " cpsie i" ); + __asm( " dsb" ); + __asm( " isb" ); /* Disable interrupts again because the clock is about to be stopped * and interrupts that execute while the clock is stopped will increase * any slippage between the time maintained by the RTOS and calendar * time. */ - __asm( " cpsid i"); - __asm( " dsb"); - __asm( " isb"); + __asm( " cpsid i" ); + __asm( " dsb" ); + __asm( " isb" ); /* Disable the SysTick clock without reading the * portNVIC_SYSTICK_CTRL_REG register to ensure the @@ -611,7 +612,7 @@ void xPortSysTickHandler( void ) vTaskStepTick( ulCompleteTickPeriods ); /* Exit with interrupts enabled. */ - __asm( " cpsie i"); + __asm( " cpsie i" ); } } diff --git a/portable/GCC/ARM_CM3/port.c b/portable/GCC/ARM_CM3/port.c old mode 100755 new mode 100644 index 250fa2c750..d1e7e67613 --- a/portable/GCC/ARM_CM3/port.c +++ b/portable/GCC/ARM_CM3/port.c @@ -219,11 +219,11 @@ static void prvTaskExitError( void ) void vPortSVCHandler( void ) { __asm volatile ( - " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ - " ldr r1, [r3] \n"/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ - " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ - " ldmia r0!, {r4-r11} \n"/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ - " msr psp, r0 \n"/* Restore the task stack pointer. */ + " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ + " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + " msr psp, r0 \n" /* Restore the task stack pointer. */ " isb \n" " mov r0, #0 \n" " msr basepri, r0 \n" @@ -239,15 +239,15 @@ void vPortSVCHandler( void ) static void prvPortStartFirstTask( void ) { __asm volatile ( - " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ " ldr r0, [r0] \n" " ldr r0, [r0] \n" - " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ - " cpsie i \n"/* Globally enable interrupts. */ + " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ + " cpsie i \n" /* Globally enable interrupts. */ " cpsie f \n" " dsb \n" " isb \n" - " svc 0 \n"/* System call to start first task. */ + " svc 0 \n" /* System call to start first task. */ " nop \n" " .ltorg \n" ); @@ -261,7 +261,8 @@ BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; @@ -306,7 +307,7 @@ BaseType_t xPortStartScheduler( void ) } else { - ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; } #ifdef __NVIC_PRIO_BITS @@ -412,11 +413,11 @@ void xPortPendSVHandler( void ) " mrs r0, psp \n" " isb \n" " \n" - " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ + " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ " ldr r2, [r3] \n" " \n" - " stmdb r0!, {r4-r11} \n"/* Save the remaining registers. */ - " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ + " stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */ + " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ " \n" " stmdb sp!, {r3, r14} \n" " mov r0, %0 \n" @@ -425,10 +426,10 @@ void xPortPendSVHandler( void ) " mov r0, #0 \n" " msr basepri, r0 \n" " ldmia sp!, {r3, r14} \n" - " \n"/* Restore the context, including the critical nesting count. */ + " \n" /* Restore the context, including the critical nesting count. */ " ldr r1, [r3] \n" - " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ - " ldmia r0!, {r4-r11} \n"/* Pop the registers. */ + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11} \n" /* Pop the registers. */ " msr psp, r0 \n" " isb \n" " bx r14 \n" diff --git a/portable/GCC/ARM_CM3_MPU/port.c b/portable/GCC/ARM_CM3_MPU/port.c old mode 100755 new mode 100644 index 6ac436f2b3..87e0cd3e11 --- a/portable/GCC/ARM_CM3_MPU/port.c +++ b/portable/GCC/ARM_CM3_MPU/port.c @@ -168,7 +168,7 @@ void vResetPrivilege( void ) __attribute__( ( naked ) ); /** * @brief Enter critical section. */ -#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) +#if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) void vPortEnterCritical( void ) FREERTOS_SYSTEM_CALL; #else void vPortEnterCritical( void ) PRIVILEGED_FUNCTION; @@ -177,7 +177,7 @@ void vResetPrivilege( void ) __attribute__( ( naked ) ); /** * @brief Exit from critical section. */ -#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) +#if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) void vPortExitCritical( void ) FREERTOS_SYSTEM_CALL; #else void vPortExitCritical( void ) PRIVILEGED_FUNCTION; @@ -307,9 +307,9 @@ static void prvSVCHandler( uint32_t * pulParam ) { __asm volatile ( - " mrs r1, control \n"/* Obtain current control value. */ - " bic r1, #1 \n"/* Set privilege bit. */ - " msr control, r1 \n"/* Write back new control value. */ + " mrs r1, control \n" /* Obtain current control value. */ + " bic r1, #1 \n" /* Set privilege bit. */ + " msr control, r1 \n" /* Write back new control value. */ ::: "r1", "memory" ); } @@ -319,9 +319,9 @@ static void prvSVCHandler( uint32_t * pulParam ) case portSVC_RAISE_PRIVILEGE: __asm volatile ( - " mrs r1, control \n"/* Obtain current control value. */ - " bic r1, #1 \n"/* Set privilege bit. */ - " msr control, r1 \n"/* Write back new control value. */ + " mrs r1, control \n" /* Obtain current control value. */ + " bic r1, #1 \n" /* Set privilege bit. */ + " msr control, r1 \n" /* Write back new control value. */ ::: "r1", "memory" ); break; @@ -337,40 +337,40 @@ static void prvRestoreContextOfFirstTask( void ) { __asm volatile ( - " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ " ldr r0, [r0] \n" " ldr r0, [r0] \n" - " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ - " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ + " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ + " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ " ldr r1, [r3] \n" - " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */ - " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */ + " ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */ + " add r1, r1, #4 \n" /* Move onto the second item in the TCB... */ " \n" - " dmb \n"/* Complete outstanding transfers before disabling MPU. */ - " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ - " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ - " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ - " str r3, [r2] \n"/* Disable MPU. */ + " dmb \n" /* Complete outstanding transfers before disabling MPU. */ + " ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */ + " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ + " bic r3, #1 \n" /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ + " str r3, [r2] \n" /* Disable MPU. */ " \n" - " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ - " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers. */ - " stmia r2!, {r4-r11} \n"/* Write 4 sets of MPU registers. */ + " ldr r2, =0xe000ed9c \n" /* Region Base Address register. */ + " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */ + " stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */ " \n" - " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ - " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ - " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ - " str r3, [r2] \n"/* Enable MPU. */ - " dsb \n"/* Force memory writes before continuing. */ + " ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */ + " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ + " orr r3, #1 \n" /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ + " str r3, [r2] \n" /* Enable MPU. */ + " dsb \n" /* Force memory writes before continuing. */ " \n" - " ldmia r0!, {r3, r4-r11} \n"/* Pop the registers that are not automatically saved on exception entry. */ + " ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */ " msr control, r3 \n" - " msr psp, r0 \n"/* Restore the task stack pointer. */ + " msr psp, r0 \n" /* Restore the task stack pointer. */ " mov r0, #0 \n" " msr basepri, r0 \n" - " ldr r14, =0xfffffffd \n"/* Load exec return code. */ + " ldr r14, =0xfffffffd \n" /* Load exec return code. */ " bx r14 \n" " \n" - " .ltorg \n"/* Assemble current literal pool to avoid offset-out-of-bound errors with lto. */ + " .ltorg \n" /* Assemble current literal pool to avoid offset-out-of-bound errors with lto. */ " .align 4 \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n" ); @@ -384,7 +384,8 @@ BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; @@ -429,7 +430,7 @@ BaseType_t xPortStartScheduler( void ) } else { - ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; } #ifdef __NVIC_PRIO_BITS @@ -479,15 +480,15 @@ BaseType_t xPortStartScheduler( void ) /* Start the first task. */ __asm volatile ( - " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ " ldr r0, [r0] \n" " ldr r0, [r0] \n" - " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ - " cpsie i \n"/* Globally enable interrupts. */ + " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ + " cpsie i \n" /* Globally enable interrupts. */ " cpsie f \n" " dsb \n" " isb \n" - " svc %0 \n"/* System call to start first task. */ + " svc %0 \n" /* System call to start first task. */ " nop \n" " .ltorg \n" ::"i" ( portSVC_START_SCHEDULER ) : "memory" ); @@ -507,53 +508,63 @@ void vPortEndScheduler( void ) void vPortEnterCritical( void ) { -#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) - if( portIS_PRIVILEGED() == pdFALSE ) - { - portRAISE_PRIVILEGE(); - portMEMORY_BARRIER(); + #if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) + if( portIS_PRIVILEGED() == pdFALSE ) + { + portRAISE_PRIVILEGE(); + portMEMORY_BARRIER(); - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; - portMEMORY_BARRIER(); + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + portMEMORY_BARRIER(); - portRESET_PRIVILEGE(); - portMEMORY_BARRIER(); - } - else - { + portRESET_PRIVILEGE(); + portMEMORY_BARRIER(); + } + else + { + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + } + #else /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ portDISABLE_INTERRUPTS(); uxCriticalNesting++; - } -#else - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; -#endif + #endif /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ } /*-----------------------------------------------------------*/ void vPortExitCritical( void ) { -#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) - if( portIS_PRIVILEGED() == pdFALSE ) - { - portRAISE_PRIVILEGE(); - portMEMORY_BARRIER(); + #if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) + if( portIS_PRIVILEGED() == pdFALSE ) + { + portRAISE_PRIVILEGE(); + portMEMORY_BARRIER(); - configASSERT( uxCriticalNesting ); - uxCriticalNesting--; + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } + + portMEMORY_BARRIER(); + + portRESET_PRIVILEGE(); + portMEMORY_BARRIER(); } - portMEMORY_BARRIER(); + else + { + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; - portRESET_PRIVILEGE(); - portMEMORY_BARRIER(); - } - else - { + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } + } + #else /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ configASSERT( uxCriticalNesting ); uxCriticalNesting--; @@ -561,16 +572,7 @@ void vPortExitCritical( void ) { portENABLE_INTERRUPTS(); } - } -#else - configASSERT( uxCriticalNesting ); - uxCriticalNesting--; - - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } -#endif + #endif /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ } /*-----------------------------------------------------------*/ @@ -582,12 +584,12 @@ void xPortPendSVHandler( void ) ( " mrs r0, psp \n" " \n" - " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ + " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ " ldr r2, [r3] \n" " \n" " mrs r1, control \n" - " stmdb r0!, {r1, r4-r11} \n"/* Save the remaining registers. */ - " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ + " stmdb r0!, {r1, r4-r11} \n" /* Save the remaining registers. */ + " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ " \n" " stmdb sp!, {r3, r14} \n" " mov r0, %0 \n" @@ -598,34 +600,34 @@ void xPortPendSVHandler( void ) " mov r0, #0 \n" " msr basepri, r0 \n" " ldmia sp!, {r3, r14} \n" - " \n"/* Restore the context. */ + " \n" /* Restore the context. */ " ldr r1, [r3] \n" - " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */ - " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */ + " ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */ + " add r1, r1, #4 \n" /* Move onto the second item in the TCB... */ " \n" - " dmb \n"/* Complete outstanding transfers before disabling MPU. */ - " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ - " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ - " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ - " str r3, [r2] \n"/* Disable MPU. */ + " dmb \n" /* Complete outstanding transfers before disabling MPU. */ + " ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */ + " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ + " bic r3, #1 \n" /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ + " str r3, [r2] \n" /* Disable MPU. */ " \n" - " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ - " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers. */ - " stmia r2!, {r4-r11} \n"/* Write 4 sets of MPU registers. */ + " ldr r2, =0xe000ed9c \n" /* Region Base Address register. */ + " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */ + " stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */ " \n" - " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ - " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ - " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ - " str r3, [r2] \n"/* Enable MPU. */ - " dsb \n"/* Force memory writes before continuing. */ + " ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */ + " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ + " orr r3, #1 \n" /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ + " str r3, [r2] \n" /* Enable MPU. */ + " dsb \n" /* Force memory writes before continuing. */ " \n" - " ldmia r0!, {r3, r4-r11} \n"/* Pop the registers that are not automatically saved on exception entry. */ + " ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */ " msr control, r3 \n" " \n" " msr psp, r0 \n" " bx r14 \n" " \n" - " .ltorg \n"/* Assemble current literal pool to avoid offset-out-of-bound errors with lto. */ + " .ltorg \n" /* Assemble current literal pool to avoid offset-out-of-bound errors with lto. */ " .align 4 \n" "pxCurrentTCBConst: .word pxCurrentTCB \n" ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) @@ -758,12 +760,12 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */ { __asm volatile ( - " mrs r0, control \n"/* r0 = CONTROL. */ - " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ + " mrs r0, control \n" /* r0 = CONTROL. */ + " tst r0, #1 \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ " ite ne \n" - " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ - " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ - " bx lr \n"/* Return. */ + " movne r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ + " moveq r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ + " bx lr \n" /* Return. */ " \n" " .align 4 \n" ::: "r0", "memory" @@ -775,10 +777,10 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */ { __asm volatile ( - " mrs r0, control \n"/* r0 = CONTROL. */ - " orr r0, #1 \n"/* r0 = r0 | 1. */ - " msr control, r0 \n"/* CONTROL = r0. */ - " bx lr \n"/* Return to the caller. */ + " mrs r0, control \n" /* r0 = CONTROL. */ + " orr r0, #1 \n" /* r0 = r0 | 1. */ + " msr control, r0 \n" /* CONTROL = r0. */ + " bx lr \n" /* Return to the caller. */ ::: "r0", "memory" ); } @@ -802,7 +804,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress = ( ( uint32_t ) __SRAM_segment_start__ ) | /* Base address. */ ( portMPU_REGION_VALID ) | - ( portSTACK_REGION ); /* Region number. */ + ( portSTACK_REGION ); /* Region number. */ xMPUSettings->xRegion[ 0 ].ulRegionAttribute = ( portMPU_REGION_READ_WRITE ) | diff --git a/portable/IAR/ARM_CM3/port.c b/portable/IAR/ARM_CM3/port.c old mode 100644 new mode 100755 index f35ee98c79..20dfdbd76d --- a/portable/IAR/ARM_CM3/port.c +++ b/portable/IAR/ARM_CM3/port.c @@ -211,7 +211,8 @@ BaseType_t xPortStartScheduler( void ) #if ( configASSERT_DEFINED == 1 ) { volatile uint32_t ulOriginalPriority; - volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API @@ -242,20 +243,28 @@ BaseType_t xPortStartScheduler( void ) /* Calculate the maximum acceptable priority group value for the number * of bits read back. */ - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) { - ulMaxPRIGROUPValue--; + ulImplementedPrioBits++; ucMaxPriorityValue <<= ( uint8_t ) 0x01; } + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + #ifdef __NVIC_PRIO_BITS { /* Check the CMSIS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); } #endif @@ -264,7 +273,7 @@ BaseType_t xPortStartScheduler( void ) /* Check the FreeRTOS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); } #endif diff --git a/portable/RVDS/ARM_CM3/port.c b/portable/RVDS/ARM_CM3/port.c index 50d6b3d1fa..19dcbe6d2b 100755 --- a/portable/RVDS/ARM_CM3/port.c +++ b/portable/RVDS/ARM_CM3/port.c @@ -263,7 +263,8 @@ BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; @@ -308,7 +309,7 @@ BaseType_t xPortStartScheduler( void ) } else { - ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; } #ifdef __NVIC_PRIO_BITS From 9a0ef2efffc1ff37f4fbf2808ef7318ca7964e07 Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Mon, 13 Mar 2023 10:10:10 +0000 Subject: [PATCH 03/21] Fix ARM_CM3_MPU --- portable/GCC/ARM_CM3_MPU/port.c | 357 ++++++++++++++++---------------- 1 file changed, 178 insertions(+), 179 deletions(-) mode change 100644 => 100755 portable/GCC/ARM_CM3_MPU/port.c diff --git a/portable/GCC/ARM_CM3_MPU/port.c b/portable/GCC/ARM_CM3_MPU/port.c old mode 100644 new mode 100755 index 87e0cd3e11..be7aa9f62f --- a/portable/GCC/ARM_CM3_MPU/port.c +++ b/portable/GCC/ARM_CM3_MPU/port.c @@ -168,7 +168,7 @@ void vResetPrivilege( void ) __attribute__( ( naked ) ); /** * @brief Enter critical section. */ -#if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) +#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) void vPortEnterCritical( void ) FREERTOS_SYSTEM_CALL; #else void vPortEnterCritical( void ) PRIVILEGED_FUNCTION; @@ -177,7 +177,7 @@ void vResetPrivilege( void ) __attribute__( ( naked ) ); /** * @brief Exit from critical section. */ -#if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) +#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) void vPortExitCritical( void ) FREERTOS_SYSTEM_CALL; #else void vPortExitCritical( void ) PRIVILEGED_FUNCTION; @@ -307,9 +307,9 @@ static void prvSVCHandler( uint32_t * pulParam ) { __asm volatile ( - " mrs r1, control \n" /* Obtain current control value. */ - " bic r1, #1 \n" /* Set privilege bit. */ - " msr control, r1 \n" /* Write back new control value. */ + " mrs r1, control \n"/* Obtain current control value. */ + " bic r1, #1 \n"/* Set privilege bit. */ + " msr control, r1 \n"/* Write back new control value. */ ::: "r1", "memory" ); } @@ -319,9 +319,9 @@ static void prvSVCHandler( uint32_t * pulParam ) case portSVC_RAISE_PRIVILEGE: __asm volatile ( - " mrs r1, control \n" /* Obtain current control value. */ - " bic r1, #1 \n" /* Set privilege bit. */ - " msr control, r1 \n" /* Write back new control value. */ + " mrs r1, control \n"/* Obtain current control value. */ + " bic r1, #1 \n"/* Set privilege bit. */ + " msr control, r1 \n"/* Write back new control value. */ ::: "r1", "memory" ); break; @@ -337,40 +337,40 @@ static void prvRestoreContextOfFirstTask( void ) { __asm volatile ( - " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ + " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, [r0] \n" " ldr r0, [r0] \n" - " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ - " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ + " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ + " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ " ldr r1, [r3] \n" - " ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */ - " add r1, r1, #4 \n" /* Move onto the second item in the TCB... */ + " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */ + " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */ " \n" - " dmb \n" /* Complete outstanding transfers before disabling MPU. */ - " ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */ - " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ - " bic r3, #1 \n" /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ - " str r3, [r2] \n" /* Disable MPU. */ + " dmb \n"/* Complete outstanding transfers before disabling MPU. */ + " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ + " str r3, [r2] \n"/* Disable MPU. */ " \n" - " ldr r2, =0xe000ed9c \n" /* Region Base Address register. */ - " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */ - " stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */ + " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers. */ + " stmia r2!, {r4-r11} \n"/* Write 4 sets of MPU registers. */ " \n" - " ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */ - " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ - " orr r3, #1 \n" /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ - " str r3, [r2] \n" /* Enable MPU. */ - " dsb \n" /* Force memory writes before continuing. */ + " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ + " str r3, [r2] \n"/* Enable MPU. */ + " dsb \n"/* Force memory writes before continuing. */ " \n" - " ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */ + " ldmia r0!, {r3, r4-r11} \n"/* Pop the registers that are not automatically saved on exception entry. */ " msr control, r3 \n" - " msr psp, r0 \n" /* Restore the task stack pointer. */ + " msr psp, r0 \n"/* Restore the task stack pointer. */ " mov r0, #0 \n" " msr basepri, r0 \n" - " ldr r14, =0xfffffffd \n" /* Load exec return code. */ + " ldr r14, =0xfffffffd \n"/* Load exec return code. */ " bx r14 \n" " \n" - " .ltorg \n" /* Assemble current literal pool to avoid offset-out-of-bound errors with lto. */ + " .ltorg \n"/* Assemble current literal pool to avoid offset-out-of-bound errors with lto. */ " .align 4 \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n" ); @@ -383,83 +383,83 @@ static void prvRestoreContextOfFirstTask( void ) BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) - { - volatile uint32_t ulOriginalPriority; - volatile uint32_t ulImplementedPrioBits = 0; - volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); - 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 = *pucFirstUserPriorityRegister; + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + 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 = *pucFirstUserPriorityRegister; - /* Determine the number of priority bits available. First write to all - * possible bits. */ - *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + /* Determine the number of priority bits available. First write to all + * possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; - /* Read the value back to see how many bits stuck. */ - ucMaxPriorityValue = *pucFirstUserPriorityRegister; + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; - /* Use the same mask on the maximum system call priority. */ - ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + /* 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 ); + /* 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. */ + /* 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 ) - { - ulMaxPRIGROUPValue = 0; - } - else - { - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; - } + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } - #ifdef __NVIC_PRIO_BITS - { - /* Check the CMSIS configuration that defines the number of - * priority bits matches the number of priority bits actually queried - * from the hardware. */ - configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); - } - #endif + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } - #ifdef configPRIO_BITS - { - /* Check the FreeRTOS configuration that defines the number of - * priority bits matches the number of priority bits actually queried - * from the hardware. */ - configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + #ifdef __NVIC_PRIO_BITS + { + /* Check the CMSIS configuration that defines the number of + * priority bits matches the number of priority bits actually queried + * from the hardware. */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif + + #ifdef configPRIO_BITS + { + /* Check the FreeRTOS configuration that defines the number of + * priority bits matches the number of priority bits actually queried + * from the hardware. */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif + + /* 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. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; } - #endif - - /* 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. */ - *pucFirstUserPriorityRegister = ulOriginalPriority; - } #endif /* configASSERT_DEFINED */ /* Make PendSV and SysTick the same priority as the kernel, and the SVC @@ -480,15 +480,15 @@ BaseType_t xPortStartScheduler( void ) /* Start the first task. */ __asm volatile ( - " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ + " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, [r0] \n" " ldr r0, [r0] \n" - " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ - " cpsie i \n" /* Globally enable interrupts. */ + " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ + " cpsie i \n"/* Globally enable interrupts. */ " cpsie f \n" " dsb \n" " isb \n" - " svc %0 \n" /* System call to start first task. */ + " svc %0 \n"/* System call to start first task. */ " nop \n" " .ltorg \n" ::"i" ( portSVC_START_SCHEDULER ) : "memory" ); @@ -508,63 +508,53 @@ void vPortEndScheduler( void ) void vPortEnterCritical( void ) { - #if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) - if( portIS_PRIVILEGED() == pdFALSE ) - { - portRAISE_PRIVILEGE(); - portMEMORY_BARRIER(); +#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) + if( portIS_PRIVILEGED() == pdFALSE ) + { + portRAISE_PRIVILEGE(); + portMEMORY_BARRIER(); - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; - portMEMORY_BARRIER(); + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + portMEMORY_BARRIER(); - portRESET_PRIVILEGE(); - portMEMORY_BARRIER(); - } - else - { - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; - } - #else /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ + portRESET_PRIVILEGE(); + portMEMORY_BARRIER(); + } + else + { portDISABLE_INTERRUPTS(); uxCriticalNesting++; - #endif /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ + } +#else + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; +#endif } /*-----------------------------------------------------------*/ void vPortExitCritical( void ) { - #if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) - if( portIS_PRIVILEGED() == pdFALSE ) - { - portRAISE_PRIVILEGE(); - portMEMORY_BARRIER(); - - configASSERT( uxCriticalNesting ); - uxCriticalNesting--; - - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } +#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) + if( portIS_PRIVILEGED() == pdFALSE ) + { + portRAISE_PRIVILEGE(); + portMEMORY_BARRIER(); - portMEMORY_BARRIER(); + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; - portRESET_PRIVILEGE(); - portMEMORY_BARRIER(); - } - else + if( uxCriticalNesting == 0 ) { - configASSERT( uxCriticalNesting ); - uxCriticalNesting--; - - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } + portENABLE_INTERRUPTS(); } - #else /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ + portMEMORY_BARRIER(); + + portRESET_PRIVILEGE(); + portMEMORY_BARRIER(); + } + else + { configASSERT( uxCriticalNesting ); uxCriticalNesting--; @@ -572,7 +562,16 @@ void vPortExitCritical( void ) { portENABLE_INTERRUPTS(); } - #endif /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ + } +#else + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } +#endif } /*-----------------------------------------------------------*/ @@ -584,12 +583,12 @@ void xPortPendSVHandler( void ) ( " mrs r0, psp \n" " \n" - " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ + " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ " ldr r2, [r3] \n" " \n" " mrs r1, control \n" - " stmdb r0!, {r1, r4-r11} \n" /* Save the remaining registers. */ - " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ + " stmdb r0!, {r1, r4-r11} \n"/* Save the remaining registers. */ + " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ " \n" " stmdb sp!, {r3, r14} \n" " mov r0, %0 \n" @@ -600,34 +599,34 @@ void xPortPendSVHandler( void ) " mov r0, #0 \n" " msr basepri, r0 \n" " ldmia sp!, {r3, r14} \n" - " \n" /* Restore the context. */ + " \n"/* Restore the context. */ " ldr r1, [r3] \n" - " ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */ - " add r1, r1, #4 \n" /* Move onto the second item in the TCB... */ + " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */ + " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */ " \n" - " dmb \n" /* Complete outstanding transfers before disabling MPU. */ - " ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */ - " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ - " bic r3, #1 \n" /* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ - " str r3, [r2] \n" /* Disable MPU. */ + " dmb \n"/* Complete outstanding transfers before disabling MPU. */ + " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ + " str r3, [r2] \n"/* Disable MPU. */ " \n" - " ldr r2, =0xe000ed9c \n" /* Region Base Address register. */ - " ldmia r1!, {r4-r11} \n" /* Read 4 sets of MPU registers. */ - " stmia r2!, {r4-r11} \n" /* Write 4 sets of MPU registers. */ + " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers. */ + " stmia r2!, {r4-r11} \n"/* Write 4 sets of MPU registers. */ " \n" - " ldr r2, =0xe000ed94 \n" /* MPU_CTRL register. */ - " ldr r3, [r2] \n" /* Read the value of MPU_CTRL. */ - " orr r3, #1 \n" /* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ - " str r3, [r2] \n" /* Enable MPU. */ - " dsb \n" /* Force memory writes before continuing. */ + " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ + " str r3, [r2] \n"/* Enable MPU. */ + " dsb \n"/* Force memory writes before continuing. */ " \n" - " ldmia r0!, {r3, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry. */ + " ldmia r0!, {r3, r4-r11} \n"/* Pop the registers that are not automatically saved on exception entry. */ " msr control, r3 \n" " \n" " msr psp, r0 \n" " bx r14 \n" " \n" - " .ltorg \n" /* Assemble current literal pool to avoid offset-out-of-bound errors with lto. */ + " .ltorg \n"/* Assemble current literal pool to avoid offset-out-of-bound errors with lto. */ " .align 4 \n" "pxCurrentTCBConst: .word pxCurrentTCB \n" ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) @@ -760,12 +759,12 @@ BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */ { __asm volatile ( - " mrs r0, control \n" /* r0 = CONTROL. */ - " tst r0, #1 \n" /* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ + " mrs r0, control \n"/* r0 = CONTROL. */ + " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ " ite ne \n" - " movne r0, #0 \n" /* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ - " moveq r0, #1 \n" /* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ - " bx lr \n" /* Return. */ + " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ + " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ + " bx lr \n"/* Return. */ " \n" " .align 4 \n" ::: "r0", "memory" @@ -777,10 +776,10 @@ void vResetPrivilege( void ) /* __attribute__ (( naked )) */ { __asm volatile ( - " mrs r0, control \n" /* r0 = CONTROL. */ - " orr r0, #1 \n" /* r0 = r0 | 1. */ - " msr control, r0 \n" /* CONTROL = r0. */ - " bx lr \n" /* Return to the caller. */ + " mrs r0, control \n"/* r0 = CONTROL. */ + " orr r0, #1 \n"/* r0 = r0 | 1. */ + " msr control, r0 \n"/* CONTROL = r0. */ + " bx lr \n"/* Return to the caller. */ ::: "r0", "memory" ); } @@ -804,7 +803,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress = ( ( uint32_t ) __SRAM_segment_start__ ) | /* Base address. */ ( portMPU_REGION_VALID ) | - ( portSTACK_REGION ); /* Region number. */ + ( portSTACK_REGION ); /* Region number. */ xMPUSettings->xRegion[ 0 ].ulRegionAttribute = ( portMPU_REGION_READ_WRITE ) | @@ -933,4 +932,4 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, } #endif /* configASSERT_DEFINED */ -/*-----------------------------------------------------------*/ +/*-----------------------------------------------------------*/ \ No newline at end of file From d1c714e3ac17c9fd41ceceb26a9d904d481b2406 Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Mon, 13 Mar 2023 10:47:04 +0000 Subject: [PATCH 04/21] Fix ARM CM3 --- portable/GCC/ARM_CM3/port.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) mode change 100644 => 100755 portable/GCC/ARM_CM3/port.c diff --git a/portable/GCC/ARM_CM3/port.c b/portable/GCC/ARM_CM3/port.c old mode 100644 new mode 100755 index d1e7e67613..4fc608888f --- a/portable/GCC/ARM_CM3/port.c +++ b/portable/GCC/ARM_CM3/port.c @@ -219,11 +219,11 @@ static void prvTaskExitError( void ) void vPortSVCHandler( void ) { __asm volatile ( - " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ - " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ - " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ - " ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ - " msr psp, r0 \n" /* Restore the task stack pointer. */ + " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ + " ldr r1, [r3] \n"/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11} \n"/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + " msr psp, r0 \n"/* Restore the task stack pointer. */ " isb \n" " mov r0, #0 \n" " msr basepri, r0 \n" @@ -239,15 +239,15 @@ void vPortSVCHandler( void ) static void prvPortStartFirstTask( void ) { __asm volatile ( - " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ + " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ " ldr r0, [r0] \n" " ldr r0, [r0] \n" - " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ - " cpsie i \n" /* Globally enable interrupts. */ + " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ + " cpsie i \n"/* Globally enable interrupts. */ " cpsie f \n" " dsb \n" " isb \n" - " svc 0 \n" /* System call to start first task. */ + " svc 0 \n"/* System call to start first task. */ " nop \n" " .ltorg \n" ); @@ -263,7 +263,7 @@ BaseType_t xPortStartScheduler( void ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; - volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API @@ -413,11 +413,11 @@ void xPortPendSVHandler( void ) " mrs r0, psp \n" " isb \n" " \n" - " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ + " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ " ldr r2, [r3] \n" " \n" - " stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */ - " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ + " stmdb r0!, {r4-r11} \n"/* Save the remaining registers. */ + " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ " \n" " stmdb sp!, {r3, r14} \n" " mov r0, %0 \n" @@ -426,10 +426,10 @@ void xPortPendSVHandler( void ) " mov r0, #0 \n" " msr basepri, r0 \n" " ldmia sp!, {r3, r14} \n" - " \n" /* Restore the context, including the critical nesting count. */ + " \n"/* Restore the context, including the critical nesting count. */ " ldr r1, [r3] \n" - " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ - " ldmia r0!, {r4-r11} \n" /* Pop the registers. */ + " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11} \n"/* Pop the registers. */ " msr psp, r0 \n" " isb \n" " bx r14 \n" @@ -765,4 +765,4 @@ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* configASSERT_DEFINED */ +#endif /* configASSERT_DEFINED */ \ No newline at end of file From cd9c113b55f6623d5cef1b24e6ec711b7dd009aa Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Mon, 13 Mar 2023 11:16:14 +0000 Subject: [PATCH 05/21] Fix ARM_CM4_MPU --- portable/GCC/ARM_CM4_MPU/port.c | 1102 +++++++++++++------------------ 1 file changed, 449 insertions(+), 653 deletions(-) diff --git a/portable/GCC/ARM_CM4_MPU/port.c b/portable/GCC/ARM_CM4_MPU/port.c index 36c9775005..9a7322c635 100755 --- a/portable/GCC/ARM_CM4_MPU/port.c +++ b/portable/GCC/ARM_CM4_MPU/port.c @@ -27,14 +27,9 @@ */ /*----------------------------------------------------------- -* Implementation of functions defined in portable.h for the ARM CM4 MPU port. +* Implementation of functions defined in portable.h for the ARM CM4F port. *----------------------------------------------------------*/ -/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining - * all the API functions to use the MPU wrappers. That should only be done when - * task.h is included from an application file. */ -#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE - /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" @@ -43,99 +38,83 @@ #error This port can only be used when the project options are configured to enable hardware floating point support. #endif -#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE - -#ifndef configSYSTICK_CLOCK_HZ - #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ - /* Ensure the SysTick is clocked at the same frequency as the core. */ - #define portNVIC_SYSTICK_CLK ( 1UL << 2UL ) -#else - -/* The way the SysTick is clocked is not modified in case it is not the same - * as the core. */ - #define portNVIC_SYSTICK_CLK ( 0 ) -#endif - -#ifndef configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS - #warning "configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS is not defined. We recommend defining it to 0 in FreeRTOSConfig.h for better security." - #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 1 -#endif +/* Constants required to manipulate the core. Registers first... */ +#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) +/* ...then bits in the registers. */ +#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) +#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) +#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) +#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) +#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) +#define portNVIC_PEND_SYSTICK_SET_BIT ( 1UL << 26UL ) +#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) + +/* Constants used to detect a Cortex-M7 r0p1 core, which should use the ARM_CM7 + * r0p1 port. */ +#define portCPUID ( *( ( volatile uint32_t * ) 0xE000ed00 ) ) +#define portCORTEX_M7_r0p1_ID ( 0x410FC271UL ) +#define portCORTEX_M7_r0p0_ID ( 0x410FC270UL ) + +#define portMIN_INTERRUPT_PRIORITY ( 255UL ) +#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) +#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) -/* Constants required to access and manipulate the NVIC. */ -#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) -#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) -#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) -#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) -#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xe000ed1c ) ) -#define portNVIC_SYS_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) ) -#define portNVIC_MEM_FAULT_ENABLE ( 1UL << 16UL ) - -/* Constants used to detect Cortex-M7 r0p0 and r0p1 cores, and ensure - * that a work around is active for errata 837070. */ -#define portCPUID ( *( ( volatile uint32_t * ) 0xE000ed00 ) ) -#define portCORTEX_M7_r0p1_ID ( 0x410FC271UL ) -#define portCORTEX_M7_r0p0_ID ( 0x410FC270UL ) - -/* Constants required to access and manipulate the MPU. */ -#define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) ) -#define portMPU_REGION_BASE_ADDRESS_REG ( *( ( volatile uint32_t * ) 0xe000ed9C ) ) -#define portMPU_REGION_ATTRIBUTE_REG ( *( ( volatile uint32_t * ) 0xe000edA0 ) ) -#define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) ) -#define portEXPECTED_MPU_TYPE_VALUE ( configTOTAL_MPU_REGIONS << 8UL ) -#define portMPU_ENABLE ( 0x01UL ) -#define portMPU_BACKGROUND_ENABLE ( 1UL << 2UL ) -#define portPRIVILEGED_EXECUTION_START_ADDRESS ( 0UL ) -#define portMPU_REGION_VALID ( 0x10UL ) -#define portMPU_REGION_ENABLE ( 0x01UL ) -#define portPERIPHERALS_START_ADDRESS 0x40000000UL -#define portPERIPHERALS_END_ADDRESS 0x5FFFFFFFUL - -/* Constants required to access and manipulate the SysTick. */ -#define portNVIC_SYSTICK_INT ( 0x00000002UL ) -#define portNVIC_SYSTICK_ENABLE ( 0x00000001UL ) -#define portMIN_INTERRUPT_PRIORITY ( 255UL ) -#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) -#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) -#define portNVIC_SVC_PRI ( ( ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL ) << 24UL ) +/* Constants required to check the validity of an interrupt priority. */ +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) +#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 ) + +/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ +#define portVECTACTIVE_MASK ( 0xFFUL ) /* Constants required to manipulate the VFP. */ -#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34UL ) /* Floating point context control register. */ -#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL ) +#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */ +#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL ) /* Constants required to set up the initial stack. */ -#define portINITIAL_XPSR ( 0x01000000UL ) -#define portINITIAL_EXC_RETURN ( 0xfffffffdUL ) -#define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 ) -#define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 ) +#define portINITIAL_XPSR ( 0x01000000 ) +#define portINITIAL_EXC_RETURN ( 0xfffffffd ) -/* Constants required to check the validity of an interrupt priority. */ -#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) -#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) -#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) -#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) -#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 ) - -/* Offsets in the stack to the parameters when inside the SVC handler. */ -#define portOFFSET_TO_PC ( 6 ) +/* The systick is a 24-bit counter. */ +#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) /* For strict compliance with the Cortex-M spec the task start address should * have bit-0 clear, as it is loaded into the PC on exit from an ISR. */ -#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL ) +#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL ) -/* - * Configure a number of standard MPU regions that are used by all tasks. - */ -static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; +/* A fiddle factor to estimate the number of SysTick counts that would have + * occurred while the SysTick counter is stopped during tickless idle + * calculations. */ +#define portMISSED_COUNTS_FACTOR ( 94UL ) -/* - * Return the smallest MPU region size that a given number of bytes will fit - * into. The region size is returned as the value that should be programmed - * into the region attribute register for that region. - */ -static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) PRIVILEGED_FUNCTION; +/* Let the user override the default SysTick clock rate. If defined by the + * user, this symbol must equal the SysTick clock rate when the CLK bit is 0 in the + * configuration register. */ +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ ( configCPU_CLOCK_HZ ) + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT_CONFIG ( portNVIC_SYSTICK_CLK_BIT ) +#else + /* Select the option to clock SysTick not at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK_BIT_CONFIG ( 0 ) +#endif + +/* Let the user override the pre-loading of the initial LR with the address of + * prvTaskExitError() in case it messes up unwinding of the stack in the + * debugger. */ +#ifdef configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS +#else + #define portTASK_RETURN_ADDRESS prvTaskExitError +#endif /* * Setup the timer to generate the tick interrupts. The implementation in this @@ -145,68 +124,55 @@ static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) PRIVI void vPortSetupTimerInterrupt( void ); /* - * Standard FreeRTOS exception handlers. + * Exception handlers. */ -void xPortPendSVHandler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; -void xPortSysTickHandler( void ) PRIVILEGED_FUNCTION; -void vPortSVCHandler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; +void xPortPendSVHandler( void ) __attribute__( ( naked ) ); +void xPortSysTickHandler( void ); +void vPortSVCHandler( void ) __attribute__( ( naked ) ); /* - * Starts the scheduler by restoring the context of the first task to run. + * Start first task is a separate function so it can be tested in isolation. */ -static void prvRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; - -/* - * C portion of the SVC handler. The SVC handler is split between an asm entry - * and a C wrapper for simplicity of coding and maintenance. - */ -static void prvSVCHandler( uint32_t * pulRegisters ) __attribute__( ( noinline ) ) PRIVILEGED_FUNCTION; +static void prvPortStartFirstTask( void ) __attribute__( ( naked ) ); /* * Function to enable the VFP. */ static void vPortEnableVFP( void ) __attribute__( ( naked ) ); -/** - * @brief Checks whether or not the processor is privileged. - * - * @return 1 if the processor is already privileged, 0 otherwise. +/* + * Used to catch tasks that attempt to return from their implementing function. */ -BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) ); +static void prvTaskExitError( void ); -/** - * @brief Lowers the privilege level by setting the bit 0 of the CONTROL - * register. - * - * Bit 0 of the CONTROL register defines the privilege level of Thread Mode. - * Bit[0] = 0 --> The processor is running privileged - * Bit[0] = 1 --> The processor is running unprivileged. - */ -void vResetPrivilege( void ) __attribute__( ( naked ) ); +/*-----------------------------------------------------------*/ -/** - * @brief Enter critical section. +/* Each task maintains its own interrupt status in the critical nesting + * variable. */ +static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; + +/* + * The number of SysTick increments that make up one tick period. */ -#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) - void vPortEnterCritical( void ) FREERTOS_SYSTEM_CALL; -#else - void vPortEnterCritical( void ) PRIVILEGED_FUNCTION; -#endif +#if ( configUSE_TICKLESS_IDLE == 1 ) + static uint32_t ulTimerCountsForOneTick = 0; +#endif /* configUSE_TICKLESS_IDLE */ -/** - * @brief Exit from critical section. +/* + * The maximum number of tick periods that can be suppressed is limited by the + * 24 bit resolution of the SysTick timer. */ -#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) - void vPortExitCritical( void ) FREERTOS_SYSTEM_CALL; -#else - void vPortExitCritical( void ) PRIVILEGED_FUNCTION; -#endif -/*-----------------------------------------------------------*/ +#if ( configUSE_TICKLESS_IDLE == 1 ) + static uint32_t xMaximumPossibleSuppressedTicks = 0; +#endif /* configUSE_TICKLESS_IDLE */ -/* Each task maintains its own interrupt status in the critical nesting - * variable. Note this is not saved as part of the task context as context - * switches can only occur when uxCriticalNesting is zero. */ -static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; +/* + * Compensate for the CPU cycles that pass while the SysTick is stopped (low + * power functionality only. + */ +#if ( configUSE_TICKLESS_IDLE == 1 ) + static uint32_t ulStoppedTimerCompensation = 0; +#endif /* configUSE_TICKLESS_IDLE */ /* * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure @@ -226,185 +192,102 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; */ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, - void * pvParameters, - BaseType_t xRunPrivileged ) + void * pvParameters ) { /* Simulate the stack frame as it would be created by a context switch * interrupt. */ - pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ + + /* Offset added to account for the way the MCU uses the stack on entry/exit + * of interrupts, and to ensure alignment. */ + pxTopOfStack--; + *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ pxTopOfStack--; *pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */ pxTopOfStack--; - *pxTopOfStack = 0; /* LR */ - pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ - *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ + + /* Save code space by skipping register initialisation. */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ /* A save method is being used that requires each task to maintain its * own exec return value. */ pxTopOfStack--; *pxTopOfStack = portINITIAL_EXC_RETURN; - pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ - - if( xRunPrivileged == pdTRUE ) - { - *pxTopOfStack = portINITIAL_CONTROL_IF_PRIVILEGED; - } - else - { - *pxTopOfStack = portINITIAL_CONTROL_IF_UNPRIVILEGED; - } + pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ return pxTopOfStack; } /*-----------------------------------------------------------*/ -void vPortSVCHandler( void ) +static void prvTaskExitError( void ) { - /* Assumes psp was in use. */ - __asm volatile - ( - #ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */ - " tst lr, #4 \n" - " ite eq \n" - " mrseq r0, msp \n" - " mrsne r0, psp \n" - #else - " mrs r0, psp \n" - #endif - " b %0 \n" - ::"i" ( prvSVCHandler ) : "r0", "memory" - ); -} -/*-----------------------------------------------------------*/ + volatile uint32_t ulDummy = 0; + + /* A function that implements a task must not exit or attempt to return to + * its caller as there is nothing to return to. If a task wants to exit it + * should instead call vTaskDelete( NULL ). + * + * Artificially force an assert() to be triggered if configASSERT() is + * defined, then stop here so application writers can catch the error. */ + configASSERT( uxCriticalNesting == ~0UL ); + portDISABLE_INTERRUPTS(); -static void prvSVCHandler( uint32_t * pulParam ) -{ - uint8_t ucSVCNumber; - uint32_t ulPC; - - #if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) - #if defined( __ARMCC_VERSION ) - - /* Declaration when these variable are defined in code instead of being - * exported from linker scripts. */ - extern uint32_t * __syscalls_flash_start__; - extern uint32_t * __syscalls_flash_end__; - #else - /* Declaration when these variable are exported from linker scripts. */ - extern uint32_t __syscalls_flash_start__[]; - extern uint32_t __syscalls_flash_end__[]; - #endif /* #if defined( __ARMCC_VERSION ) */ - #endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */ - - /* The stack contains: r0, r1, r2, r3, r12, LR, PC and xPSR. The first - * argument (r0) is pulParam[ 0 ]. */ - ulPC = pulParam[ portOFFSET_TO_PC ]; - ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ]; - - switch( ucSVCNumber ) + while( ulDummy == 0 ) { - case portSVC_START_SCHEDULER: - portNVIC_SHPR2_REG |= portNVIC_SVC_PRI; - prvRestoreContextOfFirstTask(); - break; - - case portSVC_YIELD: - portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; - - /* Barriers are normally not required - * but do ensure the code is completely - * within the specified behaviour for the - * architecture. */ - __asm volatile ( "dsb" ::: "memory" ); - __asm volatile ( "isb" ); - - break; - - #if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) - case portSVC_RAISE_PRIVILEGE: /* Only raise the privilege, if the - * svc was raised from any of the - * system calls. */ - - if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) && - ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) ) - { - __asm volatile - ( - " mrs r1, control \n"/* Obtain current control value. */ - " bic r1, #1 \n"/* Set privilege bit. */ - " msr control, r1 \n"/* Write back new control value. */ - ::: "r1", "memory" - ); - } - - break; - #else /* if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */ - case portSVC_RAISE_PRIVILEGE: - __asm volatile - ( - " mrs r1, control \n"/* Obtain current control value. */ - " bic r1, #1 \n"/* Set privilege bit. */ - " msr control, r1 \n"/* Write back new control value. */ - ::: "r1", "memory" - ); - break; - #endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */ - - default: /* Unknown SVC call. */ - break; + /* This file calls prvTaskExitError() after the scheduler has been + * started to remove a compiler warning about the function being defined + * but never called. ulDummy is used purely to quieten other warnings + * about code appearing after this function is called - making ulDummy + * volatile makes the compiler think the function could return and + * therefore not output an 'unreachable code' warning for code that appears + * after it. */ } } /*-----------------------------------------------------------*/ -static void prvRestoreContextOfFirstTask( void ) +void vPortSVCHandler( void ) { - __asm volatile - ( - " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ - " ldr r0, [r0] \n" - " ldr r0, [r0] \n" - " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ + __asm volatile ( " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ - " ldr r1, [r3] \n" - " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */ - " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */ - " \n" - " dmb \n"/* Complete outstanding transfers before disabling MPU. */ - " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ - " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ - " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ - " str r3, [r2] \n"/* Disable MPU. */ - " \n" - " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ - " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */ - " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */ - " \n" - #if ( configTOTAL_MPU_REGIONS == 16 ) - " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */ - " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */ - " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */ - " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */ - #endif /* configTOTAL_MPU_REGIONS == 16. */ - " \n" - " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ - " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ - " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ - " str r3, [r2] \n"/* Enable MPU. */ - " dsb \n"/* Force memory writes before continuing. */ - " \n" - " ldmia r0!, {r3-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry. */ - " msr control, r3 \n" + " ldr r1, [r3] \n"/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ " msr psp, r0 \n"/* Restore the task stack pointer. */ + " isb \n" " mov r0, #0 \n" " msr basepri, r0 \n" " bx r14 \n" " \n" - " .ltorg \n"/* Assemble current literal pool to avoid offset-out-of-bound errors with lto. */ " .align 4 \n" - "pxCurrentTCBConst2: .word pxCurrentTCB \n" - ); + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + ); +} +/*-----------------------------------------------------------*/ + +static void prvPortStartFirstTask( void ) +{ + /* Start the first task. This also clears the bit that indicates the FPU is + * in use in case the FPU was used before the scheduler was started - which + * would otherwise result in the unnecessary leaving of space in the SVC stack + * for lazy saving of FPU registers. */ + __asm volatile ( + " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ + " mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */ + " msr control, r0 \n" + " cpsie i \n"/* Globally enable interrupts. */ + " cpsie f \n" + " dsb \n" + " isb \n" + " svc 0 \n"/* System call to start first task. */ + " nop \n" + " .ltorg \n" + ); } /*-----------------------------------------------------------*/ @@ -413,22 +296,17 @@ static void prvRestoreContextOfFirstTask( void ) */ BaseType_t xPortStartScheduler( void ) { - /* Errata 837070 workaround must only be enabled on Cortex-M7 r0p0 - * and r0p1 cores. */ - #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) - configASSERT( ( portCPUID == portCORTEX_M7_r0p1_ID ) || ( portCPUID == portCORTEX_M7_r0p0_ID ) ); - #else - /* When using this port on a Cortex-M7 r0p0 or r0p1 core, define - * configENABLE_ERRATA_837070_WORKAROUND to 1 in your - * FreeRTOSConfig.h. */ - configASSERT( portCPUID != portCORTEX_M7_r0p1_ID ); - configASSERT( portCPUID != portCORTEX_M7_r0p0_ID ); - #endif + /* This port can be used on all revisions of the Cortex-M7 core other than + * the r0p1 parts. r0p1 parts should use the port from the + * /source/portable/GCC/ARM_CM7/r0p1 directory. */ + configASSERT( portCPUID != portCORTEX_M7_r0p1_ID ); + configASSERT( portCPUID != portCORTEX_M7_r0p0_ID ); #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; - volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API @@ -472,7 +350,7 @@ BaseType_t xPortStartScheduler( void ) } else { - ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; } #ifdef __NVIC_PRIO_BITS @@ -504,15 +382,10 @@ BaseType_t xPortStartScheduler( void ) } #endif /* configASSERT_DEFINED */ - /* Make PendSV and SysTick the same priority as the kernel, and the SVC - * handler higher priority so it can be used to exit a critical section (where - * lower priorities are masked). */ + /* Make PendSV and SysTick the lowest priority interrupts. */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; - /* Configure the regions in the MPU that are common to all tasks. */ - prvSetupMPU(); - /* Start the timer that generates the tick ISR. Interrupts are disabled * here already. */ vPortSetupTimerInterrupt(); @@ -526,25 +399,17 @@ BaseType_t xPortStartScheduler( void ) /* Lazy save always. */ *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; - /* Start the first task. This also clears the bit that indicates the FPU is - * in use in case the FPU was used before the scheduler was started - which - * would otherwise result in the unnecessary leaving of space in the SVC stack - * for lazy saving of FPU registers. */ - __asm volatile ( - " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ - " ldr r0, [r0] \n" - " ldr r0, [r0] \n" - " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ - " mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */ - " msr control, r0 \n" - " cpsie i \n"/* Globally enable interrupts. */ - " cpsie f \n" - " dsb \n" - " isb \n" - " svc %0 \n"/* System call to start first task. */ - " nop \n" - " .ltorg \n" - ::"i" ( portSVC_START_SCHEDULER ) : "memory" ); + /* Start the first task. */ + prvPortStartFirstTask(); + + /* Should never get here as the tasks will now be executing! Call the task + * exit error function to prevent compiler warnings about a static function + * not being called in the case that the application writer overrides this + * functionality by defining configTASK_RETURN_ADDRESS. Call + * vTaskSwitchContext() so link time optimisation does not remove the + * symbol. */ + vTaskSwitchContext(); + prvTaskExitError(); /* Should not get here! */ return 0; @@ -561,62 +426,23 @@ void vPortEndScheduler( void ) void vPortEnterCritical( void ) { -#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) - if( portIS_PRIVILEGED() == pdFALSE ) - { - portRAISE_PRIVILEGE(); - portMEMORY_BARRIER(); - - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; - portMEMORY_BARRIER(); + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; - portRESET_PRIVILEGE(); - portMEMORY_BARRIER(); - } - else + /* This is not the interrupt safe version of the enter critical function so + * assert() if it is being called from an interrupt context. Only API + * functions that end in "FromISR" can be used in an interrupt. Only assert if + * the critical nesting count is 1 to protect against recursive calls if the + * assert function also uses a critical section. */ + if( uxCriticalNesting == 1 ) { - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; + configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); } -#else - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; -#endif } /*-----------------------------------------------------------*/ void vPortExitCritical( void ) { -#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) - if( portIS_PRIVILEGED() == pdFALSE ) - { - portRAISE_PRIVILEGE(); - portMEMORY_BARRIER(); - - configASSERT( uxCriticalNesting ); - uxCriticalNesting--; - - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } - portMEMORY_BARRIER(); - - portRESET_PRIVILEGE(); - portMEMORY_BARRIER(); - } - else - { - configASSERT( uxCriticalNesting ); - uxCriticalNesting--; - - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } - } -#else configASSERT( uxCriticalNesting ); uxCriticalNesting--; @@ -624,7 +450,6 @@ void vPortExitCritical( void ) { portENABLE_INTERRUPTS(); } -#endif } /*-----------------------------------------------------------*/ @@ -644,64 +469,40 @@ void xPortPendSVHandler( void ) " it eq \n" " vstmdbeq r0!, {s16-s31} \n" " \n" - " mrs r1, control \n" - " stmdb r0!, {r1, r4-r11, r14} \n"/* Save the remaining registers. */ + " stmdb r0!, {r4-r11, r14} \n"/* Save the core registers. */ " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ " \n" " stmdb sp!, {r0, r3} \n" " mov r0, %0 \n" - #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) - " cpsid i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ - #endif " msr basepri, r0 \n" " dsb \n" " isb \n" - #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) - " cpsie i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ - #endif " bl vTaskSwitchContext \n" " mov r0, #0 \n" " msr basepri, r0 \n" " ldmia sp!, {r0, r3} \n" - " \n"/* Restore the context. */ - " ldr r1, [r3] \n" - " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */ - " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */ - " \n" - " dmb \n"/* Complete outstanding transfers before disabling MPU. */ - " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ - " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ - " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ - " str r3, [r2] \n"/* Disable MPU. */ - " \n" - " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ - " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */ - " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */ " \n" - #if ( configTOTAL_MPU_REGIONS == 16 ) - " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */ - " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */ - " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */ - " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */ - #endif /* configTOTAL_MPU_REGIONS == 16. */ + " ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */ + " ldr r0, [r1] \n" " \n" - " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ - " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ - " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ - " str r3, [r2] \n"/* Enable MPU. */ - " dsb \n"/* Force memory writes before continuing. */ - " \n" - " ldmia r0!, {r3-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry. */ - " msr control, r3 \n" + " ldmia r0!, {r4-r11, r14} \n"/* Pop the core registers. */ " \n" " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, pop the high vfp registers too. */ " it eq \n" " vldmiaeq r0!, {s16-s31} \n" " \n" " msr psp, r0 \n" + " isb \n" + " \n" + #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */ + #if WORKAROUND_PMU_CM001 == 1 + " push { r14 } \n" + " pop { pc } \n" + #endif + #endif + " \n" " bx r14 \n" " \n" - " .ltorg \n"/* Assemble the current literal pool to avoid offset-out-of-bound errors with lto. */ " .align 4 \n" "pxCurrentTCBConst: .word pxCurrentTCB \n" ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) @@ -711,34 +512,267 @@ void xPortPendSVHandler( void ) void xPortSysTickHandler( void ) { - uint32_t ulDummy; - - ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); + /* The SysTick runs at the lowest interrupt priority, so when this interrupt + * executes all interrupts must be unmasked. There is therefore no need to + * save and then restore the interrupt mask value as its value is already + * known. */ + portDISABLE_INTERRUPTS(); { /* Increment the RTOS tick. */ if( xTaskIncrementTick() != pdFALSE ) { - /* Pend a context switch. */ + /* A context switch is required. Context switching is performed in + * the PendSV interrupt. Pend the PendSV interrupt. */ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } } - portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); + portENABLE_INTERRUPTS(); } /*-----------------------------------------------------------*/ +#if ( configUSE_TICKLESS_IDLE == 1 ) + + __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) + { + uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; + TickType_t xModifiableIdleTime; + + /* Make sure the SysTick reload value does not overflow the counter. */ + if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) + { + xExpectedIdleTime = xMaximumPossibleSuppressedTicks; + } + + /* Enter a critical section but don't use the taskENTER_CRITICAL() + * method as that will mask interrupts that should exit sleep mode. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); + + /* If a context switch is pending or a task is waiting for the scheduler + * to be unsuspended then abandon the low power entry. */ + if( eTaskConfirmSleepModeStatus() == eAbortSleep ) + { + /* Re-enable interrupts - see comments above the cpsid instruction + * above. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + else + { + /* Stop the SysTick momentarily. The time the SysTick is stopped for + * is accounted for as best it can be, but using the tickless mode will + * inevitably result in some tiny drift of the time maintained by the + * kernel with respect to calendar time. */ + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT ); + + /* Use the SysTick current-value register to determine the number of + * SysTick decrements remaining until the next tick interrupt. If the + * current-value register is zero, then there are actually + * ulTimerCountsForOneTick decrements remaining, not zero, because the + * SysTick requests the interrupt when decrementing from 1 to 0. */ + ulSysTickDecrementsLeft = portNVIC_SYSTICK_CURRENT_VALUE_REG; + + if( ulSysTickDecrementsLeft == 0 ) + { + ulSysTickDecrementsLeft = ulTimerCountsForOneTick; + } + + /* Calculate the reload value required to wait xExpectedIdleTime + * tick periods. -1 is used because this code normally executes part + * way through the first tick period. But if the SysTick IRQ is now + * pending, then clear the IRQ, suppressing the first tick, and correct + * the reload value to reflect that the second tick period is already + * underway. The expected idle time is always at least two ticks. */ + ulReloadValue = ulSysTickDecrementsLeft + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); + + if( ( portNVIC_INT_CTRL_REG & portNVIC_PEND_SYSTICK_SET_BIT ) != 0 ) + { + portNVIC_INT_CTRL_REG = portNVIC_PEND_SYSTICK_CLEAR_BIT; + ulReloadValue -= ulTimerCountsForOneTick; + } + + if( ulReloadValue > ulStoppedTimerCompensation ) + { + ulReloadValue -= ulStoppedTimerCompensation; + } + + /* Set the new reload value. */ + portNVIC_SYSTICK_LOAD_REG = ulReloadValue; + + /* Clear the SysTick count flag and set the count value back to + * zero. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + + /* Restart SysTick. */ + portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; + + /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can + * set its parameter to 0 to indicate that its implementation contains + * its own wait for interrupt or wait for event instruction, and so wfi + * should not be executed again. However, the original expected idle + * time variable must remain unmodified, so a copy is taken. */ + xModifiableIdleTime = xExpectedIdleTime; + configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); + + if( xModifiableIdleTime > 0 ) + { + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "wfi" ); + __asm volatile ( "isb" ); + } + + configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); + + /* Re-enable interrupts to allow the interrupt that brought the MCU + * out of sleep mode to execute immediately. See comments above + * the cpsid instruction above. */ + __asm volatile ( "cpsie i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); + + /* Disable interrupts again because the clock is about to be stopped + * and interrupts that execute while the clock is stopped will increase + * any slippage between the time maintained by the RTOS and calendar + * time. */ + __asm volatile ( "cpsid i" ::: "memory" ); + __asm volatile ( "dsb" ); + __asm volatile ( "isb" ); + + /* Disable the SysTick clock without reading the + * portNVIC_SYSTICK_CTRL_REG register to ensure the + * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, + * the time the SysTick is stopped for is accounted for as best it can + * be, but using the tickless mode will inevitably result in some tiny + * drift of the time maintained by the kernel with respect to calendar + * time*/ + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT ); + + /* Determine whether the SysTick has already counted to zero. */ + if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + uint32_t ulCalculatedLoadValue; + + /* The tick interrupt ended the sleep (or is now pending), and + * a new tick period has started. Reset portNVIC_SYSTICK_LOAD_REG + * with whatever remains of the new tick period. */ + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); + + /* Don't allow a tiny value, or values that have somehow + * underflowed because the post sleep hook did something + * that took too long or because the SysTick current-value register + * is zero. */ + if( ( ulCalculatedLoadValue <= ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) + { + ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); + } + + portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; + + /* As the pending tick will be processed as soon as this + * function exits, the tick value maintained by the tick is stepped + * forward by one less than the time spent waiting. */ + ulCompleteTickPeriods = xExpectedIdleTime - 1UL; + } + else + { + /* Something other than the tick interrupt ended the sleep. */ + + /* Use the SysTick current-value register to determine the + * number of SysTick decrements remaining until the expected idle + * time would have ended. */ + ulSysTickDecrementsLeft = portNVIC_SYSTICK_CURRENT_VALUE_REG; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG != portNVIC_SYSTICK_CLK_BIT ) + { + /* If the SysTick is not using the core clock, the current- + * value register might still be zero here. In that case, the + * SysTick didn't load from the reload register, and there are + * ulReloadValue decrements remaining in the expected idle + * time, not zero. */ + if( ulSysTickDecrementsLeft == 0 ) + { + ulSysTickDecrementsLeft = ulReloadValue; + } + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + /* Work out how long the sleep lasted rounded to complete tick + * periods (not the ulReload value which accounted for part + * ticks). */ + ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - ulSysTickDecrementsLeft; + + /* How many complete tick periods passed while the processor + * was waiting? */ + ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; + + /* The reload value is set to whatever fraction of a single tick + * period remains. */ + portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; + } + + /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, + * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If + * the SysTick is not using the core clock, temporarily configure it to + * use the core clock. This configuration forces the SysTick to load + * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next + * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready + * to receive the standard value immediately. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) + { + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + } + #else + { + /* The temporary usage of the core clock has served its purpose, + * as described above. Resume usage of the other clock. */ + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; + + if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) + { + /* The partial tick period already ended. Be sure the SysTick + * counts it only once. */ + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; + } + + portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; + portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; + } + #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ + + /* Step the tick to account for any tick periods that elapsed. */ + vTaskStepTick( ulCompleteTickPeriods ); + + /* Exit with interrupts enabled. */ + __asm volatile ( "cpsie i" ::: "memory" ); + } + } + +#endif /* #if configUSE_TICKLESS_IDLE */ +/*-----------------------------------------------------------*/ + /* * Setup the systick timer to generate the tick interrupts at the required * frequency. */ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) { + /* Calculate the constants required to configure the tick interrupt. */ + #if ( configUSE_TICKLESS_IDLE == 1 ) + { + ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); + xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; + ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); + } + #endif /* configUSE_TICKLESS_IDLE */ + /* Stop and clear the SysTick. */ portNVIC_SYSTICK_CTRL_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Configure SysTick to interrupt at the requested rate. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE ); + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); } /*-----------------------------------------------------------*/ @@ -758,243 +792,6 @@ static void vPortEnableVFP( void ) } /*-----------------------------------------------------------*/ -static void prvSetupMPU( void ) -{ - #if defined( __ARMCC_VERSION ) - - /* Declaration when these variable are defined in code instead of being - * exported from linker scripts. */ - extern uint32_t * __privileged_functions_start__; - extern uint32_t * __privileged_functions_end__; - extern uint32_t * __FLASH_segment_start__; - extern uint32_t * __FLASH_segment_end__; - extern uint32_t * __privileged_data_start__; - extern uint32_t * __privileged_data_end__; - #else - /* Declaration when these variable are exported from linker scripts. */ - extern uint32_t __privileged_functions_start__[]; - extern uint32_t __privileged_functions_end__[]; - extern uint32_t __FLASH_segment_start__[]; - extern uint32_t __FLASH_segment_end__[]; - extern uint32_t __privileged_data_start__[]; - extern uint32_t __privileged_data_end__[]; - #endif /* if defined( __ARMCC_VERSION ) */ - - /* The only permitted number of regions are 8 or 16. */ - configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) ); - - /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */ - configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE ); - - /* Check the expected MPU is present. */ - if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE ) - { - /* First setup the unprivileged flash for unprivileged read only access. */ - portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */ - ( portMPU_REGION_VALID ) | - ( portUNPRIVILEGED_FLASH_REGION ); - - portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_ONLY ) | - ( ( configTEX_S_C_B_FLASH & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) | - ( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) | - ( portMPU_REGION_ENABLE ); - - /* Setup the privileged flash for privileged only access. This is where - * the kernel code is placed. */ - portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_functions_start__ ) | /* Base address. */ - ( portMPU_REGION_VALID ) | - ( portPRIVILEGED_FLASH_REGION ); - - portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) | - ( ( configTEX_S_C_B_FLASH & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) | - ( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__ ) ) | - ( portMPU_REGION_ENABLE ); - - /* Setup the privileged data RAM region. This is where the kernel data - * is placed. */ - portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */ - ( portMPU_REGION_VALID ) | - ( portPRIVILEGED_RAM_REGION ); - - portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | - ( portMPU_REGION_EXECUTE_NEVER ) | - ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) | - prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) | - ( portMPU_REGION_ENABLE ); - - /* By default allow everything to access the general peripherals. The - * system peripherals and registers are protected. */ - portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) | - ( portMPU_REGION_VALID ) | - ( portGENERAL_PERIPHERALS_REGION ); - - portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_WRITE | portMPU_REGION_EXECUTE_NEVER ) | - ( prvGetMPURegionSizeSetting( portPERIPHERALS_END_ADDRESS - portPERIPHERALS_START_ADDRESS ) ) | - ( portMPU_REGION_ENABLE ); - - /* Enable the memory fault exception. */ - portNVIC_SYS_CTRL_STATE_REG |= portNVIC_MEM_FAULT_ENABLE; - - /* Enable the MPU with the background region configured. */ - portMPU_CTRL_REG |= ( portMPU_ENABLE | portMPU_BACKGROUND_ENABLE ); - } -} -/*-----------------------------------------------------------*/ - -static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) -{ - uint32_t ulRegionSize, ulReturnValue = 4; - - /* 32 is the smallest region size, 31 is the largest valid value for - * ulReturnValue. */ - for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) ) - { - if( ulActualSizeInBytes <= ulRegionSize ) - { - break; - } - else - { - ulReturnValue++; - } - } - - /* Shift the code by one before returning so it can be written directly - * into the the correct bit position of the attribute register. */ - return( ulReturnValue << 1UL ); -} -/*-----------------------------------------------------------*/ - -BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */ -{ - __asm volatile - ( - " mrs r0, control \n"/* r0 = CONTROL. */ - " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ - " ite ne \n" - " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ - " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ - " bx lr \n"/* Return. */ - " \n" - " .align 4 \n" - ::: "r0", "memory" - ); -} -/*-----------------------------------------------------------*/ - -void vResetPrivilege( void ) /* __attribute__ (( naked )) */ -{ - __asm volatile - ( - " mrs r0, control \n"/* r0 = CONTROL. */ - " orr r0, #1 \n"/* r0 = r0 | 1. */ - " msr control, r0 \n"/* CONTROL = r0. */ - " bx lr \n"/* Return to the caller. */ - ::: "r0", "memory" - ); -} -/*-----------------------------------------------------------*/ - -void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, - const struct xMEMORY_REGION * const xRegions, - StackType_t * pxBottomOfStack, - uint32_t ulStackDepth ) -{ - #if defined( __ARMCC_VERSION ) - - /* Declaration when these variable are defined in code instead of being - * exported from linker scripts. */ - extern uint32_t * __SRAM_segment_start__; - extern uint32_t * __SRAM_segment_end__; - extern uint32_t * __privileged_data_start__; - extern uint32_t * __privileged_data_end__; - #else - /* Declaration when these variable are exported from linker scripts. */ - extern uint32_t __SRAM_segment_start__[]; - extern uint32_t __SRAM_segment_end__[]; - extern uint32_t __privileged_data_start__[]; - extern uint32_t __privileged_data_end__[]; - #endif /* if defined( __ARMCC_VERSION ) */ - - int32_t lIndex; - uint32_t ul; - - if( xRegions == NULL ) - { - /* No MPU regions are specified so allow access to all RAM. */ - xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress = - ( ( uint32_t ) __SRAM_segment_start__ ) | /* Base address. */ - ( portMPU_REGION_VALID ) | - ( portSTACK_REGION ); /* Region number. */ - - xMPUSettings->xRegion[ 0 ].ulRegionAttribute = - ( portMPU_REGION_READ_WRITE ) | - ( portMPU_REGION_EXECUTE_NEVER ) | - ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) | - ( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) | - ( portMPU_REGION_ENABLE ); - - /* Invalidate user configurable regions. */ - for( ul = 1UL; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ ) - { - xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( ( ul - 1UL ) | portMPU_REGION_VALID ); - xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL; - } - } - else - { - /* This function is called automatically when the task is created - in - * which case the stack region parameters will be valid. At all other - * times the stack parameters will not be valid and it is assumed that the - * stack region has already been configured. */ - if( ulStackDepth > 0 ) - { - /* Define the region that allows access to the stack. */ - xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress = - ( ( uint32_t ) pxBottomOfStack ) | - ( portMPU_REGION_VALID ) | - ( portSTACK_REGION ); /* Region number. */ - - xMPUSettings->xRegion[ 0 ].ulRegionAttribute = - ( portMPU_REGION_READ_WRITE ) | - ( portMPU_REGION_EXECUTE_NEVER ) | - ( prvGetMPURegionSizeSetting( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) | - ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) | - ( portMPU_REGION_ENABLE ); - } - - lIndex = 0; - - for( ul = 1UL; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ ) - { - if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL ) - { - /* Translate the generic region definition contained in - * xRegions into the CM4 specific MPU settings that are then - * stored in xMPUSettings. */ - xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = - ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) | - ( portMPU_REGION_VALID ) | - ( ul - 1UL ); /* Region number. */ - - xMPUSettings->xRegion[ ul ].ulRegionAttribute = - ( prvGetMPURegionSizeSetting( xRegions[ lIndex ].ulLengthInBytes ) ) | - ( xRegions[ lIndex ].ulParameters ) | - ( portMPU_REGION_ENABLE ); - } - else - { - /* Invalidate the region. */ - xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( ( ul - 1UL ) | portMPU_REGION_VALID ); - xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL; - } - - lIndex++; - } - } -} -/*-----------------------------------------------------------*/ - #if ( configASSERT_DEFINED == 1 ) void vPortValidateInterruptPriority( void ) @@ -1023,10 +820,10 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, * 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, + * 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. + * 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. @@ -1049,9 +846,8 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, * 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 unpredicable behaviour. */ + * of zero will result in unpredictable behaviour. */ configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* configASSERT_DEFINED */ -/*-----------------------------------------------------------*/ +#endif /* configASSERT_DEFINED */ \ No newline at end of file From d05b46a3a9fb7dceac8453119deab7e7b0809564 Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Mon, 13 Mar 2023 12:08:38 +0000 Subject: [PATCH 06/21] Fix ARM_CM4 --- portable/GCC/ARM_CM4F/port.c | 16 +- portable/GCC/ARM_CM4_MPU/port.c | 1227 ++++++++++++++++++------------- 2 files changed, 720 insertions(+), 523 deletions(-) diff --git a/portable/GCC/ARM_CM4F/port.c b/portable/GCC/ARM_CM4F/port.c index 9db50a7334..93febf1ed2 100755 --- a/portable/GCC/ARM_CM4F/port.c +++ b/portable/GCC/ARM_CM4F/port.c @@ -304,8 +304,9 @@ BaseType_t xPortStartScheduler( void ) #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; - volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API @@ -343,15 +344,6 @@ BaseType_t xPortStartScheduler( void ) ucMaxPriorityValue <<= ( uint8_t ) 0x01; } - if( ulImplementedPrioBits == 8 ) - { - ulMaxPRIGROUPValue = 0; - } - else - { - ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; - } - #ifdef __NVIC_PRIO_BITS { /* Check the CMSIS configuration that defines the number of @@ -849,4 +841,4 @@ static void vPortEnableVFP( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* configASSERT_DEFINED */ +#endif /* configASSERT_DEFINED */ \ No newline at end of file diff --git a/portable/GCC/ARM_CM4_MPU/port.c b/portable/GCC/ARM_CM4_MPU/port.c index 9a7322c635..bf252cf51e 100755 --- a/portable/GCC/ARM_CM4_MPU/port.c +++ b/portable/GCC/ARM_CM4_MPU/port.c @@ -27,9 +27,14 @@ */ /*----------------------------------------------------------- -* Implementation of functions defined in portable.h for the ARM CM4F port. +* Implementation of functions defined in portable.h for the ARM CM4 MPU port. *----------------------------------------------------------*/ +/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining + * all the API functions to use the MPU wrappers. That should only be done when + * task.h is included from an application file. */ +#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE + /* Scheduler includes. */ #include "FreeRTOS.h" #include "task.h" @@ -38,83 +43,99 @@ #error This port can only be used when the project options are configured to enable hardware floating point support. #endif -/* Constants required to manipulate the core. Registers first... */ -#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) -#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) -#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) -#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) -/* ...then bits in the registers. */ -#define portNVIC_SYSTICK_CLK_BIT ( 1UL << 2UL ) -#define portNVIC_SYSTICK_INT_BIT ( 1UL << 1UL ) -#define portNVIC_SYSTICK_ENABLE_BIT ( 1UL << 0UL ) -#define portNVIC_SYSTICK_COUNT_FLAG_BIT ( 1UL << 16UL ) -#define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) -#define portNVIC_PEND_SYSTICK_SET_BIT ( 1UL << 26UL ) -#define portNVIC_PEND_SYSTICK_CLEAR_BIT ( 1UL << 25UL ) - -/* Constants used to detect a Cortex-M7 r0p1 core, which should use the ARM_CM7 - * r0p1 port. */ -#define portCPUID ( *( ( volatile uint32_t * ) 0xE000ed00 ) ) -#define portCORTEX_M7_r0p1_ID ( 0x410FC271UL ) -#define portCORTEX_M7_r0p0_ID ( 0x410FC270UL ) - -#define portMIN_INTERRUPT_PRIORITY ( 255UL ) -#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) -#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) +#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE -/* Constants required to check the validity of an interrupt priority. */ -#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) -#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) -#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) -#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) -#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 ) - -/* Masks off all bits but the VECTACTIVE bits in the ICSR register. */ -#define portVECTACTIVE_MASK ( 0xFFUL ) +#ifndef configSYSTICK_CLOCK_HZ + #define configSYSTICK_CLOCK_HZ configCPU_CLOCK_HZ + /* Ensure the SysTick is clocked at the same frequency as the core. */ + #define portNVIC_SYSTICK_CLK ( 1UL << 2UL ) +#else + +/* The way the SysTick is clocked is not modified in case it is not the same + * as the core. */ + #define portNVIC_SYSTICK_CLK ( 0 ) +#endif + +#ifndef configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS + #warning "configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS is not defined. We recommend defining it to 0 in FreeRTOSConfig.h for better security." + #define configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS 1 +#endif + +/* Constants required to access and manipulate the NVIC. */ +#define portNVIC_SYSTICK_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000e010 ) ) +#define portNVIC_SYSTICK_LOAD_REG ( *( ( volatile uint32_t * ) 0xe000e014 ) ) +#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( *( ( volatile uint32_t * ) 0xe000e018 ) ) +#define portNVIC_SHPR3_REG ( *( ( volatile uint32_t * ) 0xe000ed20 ) ) +#define portNVIC_SHPR2_REG ( *( ( volatile uint32_t * ) 0xe000ed1c ) ) +#define portNVIC_SYS_CTRL_STATE_REG ( *( ( volatile uint32_t * ) 0xe000ed24 ) ) +#define portNVIC_MEM_FAULT_ENABLE ( 1UL << 16UL ) + +/* Constants used to detect Cortex-M7 r0p0 and r0p1 cores, and ensure + * that a work around is active for errata 837070. */ +#define portCPUID ( *( ( volatile uint32_t * ) 0xE000ed00 ) ) +#define portCORTEX_M7_r0p1_ID ( 0x410FC271UL ) +#define portCORTEX_M7_r0p0_ID ( 0x410FC270UL ) + +/* Constants required to access and manipulate the MPU. */ +#define portMPU_TYPE_REG ( *( ( volatile uint32_t * ) 0xe000ed90 ) ) +#define portMPU_REGION_BASE_ADDRESS_REG ( *( ( volatile uint32_t * ) 0xe000ed9C ) ) +#define portMPU_REGION_ATTRIBUTE_REG ( *( ( volatile uint32_t * ) 0xe000edA0 ) ) +#define portMPU_CTRL_REG ( *( ( volatile uint32_t * ) 0xe000ed94 ) ) +#define portEXPECTED_MPU_TYPE_VALUE ( configTOTAL_MPU_REGIONS << 8UL ) +#define portMPU_ENABLE ( 0x01UL ) +#define portMPU_BACKGROUND_ENABLE ( 1UL << 2UL ) +#define portPRIVILEGED_EXECUTION_START_ADDRESS ( 0UL ) +#define portMPU_REGION_VALID ( 0x10UL ) +#define portMPU_REGION_ENABLE ( 0x01UL ) +#define portPERIPHERALS_START_ADDRESS 0x40000000UL +#define portPERIPHERALS_END_ADDRESS 0x5FFFFFFFUL + +/* Constants required to access and manipulate the SysTick. */ +#define portNVIC_SYSTICK_INT ( 0x00000002UL ) +#define portNVIC_SYSTICK_ENABLE ( 0x00000001UL ) +#define portMIN_INTERRUPT_PRIORITY ( 255UL ) +#define portNVIC_PENDSV_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 16UL ) +#define portNVIC_SYSTICK_PRI ( ( ( uint32_t ) portMIN_INTERRUPT_PRIORITY ) << 24UL ) +#define portNVIC_SVC_PRI ( ( ( uint32_t ) configMAX_SYSCALL_INTERRUPT_PRIORITY - 1UL ) << 24UL ) /* Constants required to manipulate the VFP. */ -#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34 ) /* Floating point context control register. */ -#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL ) +#define portFPCCR ( ( volatile uint32_t * ) 0xe000ef34UL ) /* Floating point context control register. */ +#define portASPEN_AND_LSPEN_BITS ( 0x3UL << 30UL ) /* Constants required to set up the initial stack. */ -#define portINITIAL_XPSR ( 0x01000000 ) -#define portINITIAL_EXC_RETURN ( 0xfffffffd ) +#define portINITIAL_XPSR ( 0x01000000UL ) +#define portINITIAL_EXC_RETURN ( 0xfffffffdUL ) +#define portINITIAL_CONTROL_IF_UNPRIVILEGED ( 0x03 ) +#define portINITIAL_CONTROL_IF_PRIVILEGED ( 0x02 ) -/* The systick is a 24-bit counter. */ -#define portMAX_24_BIT_NUMBER ( 0xffffffUL ) +/* Constants required to check the validity of an interrupt priority. */ +#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) +#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) +#define portAIRCR_REG ( *( ( volatile uint32_t * ) 0xE000ED0C ) ) +#define portMAX_8_BIT_VALUE ( ( uint8_t ) 0xff ) +#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 ) + +/* Offsets in the stack to the parameters when inside the SVC handler. */ +#define portOFFSET_TO_PC ( 6 ) /* For strict compliance with the Cortex-M spec the task start address should * have bit-0 clear, as it is loaded into the PC on exit from an ISR. */ -#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL ) - -/* A fiddle factor to estimate the number of SysTick counts that would have - * occurred while the SysTick counter is stopped during tickless idle - * calculations. */ -#define portMISSED_COUNTS_FACTOR ( 94UL ) +#define portSTART_ADDRESS_MASK ( ( StackType_t ) 0xfffffffeUL ) -/* Let the user override the default SysTick clock rate. If defined by the - * user, this symbol must equal the SysTick clock rate when the CLK bit is 0 in the - * configuration register. */ -#ifndef configSYSTICK_CLOCK_HZ - #define configSYSTICK_CLOCK_HZ ( configCPU_CLOCK_HZ ) - /* Ensure the SysTick is clocked at the same frequency as the core. */ - #define portNVIC_SYSTICK_CLK_BIT_CONFIG ( portNVIC_SYSTICK_CLK_BIT ) -#else - /* Select the option to clock SysTick not at the same frequency as the core. */ - #define portNVIC_SYSTICK_CLK_BIT_CONFIG ( 0 ) -#endif +/* + * Configure a number of standard MPU regions that are used by all tasks. + */ +static void prvSetupMPU( void ) PRIVILEGED_FUNCTION; -/* Let the user override the pre-loading of the initial LR with the address of - * prvTaskExitError() in case it messes up unwinding of the stack in the - * debugger. */ -#ifdef configTASK_RETURN_ADDRESS - #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS -#else - #define portTASK_RETURN_ADDRESS prvTaskExitError -#endif +/* + * Return the smallest MPU region size that a given number of bytes will fit + * into. The region size is returned as the value that should be programmed + * into the region attribute register for that region. + */ +static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) PRIVILEGED_FUNCTION; /* * Setup the timer to generate the tick interrupts. The implementation in this @@ -124,55 +145,68 @@ void vPortSetupTimerInterrupt( void ); /* - * Exception handlers. + * Standard FreeRTOS exception handlers. */ -void xPortPendSVHandler( void ) __attribute__( ( naked ) ); -void xPortSysTickHandler( void ); -void vPortSVCHandler( void ) __attribute__( ( naked ) ); +void xPortPendSVHandler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; +void xPortSysTickHandler( void ) PRIVILEGED_FUNCTION; +void vPortSVCHandler( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /* - * Start first task is a separate function so it can be tested in isolation. + * Starts the scheduler by restoring the context of the first task to run. */ -static void prvPortStartFirstTask( void ) __attribute__( ( naked ) ); +static void prvRestoreContextOfFirstTask( void ) __attribute__( ( naked ) ) PRIVILEGED_FUNCTION; /* - * Function to enable the VFP. + * C portion of the SVC handler. The SVC handler is split between an asm entry + * and a C wrapper for simplicity of coding and maintenance. */ -static void vPortEnableVFP( void ) __attribute__( ( naked ) ); +static void prvSVCHandler( uint32_t * pulRegisters ) __attribute__( ( noinline ) ) PRIVILEGED_FUNCTION; /* - * Used to catch tasks that attempt to return from their implementing function. + * Function to enable the VFP. */ -static void prvTaskExitError( void ); - -/*-----------------------------------------------------------*/ +static void vPortEnableVFP( void ) __attribute__( ( naked ) ); -/* Each task maintains its own interrupt status in the critical nesting - * variable. */ -static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; +/** + * @brief Checks whether or not the processor is privileged. + * + * @return 1 if the processor is already privileged, 0 otherwise. + */ +BaseType_t xIsPrivileged( void ) __attribute__( ( naked ) ); -/* - * The number of SysTick increments that make up one tick period. +/** + * @brief Lowers the privilege level by setting the bit 0 of the CONTROL + * register. + * + * Bit 0 of the CONTROL register defines the privilege level of Thread Mode. + * Bit[0] = 0 --> The processor is running privileged + * Bit[0] = 1 --> The processor is running unprivileged. */ -#if ( configUSE_TICKLESS_IDLE == 1 ) - static uint32_t ulTimerCountsForOneTick = 0; -#endif /* configUSE_TICKLESS_IDLE */ +void vResetPrivilege( void ) __attribute__( ( naked ) ); -/* - * The maximum number of tick periods that can be suppressed is limited by the - * 24 bit resolution of the SysTick timer. +/** + * @brief Enter critical section. */ -#if ( configUSE_TICKLESS_IDLE == 1 ) - static uint32_t xMaximumPossibleSuppressedTicks = 0; -#endif /* configUSE_TICKLESS_IDLE */ +#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) + void vPortEnterCritical( void ) FREERTOS_SYSTEM_CALL; +#else + void vPortEnterCritical( void ) PRIVILEGED_FUNCTION; +#endif -/* - * Compensate for the CPU cycles that pass while the SysTick is stopped (low - * power functionality only. +/** + * @brief Exit from critical section. */ -#if ( configUSE_TICKLESS_IDLE == 1 ) - static uint32_t ulStoppedTimerCompensation = 0; -#endif /* configUSE_TICKLESS_IDLE */ +#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) + void vPortExitCritical( void ) FREERTOS_SYSTEM_CALL; +#else + void vPortExitCritical( void ) PRIVILEGED_FUNCTION; +#endif +/*-----------------------------------------------------------*/ + +/* Each task maintains its own interrupt status in the critical nesting + * variable. Note this is not saved as part of the task context as context + * switches can only occur when uxCriticalNesting is zero. */ +static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; /* * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure @@ -192,102 +226,185 @@ static UBaseType_t uxCriticalNesting = 0xaaaaaaaa; */ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, TaskFunction_t pxCode, - void * pvParameters ) + void * pvParameters, + BaseType_t xRunPrivileged ) { /* Simulate the stack frame as it would be created by a context switch * interrupt. */ - - /* Offset added to account for the way the MCU uses the stack on entry/exit - * of interrupts, and to ensure alignment. */ - pxTopOfStack--; - + pxTopOfStack--; /* Offset added to account for the way the MCU uses the stack on entry/exit of interrupts. */ *pxTopOfStack = portINITIAL_XPSR; /* xPSR */ pxTopOfStack--; *pxTopOfStack = ( ( StackType_t ) pxCode ) & portSTART_ADDRESS_MASK; /* PC */ pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* LR */ - - /* Save code space by skipping register initialisation. */ - pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ - *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ + *pxTopOfStack = 0; /* LR */ + pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ + *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ /* A save method is being used that requires each task to maintain its * own exec return value. */ pxTopOfStack--; *pxTopOfStack = portINITIAL_EXC_RETURN; - pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ + + if( xRunPrivileged == pdTRUE ) + { + *pxTopOfStack = portINITIAL_CONTROL_IF_PRIVILEGED; + } + else + { + *pxTopOfStack = portINITIAL_CONTROL_IF_UNPRIVILEGED; + } return pxTopOfStack; } /*-----------------------------------------------------------*/ -static void prvTaskExitError( void ) +void vPortSVCHandler( void ) { - volatile uint32_t ulDummy = 0; - - /* A function that implements a task must not exit or attempt to return to - * its caller as there is nothing to return to. If a task wants to exit it - * should instead call vTaskDelete( NULL ). - * - * Artificially force an assert() to be triggered if configASSERT() is - * defined, then stop here so application writers can catch the error. */ - configASSERT( uxCriticalNesting == ~0UL ); - portDISABLE_INTERRUPTS(); + /* Assumes psp was in use. */ + __asm volatile + ( + #ifndef USE_PROCESS_STACK /* Code should not be required if a main() is using the process stack. */ + " tst lr, #4 \n" + " ite eq \n" + " mrseq r0, msp \n" + " mrsne r0, psp \n" + #else + " mrs r0, psp \n" + #endif + " b %0 \n" + ::"i" ( prvSVCHandler ) : "r0", "memory" + ); +} +/*-----------------------------------------------------------*/ - while( ulDummy == 0 ) +static void prvSVCHandler( uint32_t * pulParam ) +{ + uint8_t ucSVCNumber; + uint32_t ulPC; + + #if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) + #if defined( __ARMCC_VERSION ) + + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __syscalls_flash_start__; + extern uint32_t * __syscalls_flash_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __syscalls_flash_start__[]; + extern uint32_t __syscalls_flash_end__[]; + #endif /* #if defined( __ARMCC_VERSION ) */ + #endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */ + + /* The stack contains: r0, r1, r2, r3, r12, LR, PC and xPSR. The first + * argument (r0) is pulParam[ 0 ]. */ + ulPC = pulParam[ portOFFSET_TO_PC ]; + ucSVCNumber = ( ( uint8_t * ) ulPC )[ -2 ]; + + switch( ucSVCNumber ) { - /* This file calls prvTaskExitError() after the scheduler has been - * started to remove a compiler warning about the function being defined - * but never called. ulDummy is used purely to quieten other warnings - * about code appearing after this function is called - making ulDummy - * volatile makes the compiler think the function could return and - * therefore not output an 'unreachable code' warning for code that appears - * after it. */ + case portSVC_START_SCHEDULER: + portNVIC_SHPR2_REG |= portNVIC_SVC_PRI; + prvRestoreContextOfFirstTask(); + break; + + case portSVC_YIELD: + portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; + + /* Barriers are normally not required + * but do ensure the code is completely + * within the specified behaviour for the + * architecture. */ + __asm volatile ( "dsb" ::: "memory" ); + __asm volatile ( "isb" ); + + break; + + #if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) + case portSVC_RAISE_PRIVILEGE: /* Only raise the privilege, if the + * svc was raised from any of the + * system calls. */ + + if( ( ulPC >= ( uint32_t ) __syscalls_flash_start__ ) && + ( ulPC <= ( uint32_t ) __syscalls_flash_end__ ) ) + { + __asm volatile + ( + " mrs r1, control \n"/* Obtain current control value. */ + " bic r1, #1 \n"/* Set privilege bit. */ + " msr control, r1 \n"/* Write back new control value. */ + ::: "r1", "memory" + ); + } + + break; + #else /* if ( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */ + case portSVC_RAISE_PRIVILEGE: + __asm volatile + ( + " mrs r1, control \n"/* Obtain current control value. */ + " bic r1, #1 \n"/* Set privilege bit. */ + " msr control, r1 \n"/* Write back new control value. */ + ::: "r1", "memory" + ); + break; + #endif /* #if( configENFORCE_SYSTEM_CALLS_FROM_KERNEL_ONLY == 1 ) */ + + default: /* Unknown SVC call. */ + break; } } /*-----------------------------------------------------------*/ -void vPortSVCHandler( void ) +static void prvRestoreContextOfFirstTask( void ) { - __asm volatile ( + __asm volatile + ( + " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ - " ldr r1, [r3] \n"/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ - " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ - " ldmia r0!, {r4-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + " ldr r1, [r3] \n" + " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */ + " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */ + " \n" + " dmb \n"/* Complete outstanding transfers before disabling MPU. */ + " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ + " str r3, [r2] \n"/* Disable MPU. */ + " \n" + " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */ + " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */ + " \n" + #if ( configTOTAL_MPU_REGIONS == 16 ) + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */ + " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */ + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */ + " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */ + #endif /* configTOTAL_MPU_REGIONS == 16. */ + " \n" + " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ + " str r3, [r2] \n"/* Enable MPU. */ + " dsb \n"/* Force memory writes before continuing. */ + " \n" + " ldmia r0!, {r3-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry. */ + " msr control, r3 \n" " msr psp, r0 \n"/* Restore the task stack pointer. */ - " isb \n" " mov r0, #0 \n" " msr basepri, r0 \n" " bx r14 \n" " \n" + " .ltorg \n"/* Assemble current literal pool to avoid offset-out-of-bound errors with lto. */ " .align 4 \n" - "pxCurrentTCBConst2: .word pxCurrentTCB \n" - ); -} -/*-----------------------------------------------------------*/ - -static void prvPortStartFirstTask( void ) -{ - /* Start the first task. This also clears the bit that indicates the FPU is - * in use in case the FPU was used before the scheduler was started - which - * would otherwise result in the unnecessary leaving of space in the SVC stack - * for lazy saving of FPU registers. */ - __asm volatile ( - " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ - " ldr r0, [r0] \n" - " ldr r0, [r0] \n" - " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ - " mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */ - " msr control, r0 \n" - " cpsie i \n"/* Globally enable interrupts. */ - " cpsie f \n" - " dsb \n" - " isb \n" - " svc 0 \n"/* System call to start first task. */ - " nop \n" - " .ltorg \n" - ); + "pxCurrentTCBConst2: .word pxCurrentTCB \n" + ); } /*-----------------------------------------------------------*/ @@ -296,96 +413,107 @@ static void prvPortStartFirstTask( void ) */ BaseType_t xPortStartScheduler( void ) { - /* This port can be used on all revisions of the Cortex-M7 core other than - * the r0p1 parts. r0p1 parts should use the port from the - * /source/portable/GCC/ARM_CM7/r0p1 directory. */ - configASSERT( portCPUID != portCORTEX_M7_r0p1_ID ); - configASSERT( portCPUID != portCORTEX_M7_r0p0_ID ); + /* Errata 837070 workaround must only be enabled on Cortex-M7 r0p0 + * and r0p1 cores. */ + #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) + configASSERT( ( portCPUID == portCORTEX_M7_r0p1_ID ) || ( portCPUID == portCORTEX_M7_r0p0_ID ) ); + #else + /* When using this port on a Cortex-M7 r0p0 or r0p1 core, define + * configENABLE_ERRATA_837070_WORKAROUND to 1 in your + * FreeRTOSConfig.h. */ + configASSERT( portCPUID != portCORTEX_M7_r0p1_ID ); + configASSERT( portCPUID != portCORTEX_M7_r0p0_ID ); + #endif #if ( configASSERT_DEFINED == 1 ) - { - volatile uint32_t ulOriginalPriority; - volatile uint32_t ulImplementedPrioBits = 0; - volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); - 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 = *pucFirstUserPriorityRegister; + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + 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 = *pucFirstUserPriorityRegister; - /* Determine the number of priority bits available. First write to all - * possible bits. */ - *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + /* Determine the number of priority bits available. First write to all + * possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; - /* Read the value back to see how many bits stuck. */ - ucMaxPriorityValue = *pucFirstUserPriorityRegister; + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; - /* Use the same mask on the maximum system call priority. */ - ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + /* 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 ); + /* 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. */ + /* 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; - } + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } - if( ulImplementedPrioBits == 8 ) - { - ulMaxPRIGROUPValue = 0; - } - else - { - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; - } + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } - #ifdef __NVIC_PRIO_BITS - { - /* Check the CMSIS configuration that defines the number of - * priority bits matches the number of priority bits actually queried - * from the hardware. */ - configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); - } - #endif + #ifdef __NVIC_PRIO_BITS + { + /* Check the CMSIS configuration that defines the number of + * priority bits matches the number of priority bits actually queried + * from the hardware. */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif - #ifdef configPRIO_BITS - { - /* Check the FreeRTOS configuration that defines the number of - * priority bits matches the number of priority bits actually queried - * from the hardware. */ - configASSERT( ulImplementedPrioBits == configPRIO_BITS ); - } - #endif + #ifdef configPRIO_BITS + { + /* Check the FreeRTOS configuration that defines the number of + * priority bits matches the number of priority bits actually queried + * from the hardware. */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); + } + #endif - /* Shift the priority group value back to its position within the AIRCR - * register. */ - ulMaxPRIGROUPValue <<= portPRIGROUP_SHIFT; - ulMaxPRIGROUPValue &= portPRIORITY_GROUP_MASK; + /* 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. */ - *pucFirstUserPriorityRegister = ulOriginalPriority; - } + /* Restore the clobbered interrupt priority register to its original + * value. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } #endif /* configASSERT_DEFINED */ - /* Make PendSV and SysTick the lowest priority interrupts. */ + /* Make PendSV and SysTick the same priority as the kernel, and the SVC + * handler higher priority so it can be used to exit a critical section (where + * lower priorities are masked). */ portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI; portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI; + /* Configure the regions in the MPU that are common to all tasks. */ + prvSetupMPU(); + /* Start the timer that generates the tick ISR. Interrupts are disabled * here already. */ vPortSetupTimerInterrupt(); @@ -399,17 +527,25 @@ BaseType_t xPortStartScheduler( void ) /* Lazy save always. */ *( portFPCCR ) |= portASPEN_AND_LSPEN_BITS; - /* Start the first task. */ - prvPortStartFirstTask(); - - /* Should never get here as the tasks will now be executing! Call the task - * exit error function to prevent compiler warnings about a static function - * not being called in the case that the application writer overrides this - * functionality by defining configTASK_RETURN_ADDRESS. Call - * vTaskSwitchContext() so link time optimisation does not remove the - * symbol. */ - vTaskSwitchContext(); - prvTaskExitError(); + /* Start the first task. This also clears the bit that indicates the FPU is + * in use in case the FPU was used before the scheduler was started - which + * would otherwise result in the unnecessary leaving of space in the SVC stack + * for lazy saving of FPU registers. */ + __asm volatile ( + " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, [r0] \n" + " ldr r0, [r0] \n" + " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ + " mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */ + " msr control, r0 \n" + " cpsie i \n"/* Globally enable interrupts. */ + " cpsie f \n" + " dsb \n" + " isb \n" + " svc %0 \n"/* System call to start first task. */ + " nop \n" + " .ltorg \n" + ::"i" ( portSVC_START_SCHEDULER ) : "memory" ); /* Should not get here! */ return 0; @@ -426,23 +562,62 @@ void vPortEndScheduler( void ) void vPortEnterCritical( void ) { - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; +#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) + if( portIS_PRIVILEGED() == pdFALSE ) + { + portRAISE_PRIVILEGE(); + portMEMORY_BARRIER(); - /* This is not the interrupt safe version of the enter critical function so - * assert() if it is being called from an interrupt context. Only API - * functions that end in "FromISR" can be used in an interrupt. Only assert if - * the critical nesting count is 1 to protect against recursive calls if the - * assert function also uses a critical section. */ - if( uxCriticalNesting == 1 ) + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + portMEMORY_BARRIER(); + + portRESET_PRIVILEGE(); + portMEMORY_BARRIER(); + } + else { - configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; } +#else + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; +#endif } /*-----------------------------------------------------------*/ void vPortExitCritical( void ) { +#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) + if( portIS_PRIVILEGED() == pdFALSE ) + { + portRAISE_PRIVILEGE(); + portMEMORY_BARRIER(); + + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } + portMEMORY_BARRIER(); + + portRESET_PRIVILEGE(); + portMEMORY_BARRIER(); + } + else + { + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; + + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } + } +#else configASSERT( uxCriticalNesting ); uxCriticalNesting--; @@ -450,6 +625,7 @@ void vPortExitCritical( void ) { portENABLE_INTERRUPTS(); } +#endif } /*-----------------------------------------------------------*/ @@ -469,40 +645,64 @@ void xPortPendSVHandler( void ) " it eq \n" " vstmdbeq r0!, {s16-s31} \n" " \n" - " stmdb r0!, {r4-r11, r14} \n"/* Save the core registers. */ + " mrs r1, control \n" + " stmdb r0!, {r1, r4-r11, r14} \n"/* Save the remaining registers. */ " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ " \n" " stmdb sp!, {r0, r3} \n" " mov r0, %0 \n" + #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) + " cpsid i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ + #endif " msr basepri, r0 \n" " dsb \n" " isb \n" + #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) + " cpsie i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ + #endif " bl vTaskSwitchContext \n" " mov r0, #0 \n" " msr basepri, r0 \n" " ldmia sp!, {r0, r3} \n" + " \n"/* Restore the context. */ + " ldr r1, [r3] \n" + " ldr r0, [r1] \n"/* The first item in the TCB is the task top of stack. */ + " add r1, r1, #4 \n"/* Move onto the second item in the TCB... */ + " \n" + " dmb \n"/* Complete outstanding transfers before disabling MPU. */ + " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " bic r3, #1 \n"/* r3 = r3 & ~1 i.e. Clear the bit 0 in r3. */ + " str r3, [r2] \n"/* Disable MPU. */ + " \n" + " ldr r2, =0xe000ed9c \n"/* Region Base Address register. */ + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 4 - 7]. */ + " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers [MPU Region # 4 - 7]. */ + " \n" + #if ( configTOTAL_MPU_REGIONS == 16 ) + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 8 - 11]. */ + " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 8 - 11]. */ + " ldmia r1!, {r4-r11} \n"/* Read 4 sets of MPU registers [MPU Region # 12 - 15]. */ + " stmia r2, {r4-r11} \n"/* Write 4 sets of MPU registers. [MPU Region # 12 - 15]. */ + #endif /* configTOTAL_MPU_REGIONS == 16. */ " \n" - " ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */ - " ldr r0, [r1] \n" + " ldr r2, =0xe000ed94 \n"/* MPU_CTRL register. */ + " ldr r3, [r2] \n"/* Read the value of MPU_CTRL. */ + " orr r3, #1 \n"/* r3 = r3 | 1 i.e. Set the bit 0 in r3. */ + " str r3, [r2] \n"/* Enable MPU. */ + " dsb \n"/* Force memory writes before continuing. */ " \n" - " ldmia r0!, {r4-r11, r14} \n"/* Pop the core registers. */ + " ldmia r0!, {r3-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry. */ + " msr control, r3 \n" " \n" " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, pop the high vfp registers too. */ " it eq \n" " vldmiaeq r0!, {s16-s31} \n" " \n" " msr psp, r0 \n" - " isb \n" - " \n" - #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */ - #if WORKAROUND_PMU_CM001 == 1 - " push { r14 } \n" - " pop { pc } \n" - #endif - #endif - " \n" " bx r14 \n" " \n" + " .ltorg \n"/* Assemble the current literal pool to avoid offset-out-of-bound errors with lto. */ " .align 4 \n" "pxCurrentTCBConst: .word pxCurrentTCB \n" ::"i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) @@ -512,267 +712,34 @@ void xPortPendSVHandler( void ) void xPortSysTickHandler( void ) { - /* The SysTick runs at the lowest interrupt priority, so when this interrupt - * executes all interrupts must be unmasked. There is therefore no need to - * save and then restore the interrupt mask value as its value is already - * known. */ - portDISABLE_INTERRUPTS(); + uint32_t ulDummy; + + ulDummy = portSET_INTERRUPT_MASK_FROM_ISR(); { /* Increment the RTOS tick. */ if( xTaskIncrementTick() != pdFALSE ) { - /* A context switch is required. Context switching is performed in - * the PendSV interrupt. Pend the PendSV interrupt. */ + /* Pend a context switch. */ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } } - portENABLE_INTERRUPTS(); + portCLEAR_INTERRUPT_MASK_FROM_ISR( ulDummy ); } /*-----------------------------------------------------------*/ -#if ( configUSE_TICKLESS_IDLE == 1 ) - - __attribute__( ( weak ) ) void vPortSuppressTicksAndSleep( TickType_t xExpectedIdleTime ) - { - uint32_t ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickDecrementsLeft; - TickType_t xModifiableIdleTime; - - /* Make sure the SysTick reload value does not overflow the counter. */ - if( xExpectedIdleTime > xMaximumPossibleSuppressedTicks ) - { - xExpectedIdleTime = xMaximumPossibleSuppressedTicks; - } - - /* Enter a critical section but don't use the taskENTER_CRITICAL() - * method as that will mask interrupts that should exit sleep mode. */ - __asm volatile ( "cpsid i" ::: "memory" ); - __asm volatile ( "dsb" ); - __asm volatile ( "isb" ); - - /* If a context switch is pending or a task is waiting for the scheduler - * to be unsuspended then abandon the low power entry. */ - if( eTaskConfirmSleepModeStatus() == eAbortSleep ) - { - /* Re-enable interrupts - see comments above the cpsid instruction - * above. */ - __asm volatile ( "cpsie i" ::: "memory" ); - } - else - { - /* Stop the SysTick momentarily. The time the SysTick is stopped for - * is accounted for as best it can be, but using the tickless mode will - * inevitably result in some tiny drift of the time maintained by the - * kernel with respect to calendar time. */ - portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT ); - - /* Use the SysTick current-value register to determine the number of - * SysTick decrements remaining until the next tick interrupt. If the - * current-value register is zero, then there are actually - * ulTimerCountsForOneTick decrements remaining, not zero, because the - * SysTick requests the interrupt when decrementing from 1 to 0. */ - ulSysTickDecrementsLeft = portNVIC_SYSTICK_CURRENT_VALUE_REG; - - if( ulSysTickDecrementsLeft == 0 ) - { - ulSysTickDecrementsLeft = ulTimerCountsForOneTick; - } - - /* Calculate the reload value required to wait xExpectedIdleTime - * tick periods. -1 is used because this code normally executes part - * way through the first tick period. But if the SysTick IRQ is now - * pending, then clear the IRQ, suppressing the first tick, and correct - * the reload value to reflect that the second tick period is already - * underway. The expected idle time is always at least two ticks. */ - ulReloadValue = ulSysTickDecrementsLeft + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) ); - - if( ( portNVIC_INT_CTRL_REG & portNVIC_PEND_SYSTICK_SET_BIT ) != 0 ) - { - portNVIC_INT_CTRL_REG = portNVIC_PEND_SYSTICK_CLEAR_BIT; - ulReloadValue -= ulTimerCountsForOneTick; - } - - if( ulReloadValue > ulStoppedTimerCompensation ) - { - ulReloadValue -= ulStoppedTimerCompensation; - } - - /* Set the new reload value. */ - portNVIC_SYSTICK_LOAD_REG = ulReloadValue; - - /* Clear the SysTick count flag and set the count value back to - * zero. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - - /* Restart SysTick. */ - portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT; - - /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can - * set its parameter to 0 to indicate that its implementation contains - * its own wait for interrupt or wait for event instruction, and so wfi - * should not be executed again. However, the original expected idle - * time variable must remain unmodified, so a copy is taken. */ - xModifiableIdleTime = xExpectedIdleTime; - configPRE_SLEEP_PROCESSING( xModifiableIdleTime ); - - if( xModifiableIdleTime > 0 ) - { - __asm volatile ( "dsb" ::: "memory" ); - __asm volatile ( "wfi" ); - __asm volatile ( "isb" ); - } - - configPOST_SLEEP_PROCESSING( xExpectedIdleTime ); - - /* Re-enable interrupts to allow the interrupt that brought the MCU - * out of sleep mode to execute immediately. See comments above - * the cpsid instruction above. */ - __asm volatile ( "cpsie i" ::: "memory" ); - __asm volatile ( "dsb" ); - __asm volatile ( "isb" ); - - /* Disable interrupts again because the clock is about to be stopped - * and interrupts that execute while the clock is stopped will increase - * any slippage between the time maintained by the RTOS and calendar - * time. */ - __asm volatile ( "cpsid i" ::: "memory" ); - __asm volatile ( "dsb" ); - __asm volatile ( "isb" ); - - /* Disable the SysTick clock without reading the - * portNVIC_SYSTICK_CTRL_REG register to ensure the - * portNVIC_SYSTICK_COUNT_FLAG_BIT is not cleared if it is set. Again, - * the time the SysTick is stopped for is accounted for as best it can - * be, but using the tickless mode will inevitably result in some tiny - * drift of the time maintained by the kernel with respect to calendar - * time*/ - portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT ); - - /* Determine whether the SysTick has already counted to zero. */ - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) - { - uint32_t ulCalculatedLoadValue; - - /* The tick interrupt ended the sleep (or is now pending), and - * a new tick period has started. Reset portNVIC_SYSTICK_LOAD_REG - * with whatever remains of the new tick period. */ - ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ) - ( ulReloadValue - portNVIC_SYSTICK_CURRENT_VALUE_REG ); - - /* Don't allow a tiny value, or values that have somehow - * underflowed because the post sleep hook did something - * that took too long or because the SysTick current-value register - * is zero. */ - if( ( ulCalculatedLoadValue <= ulStoppedTimerCompensation ) || ( ulCalculatedLoadValue > ulTimerCountsForOneTick ) ) - { - ulCalculatedLoadValue = ( ulTimerCountsForOneTick - 1UL ); - } - - portNVIC_SYSTICK_LOAD_REG = ulCalculatedLoadValue; - - /* As the pending tick will be processed as soon as this - * function exits, the tick value maintained by the tick is stepped - * forward by one less than the time spent waiting. */ - ulCompleteTickPeriods = xExpectedIdleTime - 1UL; - } - else - { - /* Something other than the tick interrupt ended the sleep. */ - - /* Use the SysTick current-value register to determine the - * number of SysTick decrements remaining until the expected idle - * time would have ended. */ - ulSysTickDecrementsLeft = portNVIC_SYSTICK_CURRENT_VALUE_REG; - #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG != portNVIC_SYSTICK_CLK_BIT ) - { - /* If the SysTick is not using the core clock, the current- - * value register might still be zero here. In that case, the - * SysTick didn't load from the reload register, and there are - * ulReloadValue decrements remaining in the expected idle - * time, not zero. */ - if( ulSysTickDecrementsLeft == 0 ) - { - ulSysTickDecrementsLeft = ulReloadValue; - } - } - #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ - - /* Work out how long the sleep lasted rounded to complete tick - * periods (not the ulReload value which accounted for part - * ticks). */ - ulCompletedSysTickDecrements = ( xExpectedIdleTime * ulTimerCountsForOneTick ) - ulSysTickDecrementsLeft; - - /* How many complete tick periods passed while the processor - * was waiting? */ - ulCompleteTickPeriods = ulCompletedSysTickDecrements / ulTimerCountsForOneTick; - - /* The reload value is set to whatever fraction of a single tick - * period remains. */ - portNVIC_SYSTICK_LOAD_REG = ( ( ulCompleteTickPeriods + 1UL ) * ulTimerCountsForOneTick ) - ulCompletedSysTickDecrements; - } - - /* Restart SysTick so it runs from portNVIC_SYSTICK_LOAD_REG again, - * then set portNVIC_SYSTICK_LOAD_REG back to its standard value. If - * the SysTick is not using the core clock, temporarily configure it to - * use the core clock. This configuration forces the SysTick to load - * from portNVIC_SYSTICK_LOAD_REG immediately instead of at the next - * cycle of the other clock. Then portNVIC_SYSTICK_LOAD_REG is ready - * to receive the standard value immediately. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; - #if ( portNVIC_SYSTICK_CLK_BIT_CONFIG == portNVIC_SYSTICK_CLK_BIT ) - { - portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - } - #else - { - /* The temporary usage of the core clock has served its purpose, - * as described above. Resume usage of the other clock. */ - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT; - - if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) - { - /* The partial tick period already ended. Be sure the SysTick - * counts it only once. */ - portNVIC_SYSTICK_CURRENT_VALUE_REG = 0; - } - - portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; - portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT; - } - #endif /* portNVIC_SYSTICK_CLK_BIT_CONFIG */ - - /* Step the tick to account for any tick periods that elapsed. */ - vTaskStepTick( ulCompleteTickPeriods ); - - /* Exit with interrupts enabled. */ - __asm volatile ( "cpsie i" ::: "memory" ); - } - } - -#endif /* #if configUSE_TICKLESS_IDLE */ -/*-----------------------------------------------------------*/ - /* * Setup the systick timer to generate the tick interrupts at the required * frequency. */ __attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void ) { - /* Calculate the constants required to configure the tick interrupt. */ - #if ( configUSE_TICKLESS_IDLE == 1 ) - { - ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); - xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; - ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); - } - #endif /* configUSE_TICKLESS_IDLE */ - /* Stop and clear the SysTick. */ portNVIC_SYSTICK_CTRL_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; /* Configure SysTick to interrupt at the requested rate. */ portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; - portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT_CONFIG | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); + portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE ); } /*-----------------------------------------------------------*/ @@ -792,6 +759,243 @@ static void vPortEnableVFP( void ) } /*-----------------------------------------------------------*/ +static void prvSetupMPU( void ) +{ + #if defined( __ARMCC_VERSION ) + + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __privileged_functions_start__; + extern uint32_t * __privileged_functions_end__; + extern uint32_t * __FLASH_segment_start__; + extern uint32_t * __FLASH_segment_end__; + extern uint32_t * __privileged_data_start__; + extern uint32_t * __privileged_data_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __privileged_functions_start__[]; + extern uint32_t __privileged_functions_end__[]; + extern uint32_t __FLASH_segment_start__[]; + extern uint32_t __FLASH_segment_end__[]; + extern uint32_t __privileged_data_start__[]; + extern uint32_t __privileged_data_end__[]; + #endif /* if defined( __ARMCC_VERSION ) */ + + /* The only permitted number of regions are 8 or 16. */ + configASSERT( ( configTOTAL_MPU_REGIONS == 8 ) || ( configTOTAL_MPU_REGIONS == 16 ) ); + + /* Ensure that the configTOTAL_MPU_REGIONS is configured correctly. */ + configASSERT( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE ); + + /* Check the expected MPU is present. */ + if( portMPU_TYPE_REG == portEXPECTED_MPU_TYPE_VALUE ) + { + /* First setup the unprivileged flash for unprivileged read only access. */ + portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __FLASH_segment_start__ ) | /* Base address. */ + ( portMPU_REGION_VALID ) | + ( portUNPRIVILEGED_FLASH_REGION ); + + portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_ONLY ) | + ( ( configTEX_S_C_B_FLASH & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) | + ( prvGetMPURegionSizeSetting( ( uint32_t ) __FLASH_segment_end__ - ( uint32_t ) __FLASH_segment_start__ ) ) | + ( portMPU_REGION_ENABLE ); + + /* Setup the privileged flash for privileged only access. This is where + * the kernel code is placed. */ + portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_functions_start__ ) | /* Base address. */ + ( portMPU_REGION_VALID ) | + ( portPRIVILEGED_FLASH_REGION ); + + portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_ONLY ) | + ( ( configTEX_S_C_B_FLASH & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) | + ( prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_functions_end__ - ( uint32_t ) __privileged_functions_start__ ) ) | + ( portMPU_REGION_ENABLE ); + + /* Setup the privileged data RAM region. This is where the kernel data + * is placed. */ + portMPU_REGION_BASE_ADDRESS_REG = ( ( uint32_t ) __privileged_data_start__ ) | /* Base address. */ + ( portMPU_REGION_VALID ) | + ( portPRIVILEGED_RAM_REGION ); + + portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_PRIVILEGED_READ_WRITE ) | + ( portMPU_REGION_EXECUTE_NEVER ) | + ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) | + prvGetMPURegionSizeSetting( ( uint32_t ) __privileged_data_end__ - ( uint32_t ) __privileged_data_start__ ) | + ( portMPU_REGION_ENABLE ); + + /* By default allow everything to access the general peripherals. The + * system peripherals and registers are protected. */ + portMPU_REGION_BASE_ADDRESS_REG = ( portPERIPHERALS_START_ADDRESS ) | + ( portMPU_REGION_VALID ) | + ( portGENERAL_PERIPHERALS_REGION ); + + portMPU_REGION_ATTRIBUTE_REG = ( portMPU_REGION_READ_WRITE | portMPU_REGION_EXECUTE_NEVER ) | + ( prvGetMPURegionSizeSetting( portPERIPHERALS_END_ADDRESS - portPERIPHERALS_START_ADDRESS ) ) | + ( portMPU_REGION_ENABLE ); + + /* Enable the memory fault exception. */ + portNVIC_SYS_CTRL_STATE_REG |= portNVIC_MEM_FAULT_ENABLE; + + /* Enable the MPU with the background region configured. */ + portMPU_CTRL_REG |= ( portMPU_ENABLE | portMPU_BACKGROUND_ENABLE ); + } +} +/*-----------------------------------------------------------*/ + +static uint32_t prvGetMPURegionSizeSetting( uint32_t ulActualSizeInBytes ) +{ + uint32_t ulRegionSize, ulReturnValue = 4; + + /* 32 is the smallest region size, 31 is the largest valid value for + * ulReturnValue. */ + for( ulRegionSize = 32UL; ulReturnValue < 31UL; ( ulRegionSize <<= 1UL ) ) + { + if( ulActualSizeInBytes <= ulRegionSize ) + { + break; + } + else + { + ulReturnValue++; + } + } + + /* Shift the code by one before returning so it can be written directly + * into the the correct bit position of the attribute register. */ + return( ulReturnValue << 1UL ); +} +/*-----------------------------------------------------------*/ + +BaseType_t xIsPrivileged( void ) /* __attribute__ (( naked )) */ +{ + __asm volatile + ( + " mrs r0, control \n"/* r0 = CONTROL. */ + " tst r0, #1 \n"/* Perform r0 & 1 (bitwise AND) and update the conditions flag. */ + " ite ne \n" + " movne r0, #0 \n"/* CONTROL[0]!=0. Return false to indicate that the processor is not privileged. */ + " moveq r0, #1 \n"/* CONTROL[0]==0. Return true to indicate that the processor is privileged. */ + " bx lr \n"/* Return. */ + " \n" + " .align 4 \n" + ::: "r0", "memory" + ); +} +/*-----------------------------------------------------------*/ + +void vResetPrivilege( void ) /* __attribute__ (( naked )) */ +{ + __asm volatile + ( + " mrs r0, control \n"/* r0 = CONTROL. */ + " orr r0, #1 \n"/* r0 = r0 | 1. */ + " msr control, r0 \n"/* CONTROL = r0. */ + " bx lr \n"/* Return to the caller. */ + ::: "r0", "memory" + ); +} +/*-----------------------------------------------------------*/ + +void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, + const struct xMEMORY_REGION * const xRegions, + StackType_t * pxBottomOfStack, + uint32_t ulStackDepth ) +{ + #if defined( __ARMCC_VERSION ) + + /* Declaration when these variable are defined in code instead of being + * exported from linker scripts. */ + extern uint32_t * __SRAM_segment_start__; + extern uint32_t * __SRAM_segment_end__; + extern uint32_t * __privileged_data_start__; + extern uint32_t * __privileged_data_end__; + #else + /* Declaration when these variable are exported from linker scripts. */ + extern uint32_t __SRAM_segment_start__[]; + extern uint32_t __SRAM_segment_end__[]; + extern uint32_t __privileged_data_start__[]; + extern uint32_t __privileged_data_end__[]; + #endif /* if defined( __ARMCC_VERSION ) */ + + int32_t lIndex; + uint32_t ul; + + if( xRegions == NULL ) + { + /* No MPU regions are specified so allow access to all RAM. */ + xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress = + ( ( uint32_t ) __SRAM_segment_start__ ) | /* Base address. */ + ( portMPU_REGION_VALID ) | + ( portSTACK_REGION ); /* Region number. */ + + xMPUSettings->xRegion[ 0 ].ulRegionAttribute = + ( portMPU_REGION_READ_WRITE ) | + ( portMPU_REGION_EXECUTE_NEVER ) | + ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) | + ( prvGetMPURegionSizeSetting( ( uint32_t ) __SRAM_segment_end__ - ( uint32_t ) __SRAM_segment_start__ ) ) | + ( portMPU_REGION_ENABLE ); + + /* Invalidate user configurable regions. */ + for( ul = 1UL; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ ) + { + xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( ( ul - 1UL ) | portMPU_REGION_VALID ); + xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL; + } + } + else + { + /* This function is called automatically when the task is created - in + * which case the stack region parameters will be valid. At all other + * times the stack parameters will not be valid and it is assumed that the + * stack region has already been configured. */ + if( ulStackDepth > 0 ) + { + /* Define the region that allows access to the stack. */ + xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress = + ( ( uint32_t ) pxBottomOfStack ) | + ( portMPU_REGION_VALID ) | + ( portSTACK_REGION ); /* Region number. */ + + xMPUSettings->xRegion[ 0 ].ulRegionAttribute = + ( portMPU_REGION_READ_WRITE ) | + ( portMPU_REGION_EXECUTE_NEVER ) | + ( prvGetMPURegionSizeSetting( ulStackDepth * ( uint32_t ) sizeof( StackType_t ) ) ) | + ( ( configTEX_S_C_B_SRAM & portMPU_RASR_TEX_S_C_B_MASK ) << portMPU_RASR_TEX_S_C_B_LOCATION ) | + ( portMPU_REGION_ENABLE ); + } + + lIndex = 0; + + for( ul = 1UL; ul <= portNUM_CONFIGURABLE_REGIONS; ul++ ) + { + if( ( xRegions[ lIndex ] ).ulLengthInBytes > 0UL ) + { + /* Translate the generic region definition contained in + * xRegions into the CM4 specific MPU settings that are then + * stored in xMPUSettings. */ + xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = + ( ( uint32_t ) xRegions[ lIndex ].pvBaseAddress ) | + ( portMPU_REGION_VALID ) | + ( ul - 1UL ); /* Region number. */ + + xMPUSettings->xRegion[ ul ].ulRegionAttribute = + ( prvGetMPURegionSizeSetting( xRegions[ lIndex ].ulLengthInBytes ) ) | + ( xRegions[ lIndex ].ulParameters ) | + ( portMPU_REGION_ENABLE ); + } + else + { + /* Invalidate the region. */ + xMPUSettings->xRegion[ ul ].ulRegionBaseAddress = ( ( ul - 1UL ) | portMPU_REGION_VALID ); + xMPUSettings->xRegion[ ul ].ulRegionAttribute = 0UL; + } + + lIndex++; + } + } +} +/*-----------------------------------------------------------*/ + #if ( configASSERT_DEFINED == 1 ) void vPortValidateInterruptPriority( void ) @@ -820,10 +1024,10 @@ static void vPortEnableVFP( void ) * 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, + * 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. + * 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. @@ -846,8 +1050,9 @@ static void vPortEnableVFP( void ) * 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. */ + * of zero will result in unpredicable behaviour. */ configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* configASSERT_DEFINED */ \ No newline at end of file +#endif /* configASSERT_DEFINED */ +/*-----------------------------------------------------------*/ \ No newline at end of file From cb183b7d0ba3d3e6ed4a1b3e280c094356295868 Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Mon, 13 Mar 2023 12:10:53 +0000 Subject: [PATCH 07/21] Fix GCC ARM_CM7 --- portable/GCC/ARM_CM7/r0p1/port.c | 49 ++++++++++++++++---------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/portable/GCC/ARM_CM7/r0p1/port.c b/portable/GCC/ARM_CM7/r0p1/port.c index cf3696bedd..2ea8e312d5 100755 --- a/portable/GCC/ARM_CM7/r0p1/port.c +++ b/portable/GCC/ARM_CM7/r0p1/port.c @@ -245,11 +245,11 @@ static void prvTaskExitError( void ) void vPortSVCHandler( void ) { __asm volatile ( - " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ - " ldr r1, [r3] \n"/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ - " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ - " ldmia r0!, {r4-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ - " msr psp, r0 \n"/* Restore the task stack pointer. */ + " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ + " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + " msr psp, r0 \n" /* Restore the task stack pointer. */ " isb \n" " mov r0, #0 \n" " msr basepri, r0 \n" @@ -268,17 +268,17 @@ static void prvPortStartFirstTask( void ) * would otherwise result in the unnecessary leaving of space in the SVC stack * for lazy saving of FPU registers. */ __asm volatile ( - " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ " ldr r0, [r0] \n" " ldr r0, [r0] \n" - " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ - " mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */ + " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ + " mov r0, #0 \n" /* Clear the bit that indicates the FPU is in use, see comment above. */ " msr control, r0 \n" - " cpsie i \n"/* Globally enable interrupts. */ + " cpsie i \n" /* Globally enable interrupts. */ " cpsie f \n" " dsb \n" " isb \n" - " svc 0 \n"/* System call to start first task. */ + " svc 0 \n" /* System call to start first task. */ " nop \n" " .ltorg \n" ); @@ -292,8 +292,9 @@ BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; - volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint32_t ulOriginalPriority, + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API @@ -337,7 +338,7 @@ BaseType_t xPortStartScheduler( void ) } else { - ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; } #ifdef __NVIC_PRIO_BITS @@ -449,34 +450,34 @@ void xPortPendSVHandler( void ) " mrs r0, psp \n" " isb \n" " \n" - " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ + " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ " ldr r2, [r3] \n" " \n" - " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, push high vfp registers. */ + " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */ " it eq \n" " vstmdbeq r0!, {s16-s31} \n" " \n" - " stmdb r0!, {r4-r11, r14} \n"/* Save the core registers. */ - " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ + " stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */ + " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ " \n" " stmdb sp!, {r0, r3} \n" " mov r0, %0 \n" - " cpsid i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ + " cpsid i \n" /* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ " msr basepri, r0 \n" " dsb \n" " isb \n" - " cpsie i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ + " cpsie i \n" /* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ " bl vTaskSwitchContext \n" " mov r0, #0 \n" " msr basepri, r0 \n" " ldmia sp!, {r0, r3} \n" " \n" - " ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */ + " ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n" " \n" - " ldmia r0!, {r4-r11, r14} \n"/* Pop the core registers. */ + " ldmia r0!, {r4-r11, r14} \n" /* Pop the core registers. */ " \n" - " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, pop the high vfp registers too. */ + " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */ " it eq \n" " vldmiaeq r0!, {s16-s31} \n" " \n" @@ -770,10 +771,10 @@ static void vPortEnableVFP( void ) { __asm volatile ( - " ldr.w r0, =0xE000ED88 \n"/* The FPU enable bits are in the CPACR. */ + " ldr.w r0, =0xE000ED88 \n" /* The FPU enable bits are in the CPACR. */ " ldr r1, [r0] \n" " \n" - " orr r1, r1, #( 0xf << 20 ) \n"/* Enable CP10 and CP11 coprocessors, then save back. */ + " orr r1, r1, #( 0xf << 20 ) \n" /* Enable CP10 and CP11 coprocessors, then save back. */ " str r1, [r0] \n" " bx r14 \n" " .ltorg \n" From 28e98701f132818bb1775939a045741e91a93811 Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Mon, 13 Mar 2023 12:16:15 +0000 Subject: [PATCH 08/21] Fix IAR ARM ports --- portable/IAR/ARM_CM4F/port.c | 19 ++- portable/IAR/ARM_CM4F_MPU/port.c | 275 ++++++++++++++++--------------- portable/IAR/ARM_CM7/r0p1/port.c | 19 ++- 3 files changed, 173 insertions(+), 140 deletions(-) mode change 100644 => 100755 portable/IAR/ARM_CM4F/port.c mode change 100644 => 100755 portable/IAR/ARM_CM4F_MPU/port.c mode change 100644 => 100755 portable/IAR/ARM_CM7/r0p1/port.c diff --git a/portable/IAR/ARM_CM4F/port.c b/portable/IAR/ARM_CM4F/port.c old mode 100644 new mode 100755 index 90be11d0ed..b236f47f78 --- a/portable/IAR/ARM_CM4F/port.c +++ b/portable/IAR/ARM_CM4F/port.c @@ -249,7 +249,8 @@ BaseType_t xPortStartScheduler( void ) #if ( configASSERT_DEFINED == 1 ) { volatile uint32_t ulOriginalPriority; - volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API @@ -280,20 +281,28 @@ BaseType_t xPortStartScheduler( void ) /* Calculate the maximum acceptable priority group value for the number * of bits read back. */ - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) { - ulMaxPRIGROUPValue--; + ulImplementedPrioBits++; ucMaxPriorityValue <<= ( uint8_t ) 0x01; } + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + #ifdef __NVIC_PRIO_BITS { /* Check the CMSIS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); } #endif @@ -302,7 +311,7 @@ BaseType_t xPortStartScheduler( void ) /* Check the FreeRTOS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); } #endif diff --git a/portable/IAR/ARM_CM4F_MPU/port.c b/portable/IAR/ARM_CM4F_MPU/port.c old mode 100644 new mode 100755 index dd6bde281c..c872335f64 --- a/portable/IAR/ARM_CM4F_MPU/port.c +++ b/portable/IAR/ARM_CM4F_MPU/port.c @@ -194,7 +194,7 @@ extern void vPortRestoreContextOfFirstTask( void ) PRIVILEGED_FUNCTION; /** * @brief Enter critical section. */ -#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) +#if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) void vPortEnterCritical( void ) FREERTOS_SYSTEM_CALL; #else void vPortEnterCritical( void ) PRIVILEGED_FUNCTION; @@ -203,7 +203,7 @@ extern void vPortRestoreContextOfFirstTask( void ) PRIVILEGED_FUNCTION; /** * @brief Exit from critical section. */ -#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) +#if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) void vPortExitCritical( void ) FREERTOS_SYSTEM_CALL; #else void vPortExitCritical( void ) PRIVILEGED_FUNCTION; @@ -316,9 +316,9 @@ void vPortSVCHandler_C( uint32_t * pulParam ) { __asm volatile ( - " mrs r1, control \n"/* Obtain current control value. */ - " bic r1, r1, #1 \n"/* Set privilege bit. */ - " msr control, r1 \n"/* Write back new control value. */ + " mrs r1, control \n" /* Obtain current control value. */ + " bic r1, r1, #1 \n" /* Set privilege bit. */ + " msr control, r1 \n" /* Write back new control value. */ ::: "r1", "memory" ); } @@ -328,9 +328,9 @@ void vPortSVCHandler_C( uint32_t * pulParam ) case portSVC_RAISE_PRIVILEGE: __asm volatile ( - " mrs r1, control \n"/* Obtain current control value. */ - " bic r1, r1, #1 \n"/* Set privilege bit. */ - " msr control, r1 \n"/* Write back new control value. */ + " mrs r1, control \n" /* Obtain current control value. */ + " bic r1, r1, #1 \n" /* Set privilege bit. */ + " msr control, r1 \n" /* Write back new control value. */ ::: "r1", "memory" ); break; @@ -352,6 +352,7 @@ BaseType_t xPortStartScheduler( void ) #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) configASSERT( ( portCPUID == portCORTEX_M7_r0p1_ID ) || ( portCPUID == portCORTEX_M7_r0p0_ID ) ); #else + /* When using this port on a Cortex-M7 r0p0 or r0p1 core, define * configENABLE_ERRATA_837070_WORKAROUND to 1 in your * FreeRTOSConfig.h. */ @@ -360,74 +361,83 @@ BaseType_t xPortStartScheduler( void ) #endif #if ( configASSERT_DEFINED == 1 ) - { - volatile uint32_t ulOriginalPriority; - volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); - 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 = *pucFirstUserPriorityRegister; + { + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + 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 = *pucFirstUserPriorityRegister; - /* Determine the number of priority bits available. First write to all - * possible bits. */ - *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; + /* Determine the number of priority bits available. First write to all + * possible bits. */ + *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; - /* Read the value back to see how many bits stuck. */ - ucMaxPriorityValue = *pucFirstUserPriorityRegister; + /* Read the value back to see how many bits stuck. */ + ucMaxPriorityValue = *pucFirstUserPriorityRegister; - /* Use the same mask on the maximum system call priority. */ - ucMaxSysCallPriority = configMAX_SYSCALL_INTERRUPT_PRIORITY & ucMaxPriorityValue; + /* 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 ); + /* 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. */ - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; + /* Calculate the maximum acceptable priority group value for the number + * of bits read back. */ - while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) - { - ulMaxPRIGROUPValue--; - ucMaxPriorityValue <<= ( uint8_t ) 0x01; - } + while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) + { + ulImplementedPrioBits++; + ucMaxPriorityValue <<= ( uint8_t ) 0x01; + } - #ifdef __NVIC_PRIO_BITS - { - /* Check the CMSIS configuration that defines the number of - * priority bits matches the number of priority bits actually queried - * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); - } - #endif - - #ifdef configPRIO_BITS - { - /* Check the FreeRTOS configuration that defines the number of - * priority bits matches the number of priority bits actually queried - * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); - } - #endif - - /* 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. */ - *pucFirstUserPriorityRegister = ulOriginalPriority; + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + + #ifdef __NVIC_PRIO_BITS + { + /* Check the CMSIS configuration that defines the number of + * priority bits matches the number of priority bits actually queried + * from the hardware. */ + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); + } + #endif + + #ifdef configPRIO_BITS + { + /* Check the FreeRTOS configuration that defines the number of + * priority bits matches the number of priority bits actually queried + * from the hardware. */ + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); } + #endif + + /* 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. */ + *pucFirstUserPriorityRegister = ulOriginalPriority; + } #endif /* configASSERT_DEFINED */ /* Make PendSV and SysTick the lowest priority interrupts. */ @@ -468,32 +478,49 @@ void vPortEndScheduler( void ) void vPortEnterCritical( void ) { -#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) - if( portIS_PRIVILEGED() == pdFALSE ) - { - portRAISE_PRIVILEGE(); - portMEMORY_BARRIER(); + #if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) + if( portIS_PRIVILEGED() == pdFALSE ) + { + portRAISE_PRIVILEGE(); + portMEMORY_BARRIER(); + + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + + /* This is not the interrupt safe version of the enter critical function so + * assert() if it is being called from an interrupt context. Only API + * functions that end in "FromISR" can be used in an interrupt. Only assert if + * the critical nesting count is 1 to protect against recursive calls if the + * assert function also uses a critical section. */ + if( uxCriticalNesting == 1 ) + { + configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + } - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; - /* This is not the interrupt safe version of the enter critical function so - * assert() if it is being called from an interrupt context. Only API - * functions that end in "FromISR" can be used in an interrupt. Only assert if - * the critical nesting count is 1 to protect against recursive calls if the - * assert function also uses a critical section. */ - if( uxCriticalNesting == 1 ) + portMEMORY_BARRIER(); + + portRESET_PRIVILEGE(); + portMEMORY_BARRIER(); + } + else { - configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + + /* This is not the interrupt safe version of the enter critical function so + * assert() if it is being called from an interrupt context. Only API + * functions that end in "FromISR" can be used in an interrupt. Only assert if + * the critical nesting count is 1 to protect against recursive calls if the + * assert function also uses a critical section. */ + if( uxCriticalNesting == 1 ) + { + configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); + } } - portMEMORY_BARRIER(); - - portRESET_PRIVILEGE(); - portMEMORY_BARRIER(); - } - else - { + #else /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ portDISABLE_INTERRUPTS(); uxCriticalNesting++; + /* This is not the interrupt safe version of the enter critical function so * assert() if it is being called from an interrupt context. Only API * functions that end in "FromISR" can be used in an interrupt. Only assert if @@ -503,45 +530,42 @@ void vPortEnterCritical( void ) { configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); } - } -#else - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; - /* This is not the interrupt safe version of the enter critical function so - * assert() if it is being called from an interrupt context. Only API - * functions that end in "FromISR" can be used in an interrupt. Only assert if - * the critical nesting count is 1 to protect against recursive calls if the - * assert function also uses a critical section. */ - if( uxCriticalNesting == 1 ) - { - configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); - } -#endif + #endif /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ } /*-----------------------------------------------------------*/ void vPortExitCritical( void ) { -#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) - if( portIS_PRIVILEGED() == pdFALSE ) - { - portRAISE_PRIVILEGE(); - portMEMORY_BARRIER(); + #if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) + if( portIS_PRIVILEGED() == pdFALSE ) + { + portRAISE_PRIVILEGE(); + portMEMORY_BARRIER(); - configASSERT( uxCriticalNesting ); - uxCriticalNesting--; + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } + + portMEMORY_BARRIER(); + + portRESET_PRIVILEGE(); + portMEMORY_BARRIER(); } - portMEMORY_BARRIER(); + else + { + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; - portRESET_PRIVILEGE(); - portMEMORY_BARRIER(); - } - else - { + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } + } + #else /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ configASSERT( uxCriticalNesting ); uxCriticalNesting--; @@ -549,16 +573,7 @@ void vPortExitCritical( void ) { portENABLE_INTERRUPTS(); } - } -#else - configASSERT( uxCriticalNesting ); - uxCriticalNesting--; - - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } -#endif + #endif /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ } /*-----------------------------------------------------------*/ @@ -710,7 +725,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress = ( ( uint32_t ) __SRAM_segment_start__ ) | /* Base address. */ ( portMPU_REGION_VALID ) | - ( portSTACK_REGION ); /* Region number. */ + ( portSTACK_REGION ); /* Region number. */ xMPUSettings->xRegion[ 0 ].ulRegionAttribute = ( portMPU_REGION_READ_WRITE ) | diff --git a/portable/IAR/ARM_CM7/r0p1/port.c b/portable/IAR/ARM_CM7/r0p1/port.c old mode 100644 new mode 100755 index e9e3805f05..9938f91cad --- a/portable/IAR/ARM_CM7/r0p1/port.c +++ b/portable/IAR/ARM_CM7/r0p1/port.c @@ -237,7 +237,8 @@ BaseType_t xPortStartScheduler( void ) #if ( configASSERT_DEFINED == 1 ) { volatile uint32_t ulOriginalPriority; - volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint32_t ulImplementedPrioBits = 0; + volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API @@ -268,20 +269,28 @@ BaseType_t xPortStartScheduler( void ) /* Calculate the maximum acceptable priority group value for the number * of bits read back. */ - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS; while( ( ucMaxPriorityValue & portTOP_BIT_OF_BYTE ) == portTOP_BIT_OF_BYTE ) { - ulMaxPRIGROUPValue--; + ulImplementedPrioBits++; ucMaxPriorityValue <<= ( uint8_t ) 0x01; } + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + #ifdef __NVIC_PRIO_BITS { /* Check the CMSIS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == __NVIC_PRIO_BITS ); + configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); } #endif @@ -290,7 +299,7 @@ BaseType_t xPortStartScheduler( void ) /* Check the FreeRTOS configuration that defines the number of * priority bits matches the number of priority bits actually queried * from the hardware. */ - configASSERT( ( portMAX_PRIGROUP_BITS - ulMaxPRIGROUPValue ) == configPRIO_BITS ); + configASSERT( ulImplementedPrioBits == configPRIO_BITS ); } #endif From dea93331b77ad9fe31a9169f50f17de43212fb76 Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Mon, 13 Mar 2023 12:19:41 +0000 Subject: [PATCH 09/21] Uncrustify changes --- portable/IAR/ARM_CM4F_MPU/port.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) mode change 100755 => 100644 portable/IAR/ARM_CM4F_MPU/port.c diff --git a/portable/IAR/ARM_CM4F_MPU/port.c b/portable/IAR/ARM_CM4F_MPU/port.c old mode 100755 new mode 100644 index c872335f64..a2ab3d8886 --- a/portable/IAR/ARM_CM4F_MPU/port.c +++ b/portable/IAR/ARM_CM4F_MPU/port.c @@ -517,7 +517,7 @@ void vPortEnterCritical( void ) configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 ); } } - #else /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ + #else /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ portDISABLE_INTERRUPTS(); uxCriticalNesting++; @@ -565,7 +565,7 @@ void vPortExitCritical( void ) portENABLE_INTERRUPTS(); } } - #else /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ + #else /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ configASSERT( uxCriticalNesting ); uxCriticalNesting--; From 5c24d9de312a6f7d69e9227fabb3c1eeddb26b87 Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Mon, 13 Mar 2023 12:24:12 +0000 Subject: [PATCH 10/21] Fix MikroC_ARM_CM4F port --- portable/MikroC/ARM_CM4F/port.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/portable/MikroC/ARM_CM4F/port.c b/portable/MikroC/ARM_CM4F/port.c index 1106e83a8e..f835c5ca57 100755 --- a/portable/MikroC/ARM_CM4F/port.c +++ b/portable/MikroC/ARM_CM4F/port.c @@ -298,7 +298,8 @@ BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; @@ -343,7 +344,7 @@ BaseType_t xPortStartScheduler( void ) } else { - ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; } #ifdef __NVIC_PRIO_BITS From d41460b493345eaa92ffa38ad68879e137f2980b Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Mon, 13 Mar 2023 12:25:08 +0000 Subject: [PATCH 11/21] Fix MikroC_ARM_CM4F port-(2) --- portable/MikroC/ARM_CM4F/port.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/portable/MikroC/ARM_CM4F/port.c b/portable/MikroC/ARM_CM4F/port.c index f835c5ca57..a0a9a789ff 100755 --- a/portable/MikroC/ARM_CM4F/port.c +++ b/portable/MikroC/ARM_CM4F/port.c @@ -300,7 +300,7 @@ BaseType_t xPortStartScheduler( void ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; - volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API From 41041926cf0929cc3fa13f811ebbfe9661e5e387 Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Mon, 13 Mar 2023 12:33:07 +0000 Subject: [PATCH 12/21] Fix RVDS ARM ports --- portable/RVDS/ARM_CM4F/port.c | 5 +- portable/RVDS/ARM_CM4_MPU/port.c | 101 +++++++++++++++--------------- portable/RVDS/ARM_CM7/r0p1/port.c | 5 +- 3 files changed, 58 insertions(+), 53 deletions(-) diff --git a/portable/RVDS/ARM_CM4F/port.c b/portable/RVDS/ARM_CM4F/port.c index 12f545c081..67810229e5 100755 --- a/portable/RVDS/ARM_CM4F/port.c +++ b/portable/RVDS/ARM_CM4F/port.c @@ -329,7 +329,8 @@ BaseType_t xPortStartScheduler( void ) #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; @@ -374,7 +375,7 @@ BaseType_t xPortStartScheduler( void ) } else { - ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; } #ifdef __NVIC_PRIO_BITS diff --git a/portable/RVDS/ARM_CM4_MPU/port.c b/portable/RVDS/ARM_CM4_MPU/port.c index f270ec8a6e..5e7aeab02c 100755 --- a/portable/RVDS/ARM_CM4_MPU/port.c +++ b/portable/RVDS/ARM_CM4_MPU/port.c @@ -201,7 +201,7 @@ void vResetPrivilege( void ); /** * @brief Enter critical section. */ -#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) +#if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) void vPortEnterCritical( void ) FREERTOS_SYSTEM_CALL; #else void vPortEnterCritical( void ) PRIVILEGED_FUNCTION; @@ -210,7 +210,7 @@ void vResetPrivilege( void ); /** * @brief Exit from critical section. */ -#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) +#if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) void vPortExitCritical( void ) FREERTOS_SYSTEM_CALL; #else void vPortExitCritical( void ) PRIVILEGED_FUNCTION; @@ -412,6 +412,7 @@ BaseType_t xPortStartScheduler( void ) #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) configASSERT( ( portCPUID == portCORTEX_M7_r0p1_ID ) || ( portCPUID == portCORTEX_M7_r0p0_ID ) ); #else + /* When using this port on a Cortex-M7 r0p0 or r0p1 core, define * configENABLE_ERRATA_837070_WORKAROUND to 1 in your * FreeRTOSConfig.h. */ @@ -421,7 +422,8 @@ BaseType_t xPortStartScheduler( void ) #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; @@ -466,7 +468,7 @@ BaseType_t xPortStartScheduler( void ) } else { - ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; } #ifdef __NVIC_PRIO_BITS @@ -567,53 +569,63 @@ void vPortEndScheduler( void ) void vPortEnterCritical( void ) { -#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) - if( portIS_PRIVILEGED() == pdFALSE ) - { - portRAISE_PRIVILEGE(); - portMEMORY_BARRIER(); + #if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) + if( portIS_PRIVILEGED() == pdFALSE ) + { + portRAISE_PRIVILEGE(); + portMEMORY_BARRIER(); - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; - portMEMORY_BARRIER(); + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + portMEMORY_BARRIER(); - portRESET_PRIVILEGE(); - portMEMORY_BARRIER(); - } - else - { + portRESET_PRIVILEGE(); + portMEMORY_BARRIER(); + } + else + { + portDISABLE_INTERRUPTS(); + uxCriticalNesting++; + } + #else /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ portDISABLE_INTERRUPTS(); uxCriticalNesting++; - } -#else - portDISABLE_INTERRUPTS(); - uxCriticalNesting++; -#endif + #endif /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ } /*-----------------------------------------------------------*/ void vPortExitCritical( void ) { -#if( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) - if( portIS_PRIVILEGED() == pdFALSE ) - { - portRAISE_PRIVILEGE(); - portMEMORY_BARRIER(); + #if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) + if( portIS_PRIVILEGED() == pdFALSE ) + { + portRAISE_PRIVILEGE(); + portMEMORY_BARRIER(); - configASSERT( uxCriticalNesting ); - uxCriticalNesting--; + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } + + portMEMORY_BARRIER(); + + portRESET_PRIVILEGE(); + portMEMORY_BARRIER(); } - portMEMORY_BARRIER(); + else + { + configASSERT( uxCriticalNesting ); + uxCriticalNesting--; - portRESET_PRIVILEGE(); - portMEMORY_BARRIER(); - } - else - { + if( uxCriticalNesting == 0 ) + { + portENABLE_INTERRUPTS(); + } + } + #else /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ configASSERT( uxCriticalNesting ); uxCriticalNesting--; @@ -621,16 +633,7 @@ void vPortExitCritical( void ) { portENABLE_INTERRUPTS(); } - } -#else - configASSERT( uxCriticalNesting ); - uxCriticalNesting--; - - if( uxCriticalNesting == 0 ) - { - portENABLE_INTERRUPTS(); - } -#endif + #endif /* if ( configALLOW_UNPRIVILEGED_CRITICAL_SECTIONS == 1 ) */ } /*-----------------------------------------------------------*/ @@ -918,7 +921,7 @@ void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings, xMPUSettings->xRegion[ 0 ].ulRegionBaseAddress = ( ( uint32_t ) __SRAM_segment_start__ ) | /* Base address. */ ( portMPU_REGION_VALID ) | - ( portSTACK_REGION ); /* Region number. */ + ( portSTACK_REGION ); /* Region number. */ xMPUSettings->xRegion[ 0 ].ulRegionAttribute = ( portMPU_REGION_READ_WRITE ) | diff --git a/portable/RVDS/ARM_CM7/r0p1/port.c b/portable/RVDS/ARM_CM7/r0p1/port.c index ae04395004..e5733b34be 100755 --- a/portable/RVDS/ARM_CM7/r0p1/port.c +++ b/portable/RVDS/ARM_CM7/r0p1/port.c @@ -313,7 +313,8 @@ BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; + volatile uint32_t ulOriginalPriority; + volatile uint32_t ulImplementedPrioBits = 0; volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; @@ -358,7 +359,7 @@ BaseType_t xPortStartScheduler( void ) } else { - ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; } #ifdef __NVIC_PRIO_BITS From e90f1481a8a2aefb5a59386518cedfa244ddaac4 Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Mon, 13 Mar 2023 12:35:54 +0000 Subject: [PATCH 13/21] Revert changes for Tasking/ARM_CM4F port --- portable/Tasking/ARM_CM4F/port.c | 81 +------------------------------- 1 file changed, 1 insertion(+), 80 deletions(-) diff --git a/portable/Tasking/ARM_CM4F/port.c b/portable/Tasking/ARM_CM4F/port.c index f6d161a54a..bd8da7d9bb 100755 --- a/portable/Tasking/ARM_CM4F/port.c +++ b/portable/Tasking/ARM_CM4F/port.c @@ -165,85 +165,6 @@ BaseType_t xPortStartScheduler( void ) * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ); - #if ( configASSERT_DEFINED == 1 ) - { - volatile uint32_t ulOriginalPriority , ulImplementedPrioBits = 0; - volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); - 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 = *pucFirstUserPriorityRegister; - - /* Determine the number of priority bits available. First write to all - * possible bits. */ - *pucFirstUserPriorityRegister = portMAX_8_BIT_VALUE; - - /* Read the value back to see how many bits stuck. */ - ucMaxPriorityValue = *pucFirstUserPriorityRegister; - - /* 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 ) - { - ulMaxPRIGROUPValue = 0; - } - else - { - ulMaxPRIGROUPValue = ulMAX_PRIGROUP_BITS - ulImplementedPrioBits; - } - - #ifdef __NVIC_PRIO_BITS - { - /* Check the CMSIS configuration that defines the number of - * priority bits matches the number of priority bits actually queried - * from the hardware. */ - configASSERT( ulImplementedPrioBits == __NVIC_PRIO_BITS ); - } - #endif - - #ifdef configPRIO_BITS - { - /* Check the FreeRTOS configuration that defines the number of - * priority bits matches the number of priority bits actually queried - * from the hardware. */ - configASSERT( ulImplementedPrioBits == configPRIO_BITS ); - } - #endif - - /* 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. */ - *pucFirstUserPriorityRegister = ulOriginalPriority; - } - #endif /* configASSERT_DEFINED */ - /* Make PendSV and SysTick the lowest priority interrupts. */ *( portNVIC_SHPR3_REG ) |= portNVIC_PENDSV_PRI; *( portNVIC_SHPR3_REG ) |= portNVIC_SYSTICK_PRI; @@ -346,4 +267,4 @@ void prvSetupTimerInterrupt( void ) *( portNVIC_SYSTICK_LOAD ) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; *( portNVIC_SYSTICK_CTRL ) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; } -/*-----------------------------------------------------------*/ +/*-----------------------------------------------------------*/ \ No newline at end of file From 35a1c368ae6fb8bb2053854d712e85ed724670fb Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Mon, 13 Mar 2023 12:36:49 +0000 Subject: [PATCH 14/21] Revert changes for Tasking/ARM_CM4F port-(2) --- portable/Tasking/ARM_CM4F/port.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/portable/Tasking/ARM_CM4F/port.c b/portable/Tasking/ARM_CM4F/port.c index bd8da7d9bb..4ba5da739d 100755 --- a/portable/Tasking/ARM_CM4F/port.c +++ b/portable/Tasking/ARM_CM4F/port.c @@ -266,5 +266,4 @@ void prvSetupTimerInterrupt( void ) /* Configure SysTick to interrupt at the requested rate. */ *( portNVIC_SYSTICK_LOAD ) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; *( portNVIC_SYSTICK_CTRL ) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; -} -/*-----------------------------------------------------------*/ \ No newline at end of file +} \ No newline at end of file From 8f572fdc5874fc17bdb93a78277bc6b26c8e9b53 Mon Sep 17 00:00:00 2001 From: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> Date: Sat, 18 Mar 2023 10:06:23 +0530 Subject: [PATCH 15/21] Update port.c Fix GCC/ARM_CM4F port --- portable/GCC/ARM_CM4F/port.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/portable/GCC/ARM_CM4F/port.c b/portable/GCC/ARM_CM4F/port.c index 93febf1ed2..3cf01f4eae 100755 --- a/portable/GCC/ARM_CM4F/port.c +++ b/portable/GCC/ARM_CM4F/port.c @@ -343,6 +343,15 @@ BaseType_t xPortStartScheduler( void ) ulImplementedPrioBits++; ucMaxPriorityValue <<= ( uint8_t ) 0x01; } + + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } #ifdef __NVIC_PRIO_BITS { @@ -841,4 +850,4 @@ static void vPortEnableVFP( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* configASSERT_DEFINED */ \ No newline at end of file +#endif /* configASSERT_DEFINED */ From 60e9006b0e26500fb8c6c15d24df9158143e0334 Mon Sep 17 00:00:00 2001 From: kar-rahul-aws <118818625+kar-rahul-aws@users.noreply.github.com> Date: Sat, 18 Mar 2023 10:24:21 +0530 Subject: [PATCH 16/21] Update port.c --- portable/GCC/ARM_CM4F/port.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/portable/GCC/ARM_CM4F/port.c b/portable/GCC/ARM_CM4F/port.c index 3cf01f4eae..f4d6e5d4d9 100755 --- a/portable/GCC/ARM_CM4F/port.c +++ b/portable/GCC/ARM_CM4F/port.c @@ -346,11 +346,11 @@ BaseType_t xPortStartScheduler( void ) if( ulImplementedPrioBits == 8 ) { - ulMaxPRIGROUPValue = 0; + ulMaxPRIGROUPValue = 0; } else { - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS-ulImplementedPrioBits; } #ifdef __NVIC_PRIO_BITS From 5143ed1c54a4ee2a96bef7de3557c186ae7a8b3f Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Sat, 18 Mar 2023 05:47:29 +0000 Subject: [PATCH 17/21] update GCC\ARM_CM4F port --- portable/GCC/ARM_CM4F/port.c | 49 +++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 20 deletions(-) mode change 100755 => 100644 portable/GCC/ARM_CM4F/port.c diff --git a/portable/GCC/ARM_CM4F/port.c b/portable/GCC/ARM_CM4F/port.c old mode 100755 new mode 100644 index 93febf1ed2..a9173b8d51 --- a/portable/GCC/ARM_CM4F/port.c +++ b/portable/GCC/ARM_CM4F/port.c @@ -251,11 +251,11 @@ static void prvTaskExitError( void ) void vPortSVCHandler( void ) { __asm volatile ( - " ldr r3, pxCurrentTCBConst2 \n"/* Restore the context. */ - " ldr r1, [r3] \n"/* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ - " ldr r0, [r1] \n"/* The first item in pxCurrentTCB is the task top of stack. */ - " ldmia r0!, {r4-r11, r14} \n"/* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ - " msr psp, r0 \n"/* Restore the task stack pointer. */ + " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ + " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ + " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ + " ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ + " msr psp, r0 \n" /* Restore the task stack pointer. */ " isb \n" " mov r0, #0 \n" " msr basepri, r0 \n" @@ -274,17 +274,17 @@ static void prvPortStartFirstTask( void ) * would otherwise result in the unnecessary leaving of space in the SVC stack * for lazy saving of FPU registers. */ __asm volatile ( - " ldr r0, =0xE000ED08 \n"/* Use the NVIC offset register to locate the stack. */ + " ldr r0, =0xE000ED08 \n" /* Use the NVIC offset register to locate the stack. */ " ldr r0, [r0] \n" " ldr r0, [r0] \n" - " msr msp, r0 \n"/* Set the msp back to the start of the stack. */ - " mov r0, #0 \n"/* Clear the bit that indicates the FPU is in use, see comment above. */ + " msr msp, r0 \n" /* Set the msp back to the start of the stack. */ + " mov r0, #0 \n" /* Clear the bit that indicates the FPU is in use, see comment above. */ " msr control, r0 \n" - " cpsie i \n"/* Globally enable interrupts. */ + " cpsie i \n" /* Globally enable interrupts. */ " cpsie f \n" " dsb \n" " isb \n" - " svc 0 \n"/* System call to start first task. */ + " svc 0 \n" /* System call to start first task. */ " nop \n" " .ltorg \n" ); @@ -344,6 +344,15 @@ BaseType_t xPortStartScheduler( void ) ucMaxPriorityValue <<= ( uint8_t ) 0x01; } + if( ulImplementedPrioBits == 8 ) + { + ulMaxPRIGROUPValue = 0; + } + else + { + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; + } + #ifdef __NVIC_PRIO_BITS { /* Check the CMSIS configuration that defines the number of @@ -453,15 +462,15 @@ void xPortPendSVHandler( void ) " mrs r0, psp \n" " isb \n" " \n" - " ldr r3, pxCurrentTCBConst \n"/* Get the location of the current TCB. */ + " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ " ldr r2, [r3] \n" " \n" - " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, push high vfp registers. */ + " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */ " it eq \n" " vstmdbeq r0!, {s16-s31} \n" " \n" - " stmdb r0!, {r4-r11, r14} \n"/* Save the core registers. */ - " str r0, [r2] \n"/* Save the new top of stack into the first member of the TCB. */ + " stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */ + " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ " \n" " stmdb sp!, {r0, r3} \n" " mov r0, %0 \n" @@ -473,12 +482,12 @@ void xPortPendSVHandler( void ) " msr basepri, r0 \n" " ldmia sp!, {r0, r3} \n" " \n" - " ldr r1, [r3] \n"/* The first item in pxCurrentTCB is the task top of stack. */ + " ldr r1, [r3] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n" " \n" - " ldmia r0!, {r4-r11, r14} \n"/* Pop the core registers. */ + " ldmia r0!, {r4-r11, r14} \n" /* Pop the core registers. */ " \n" - " tst r14, #0x10 \n"/* Is the task using the FPU context? If so, pop the high vfp registers too. */ + " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, pop the high vfp registers too. */ " it eq \n" " vldmiaeq r0!, {s16-s31} \n" " \n" @@ -772,10 +781,10 @@ static void vPortEnableVFP( void ) { __asm volatile ( - " ldr.w r0, =0xE000ED88 \n"/* The FPU enable bits are in the CPACR. */ + " ldr.w r0, =0xE000ED88 \n" /* The FPU enable bits are in the CPACR. */ " ldr r1, [r0] \n" " \n" - " orr r1, r1, #( 0xf << 20 ) \n"/* Enable CP10 and CP11 coprocessors, then save back. */ + " orr r1, r1, #( 0xf << 20 ) \n" /* Enable CP10 and CP11 coprocessors, then save back. */ " str r1, [r0] \n" " bx r14 \n" " .ltorg \n" @@ -841,4 +850,4 @@ static void vPortEnableVFP( void ) configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); } -#endif /* configASSERT_DEFINED */ \ No newline at end of file +#endif /* configASSERT_DEFINED */ From 0b7d65f1e67facc943cd53611dc6b411ce7a9a52 Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Sat, 18 Mar 2023 05:55:15 +0000 Subject: [PATCH 18/21] update port.c --- portable/GCC/ARM_CM4F/port.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/portable/GCC/ARM_CM4F/port.c b/portable/GCC/ARM_CM4F/port.c index 5449b20866..a3e6d4efb7 100644 --- a/portable/GCC/ARM_CM4F/port.c +++ b/portable/GCC/ARM_CM4F/port.c @@ -343,14 +343,14 @@ BaseType_t xPortStartScheduler( void ) ulImplementedPrioBits++; ucMaxPriorityValue <<= ( uint8_t ) 0x01; } - + if( ulImplementedPrioBits == 8 ) { ulMaxPRIGROUPValue = 0; } else { - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS-ulImplementedPrioBits; + ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; } if( ulImplementedPrioBits == 8 ) From b52734bdd0b4a9a8efbbb39cd57e827cefacb3b6 Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Mon, 20 Mar 2023 18:22:23 +0000 Subject: [PATCH 19/21] Assert to check configMAX_SYSCALL_INTERRUPT_PRIORITY is set to higher priority --- portable/CCS/ARM_CM3/port.c | 18 ++++++++++++++++++ portable/CCS/ARM_CM4F/port.c | 18 ++++++++++++++++++ portable/GCC/ARM_CM3/port.c | 18 ++++++++++++++++++ portable/GCC/ARM_CM3_MPU/port.c | 18 ++++++++++++++++++ portable/GCC/ARM_CM4F/port.c | 18 ++++++++++++++++++ portable/GCC/ARM_CM4_MPU/port.c | 18 ++++++++++++++++++ portable/GCC/ARM_CM7/r0p1/port.c | 18 ++++++++++++++++++ portable/IAR/ARM_CM3/port.c | 18 ++++++++++++++++++ portable/IAR/ARM_CM4F/port.c | 18 ++++++++++++++++++ portable/IAR/ARM_CM4F_MPU/port.c | 18 ++++++++++++++++++ portable/IAR/ARM_CM7/r0p1/port.c | 18 ++++++++++++++++++ portable/MikroC/ARM_CM4F/port.c | 18 ++++++++++++++++++ portable/RVDS/ARM_CM3/port.c | 18 ++++++++++++++++++ portable/RVDS/ARM_CM4F/port.c | 18 ++++++++++++++++++ portable/RVDS/ARM_CM4_MPU/port.c | 18 ++++++++++++++++++ portable/RVDS/ARM_CM7/r0p1/port.c | 18 ++++++++++++++++++ 16 files changed, 288 insertions(+) mode change 100644 => 100755 portable/CCS/ARM_CM3/port.c mode change 100644 => 100755 portable/CCS/ARM_CM4F/port.c mode change 100644 => 100755 portable/GCC/ARM_CM4F/port.c mode change 100644 => 100755 portable/IAR/ARM_CM4F_MPU/port.c diff --git a/portable/CCS/ARM_CM3/port.c b/portable/CCS/ARM_CM3/port.c old mode 100644 new mode 100755 index 8a0cceaa23..63dc600a75 --- a/portable/CCS/ARM_CM3/port.c +++ b/portable/CCS/ARM_CM3/port.c @@ -260,6 +260,24 @@ BaseType_t xPortStartScheduler( void ) 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 diff --git a/portable/CCS/ARM_CM4F/port.c b/portable/CCS/ARM_CM4F/port.c old mode 100644 new mode 100755 index 3f5b0a40a4..a741b09156 --- a/portable/CCS/ARM_CM4F/port.c +++ b/portable/CCS/ARM_CM4F/port.c @@ -279,6 +279,24 @@ BaseType_t xPortStartScheduler( void ) 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 diff --git a/portable/GCC/ARM_CM3/port.c b/portable/GCC/ARM_CM3/port.c index 4fc608888f..57337e6050 100755 --- a/portable/GCC/ARM_CM3/port.c +++ b/portable/GCC/ARM_CM3/port.c @@ -303,6 +303,24 @@ BaseType_t xPortStartScheduler( void ) 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 diff --git a/portable/GCC/ARM_CM3_MPU/port.c b/portable/GCC/ARM_CM3_MPU/port.c index be7aa9f62f..4b21236e78 100755 --- a/portable/GCC/ARM_CM3_MPU/port.c +++ b/portable/GCC/ARM_CM3_MPU/port.c @@ -426,6 +426,24 @@ BaseType_t xPortStartScheduler( void ) 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 diff --git a/portable/GCC/ARM_CM4F/port.c b/portable/GCC/ARM_CM4F/port.c old mode 100644 new mode 100755 index a3e6d4efb7..e6befca350 --- a/portable/GCC/ARM_CM4F/port.c +++ b/portable/GCC/ARM_CM4F/port.c @@ -346,6 +346,24 @@ BaseType_t xPortStartScheduler( void ) 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 diff --git a/portable/GCC/ARM_CM4_MPU/port.c b/portable/GCC/ARM_CM4_MPU/port.c index bf252cf51e..682b64ea8c 100755 --- a/portable/GCC/ARM_CM4_MPU/port.c +++ b/portable/GCC/ARM_CM4_MPU/port.c @@ -469,6 +469,24 @@ BaseType_t xPortStartScheduler( void ) 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 diff --git a/portable/GCC/ARM_CM7/r0p1/port.c b/portable/GCC/ARM_CM7/r0p1/port.c index 2ea8e312d5..8e1a02302d 100755 --- a/portable/GCC/ARM_CM7/r0p1/port.c +++ b/portable/GCC/ARM_CM7/r0p1/port.c @@ -334,6 +334,24 @@ BaseType_t xPortStartScheduler( void ) 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 diff --git a/portable/IAR/ARM_CM3/port.c b/portable/IAR/ARM_CM3/port.c index 20dfdbd76d..a6fc5f2ee8 100755 --- a/portable/IAR/ARM_CM3/port.c +++ b/portable/IAR/ARM_CM3/port.c @@ -252,6 +252,24 @@ BaseType_t xPortStartScheduler( void ) 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 diff --git a/portable/IAR/ARM_CM4F/port.c b/portable/IAR/ARM_CM4F/port.c index b236f47f78..d3c938319e 100755 --- a/portable/IAR/ARM_CM4F/port.c +++ b/portable/IAR/ARM_CM4F/port.c @@ -290,6 +290,24 @@ BaseType_t xPortStartScheduler( void ) 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 diff --git a/portable/IAR/ARM_CM4F_MPU/port.c b/portable/IAR/ARM_CM4F_MPU/port.c old mode 100644 new mode 100755 index a2ab3d8886..2b888011c1 --- a/portable/IAR/ARM_CM4F_MPU/port.c +++ b/portable/IAR/ARM_CM4F_MPU/port.c @@ -404,6 +404,24 @@ BaseType_t xPortStartScheduler( void ) 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 diff --git a/portable/IAR/ARM_CM7/r0p1/port.c b/portable/IAR/ARM_CM7/r0p1/port.c index 9938f91cad..0a50859adb 100755 --- a/portable/IAR/ARM_CM7/r0p1/port.c +++ b/portable/IAR/ARM_CM7/r0p1/port.c @@ -278,6 +278,24 @@ BaseType_t xPortStartScheduler( void ) 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 diff --git a/portable/MikroC/ARM_CM4F/port.c b/portable/MikroC/ARM_CM4F/port.c index a0a9a789ff..8e314b6709 100755 --- a/portable/MikroC/ARM_CM4F/port.c +++ b/portable/MikroC/ARM_CM4F/port.c @@ -340,6 +340,24 @@ BaseType_t xPortStartScheduler( void ) 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 diff --git a/portable/RVDS/ARM_CM3/port.c b/portable/RVDS/ARM_CM3/port.c index 19dcbe6d2b..e1bfc6afcc 100755 --- a/portable/RVDS/ARM_CM3/port.c +++ b/portable/RVDS/ARM_CM3/port.c @@ -305,6 +305,24 @@ BaseType_t xPortStartScheduler( void ) 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 diff --git a/portable/RVDS/ARM_CM4F/port.c b/portable/RVDS/ARM_CM4F/port.c index 67810229e5..5233533c0c 100755 --- a/portable/RVDS/ARM_CM4F/port.c +++ b/portable/RVDS/ARM_CM4F/port.c @@ -371,6 +371,24 @@ BaseType_t xPortStartScheduler( void ) 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 diff --git a/portable/RVDS/ARM_CM4_MPU/port.c b/portable/RVDS/ARM_CM4_MPU/port.c index 5e7aeab02c..d9978a913f 100755 --- a/portable/RVDS/ARM_CM4_MPU/port.c +++ b/portable/RVDS/ARM_CM4_MPU/port.c @@ -464,6 +464,24 @@ BaseType_t xPortStartScheduler( void ) 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 diff --git a/portable/RVDS/ARM_CM7/r0p1/port.c b/portable/RVDS/ARM_CM7/r0p1/port.c index e5733b34be..ee456d87a9 100755 --- a/portable/RVDS/ARM_CM7/r0p1/port.c +++ b/portable/RVDS/ARM_CM7/r0p1/port.c @@ -355,6 +355,24 @@ BaseType_t xPortStartScheduler( void ) 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 From bdb67f57ea252a0bb60e337b444e43cc1360c55b Mon Sep 17 00:00:00 2001 From: kar-rahul-aws Date: Tue, 21 Mar 2023 02:20:35 +0000 Subject: [PATCH 20/21] Fix merge error: remove duplicate code --- portable/GCC/ARM_CM4F/port.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/portable/GCC/ARM_CM4F/port.c b/portable/GCC/ARM_CM4F/port.c index e6befca350..84e7913048 100755 --- a/portable/GCC/ARM_CM4F/port.c +++ b/portable/GCC/ARM_CM4F/port.c @@ -371,15 +371,6 @@ BaseType_t xPortStartScheduler( void ) ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; } - if( ulImplementedPrioBits == 8 ) - { - ulMaxPRIGROUPValue = 0; - } - else - { - ulMaxPRIGROUPValue = portMAX_PRIGROUP_BITS - ulImplementedPrioBits; - } - #ifdef __NVIC_PRIO_BITS { /* Check the CMSIS configuration that defines the number of From 79739e5865713ee1f3acb58579434dcbf542b0dd Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 21 Mar 2023 17:07:07 +0000 Subject: [PATCH 21/21] Fix typos --- portable/GCC/ARM_CM7/r0p1/port.c | 2 +- portable/IAR/ARM_CM3/port.c | 2 +- portable/IAR/ARM_CM4F/port.c | 2 +- portable/IAR/ARM_CM4F_MPU/port.c | 2 +- portable/IAR/ARM_CM7/r0p1/port.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/portable/GCC/ARM_CM7/r0p1/port.c b/portable/GCC/ARM_CM7/r0p1/port.c index 8e1a02302d..25a06bf46e 100755 --- a/portable/GCC/ARM_CM7/r0p1/port.c +++ b/portable/GCC/ARM_CM7/r0p1/port.c @@ -292,7 +292,7 @@ BaseType_t xPortStartScheduler( void ) { #if ( configASSERT_DEFINED == 1 ) { - volatile uint32_t ulOriginalPriority, + volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; diff --git a/portable/IAR/ARM_CM3/port.c b/portable/IAR/ARM_CM3/port.c index a6fc5f2ee8..a7a5ad86bd 100755 --- a/portable/IAR/ARM_CM3/port.c +++ b/portable/IAR/ARM_CM3/port.c @@ -212,7 +212,7 @@ BaseType_t xPortStartScheduler( void ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; - volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API diff --git a/portable/IAR/ARM_CM4F/port.c b/portable/IAR/ARM_CM4F/port.c index d3c938319e..9b4ed52fae 100755 --- a/portable/IAR/ARM_CM4F/port.c +++ b/portable/IAR/ARM_CM4F/port.c @@ -250,7 +250,7 @@ BaseType_t xPortStartScheduler( void ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; - volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API diff --git a/portable/IAR/ARM_CM4F_MPU/port.c b/portable/IAR/ARM_CM4F_MPU/port.c index 2b888011c1..6aec5b3426 100755 --- a/portable/IAR/ARM_CM4F_MPU/port.c +++ b/portable/IAR/ARM_CM4F_MPU/port.c @@ -364,7 +364,7 @@ BaseType_t xPortStartScheduler( void ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; - volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API diff --git a/portable/IAR/ARM_CM7/r0p1/port.c b/portable/IAR/ARM_CM7/r0p1/port.c index 0a50859adb..1c53fa94e2 100755 --- a/portable/IAR/ARM_CM7/r0p1/port.c +++ b/portable/IAR/ARM_CM7/r0p1/port.c @@ -238,7 +238,7 @@ BaseType_t xPortStartScheduler( void ) { volatile uint32_t ulOriginalPriority; volatile uint32_t ulImplementedPrioBits = 0; - volatile uint8_t * const pucFirstUserPriorityRegister = ( uint8_t * ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); + volatile uint8_t * const pucFirstUserPriorityRegister = ( volatile uint8_t * const ) ( portNVIC_IP_REGISTERS_OFFSET_16 + portFIRST_USER_INTERRUPT_NUMBER ); volatile uint8_t ucMaxPriorityValue; /* Determine the maximum priority from which ISR safe FreeRTOS API