From 2dfdfc4ba4d8bb487c8ea6b5428d7d742ce162b8 Mon Sep 17 00:00:00 2001 From: Paul Bartell Date: Wed, 29 Jun 2022 22:05:26 -0700 Subject: [PATCH] Add Cortex M7 r0p1 Errata 837070 workaround to CM4_MPU ports (#513) * Clarify Cortex M7 r0p1 errata number in r0p1 specific port. * Add ARM Cortex M7 r0p0 / r0p1 Errata 837070 workaround to CM4 MPU ports. Optionally, enable the errata workaround by defining configTARGET_ARM_CM7_r0p0 or configTARGET_ARM_CM7_r0p1 in FreeRTOSConfig.h. * Add r0p1 errata support to IAR port as well Signed-off-by: Gaurav Aggarwal * Change macro name to configENABLE_ERRATA_837070_WORKAROUND Signed-off-by: Gaurav Aggarwal Co-authored-by: Gaurav Aggarwal --- portable/GCC/ARM_CM4_MPU/port.c | 24 +++++++++++++++++++++ portable/GCC/ARM_CM4_MPU/portmacro.h | 31 +++++++++++++++++++-------- portable/GCC/ARM_CM7/r0p1/port.c | 4 ++-- portable/IAR/ARM_CM4F_MPU/port.c | 20 +++++++++++------ portable/IAR/ARM_CM4F_MPU/portasm.s | 6 ++++++ portable/IAR/ARM_CM4F_MPU/portmacro.h | 24 +++++++++++++++------ portable/RVDS/ARM_CM4_MPU/port.c | 24 +++++++++++++++++++++ portable/RVDS/ARM_CM4_MPU/portmacro.h | 13 +++++++++++ 8 files changed, 122 insertions(+), 24 deletions(-) diff --git a/portable/GCC/ARM_CM4_MPU/port.c b/portable/GCC/ARM_CM4_MPU/port.c index a10d9b97b..ecffbfe00 100644 --- a/portable/GCC/ARM_CM4_MPU/port.c +++ b/portable/GCC/ARM_CM4_MPU/port.c @@ -70,6 +70,12 @@ #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 ) ) @@ -410,6 +416,18 @@ BaseType_t xPortStartScheduler( void ) * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ configASSERT( ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) ); + /* 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; @@ -587,9 +605,15 @@ void xPortPendSVHandler( void ) " \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" diff --git a/portable/GCC/ARM_CM4_MPU/portmacro.h b/portable/GCC/ARM_CM4_MPU/portmacro.h index d77522b9e..cef1b04be 100644 --- a/portable/GCC/ARM_CM4_MPU/portmacro.h +++ b/portable/GCC/ARM_CM4_MPU/portmacro.h @@ -71,6 +71,7 @@ typedef unsigned long UBaseType_t; * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #endif + /*-----------------------------------------------------------*/ /* MPU specific constants. */ @@ -346,10 +347,16 @@ portFORCE_INLINE static void vPortRaiseBASEPRI( void ) __asm volatile ( - " mov %0, %1 \n"\ - " msr basepri, %0 \n"\ - " isb \n"\ - " dsb \n"\ + " mov %0, %1 \n" + #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) + " cpsid i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ + #endif + " msr basepri, %0 \n" + " isb \n" + " dsb \n" + #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) + " cpsie i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ + #endif : "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" ); } @@ -362,11 +369,17 @@ portFORCE_INLINE static uint32_t ulPortRaiseBASEPRI( void ) __asm volatile ( - " mrs %0, basepri \n"\ - " mov %1, %2 \n"\ - " msr basepri, %1 \n"\ - " isb \n"\ - " dsb \n"\ + " mrs %0, basepri \n" + " mov %1, %2 \n" + #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) + " cpsid i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ + #endif + " msr basepri, %1 \n" + " isb \n" + " dsb \n" + #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) + " cpsie i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ + #endif : "=r" ( ulOriginalBASEPRI ), "=r" ( ulNewBASEPRI ) : "i" ( configMAX_SYSCALL_INTERRUPT_PRIORITY ) : "memory" ); diff --git a/portable/GCC/ARM_CM7/r0p1/port.c b/portable/GCC/ARM_CM7/r0p1/port.c index df36423a3..130e1878d 100644 --- a/portable/GCC/ARM_CM7/r0p1/port.c +++ b/portable/GCC/ARM_CM7/r0p1/port.c @@ -445,11 +445,11 @@ void xPortPendSVHandler( void ) " \n" " stmdb sp!, {r0, r3} \n" " mov r0, %0 \n" - " cpsid i \n"/* Errata workaround. */ + " cpsid i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ " msr basepri, r0 \n" " dsb \n" " isb \n" - " cpsie i \n"/* Errata workaround. */ + " cpsie i \n"/* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ " bl vTaskSwitchContext \n" " mov r0, #0 \n" " msr basepri, r0 \n" diff --git a/portable/IAR/ARM_CM4F_MPU/port.c b/portable/IAR/ARM_CM4F_MPU/port.c index 5e8c723da..c9a254131 100644 --- a/portable/IAR/ARM_CM4F_MPU/port.c +++ b/portable/IAR/ARM_CM4F_MPU/port.c @@ -98,8 +98,8 @@ #define portNVIC_PENDSVCLEAR_BIT ( 1UL << 27UL ) #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. */ +/* 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 ) @@ -350,11 +350,17 @@ BaseType_t xPortStartScheduler( void ) * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY ); - /* 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 ) { diff --git a/portable/IAR/ARM_CM4F_MPU/portasm.s b/portable/IAR/ARM_CM4F_MPU/portasm.s index 1ea6fdae7..f37912b02 100644 --- a/portable/IAR/ARM_CM4F_MPU/portasm.s +++ b/portable/IAR/ARM_CM4F_MPU/portasm.s @@ -70,9 +70,15 @@ xPortPendSVHandler: stmdb sp!, {r0, r3} mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY + #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) + cpsid i /* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ + #endif msr basepri, r0 dsb isb + #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) + cpsie i /* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ + #endif bl vTaskSwitchContext mov r0, #0 msr basepri, r0 diff --git a/portable/IAR/ARM_CM4F_MPU/portmacro.h b/portable/IAR/ARM_CM4F_MPU/portmacro.h index ea7ecdd5d..659fb13ea 100644 --- a/portable/IAR/ARM_CM4F_MPU/portmacro.h +++ b/portable/IAR/ARM_CM4F_MPU/portmacro.h @@ -73,6 +73,7 @@ typedef unsigned long UBaseType_t; * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #endif + /*-----------------------------------------------------------*/ /* MPU specific constants. */ @@ -253,12 +254,23 @@ typedef struct MPU_SETTINGS extern void vPortEnterCritical( void ); extern void vPortExitCritical( void ); -#define portDISABLE_INTERRUPTS() \ - { \ - __set_BASEPRI( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \ - __DSB(); \ - __ISB(); \ - } +#if( configENABLE_ERRATA_837070_WORKAROUND == 1 ) + #define portDISABLE_INTERRUPTS() \ + { \ + __disable_interrupt(); \ + __set_BASEPRI( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \ + __DSB(); \ + __ISB(); \ + __enable_interrupt(); \ + } +#else + #define portDISABLE_INTERRUPTS() \ + { \ + __set_BASEPRI( configMAX_SYSCALL_INTERRUPT_PRIORITY ); \ + __DSB(); \ + __ISB(); \ + } +#endif #define portENABLE_INTERRUPTS() __set_BASEPRI( 0 ) #define portENTER_CRITICAL() vPortEnterCritical() diff --git a/portable/RVDS/ARM_CM4_MPU/port.c b/portable/RVDS/ARM_CM4_MPU/port.c index 4d3c4a440..46fe89d43 100644 --- a/portable/RVDS/ARM_CM4_MPU/port.c +++ b/portable/RVDS/ARM_CM4_MPU/port.c @@ -59,6 +59,12 @@ #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 ) ) @@ -400,6 +406,18 @@ BaseType_t xPortStartScheduler( void ) * See https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ configASSERT( configMAX_SYSCALL_INTERRUPT_PRIORITY ); + /* 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; @@ -591,9 +609,15 @@ __asm void xPortPendSVHandler( void ) stmdb sp !, { r0, r3 } mov r0, # configMAX_SYSCALL_INTERRUPT_PRIORITY + #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) + cpsid i /* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ + #endif msr basepri, r0 dsb isb + #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) + cpsie i /* ARM Cortex-M7 r0p1 Errata 837070 workaround. */ + #endif bl vTaskSwitchContext mov r0, #0 msr basepri, r0 diff --git a/portable/RVDS/ARM_CM4_MPU/portmacro.h b/portable/RVDS/ARM_CM4_MPU/portmacro.h index 4e0ad0aeb..7c3d7b562 100644 --- a/portable/RVDS/ARM_CM4_MPU/portmacro.h +++ b/portable/RVDS/ARM_CM4_MPU/portmacro.h @@ -70,6 +70,7 @@ typedef unsigned long UBaseType_t; * not need to be guarded with a critical section. */ #define portTICK_TYPE_IS_ATOMIC 1 #endif + /*-----------------------------------------------------------*/ /* MPU specific constants. */ @@ -334,9 +335,15 @@ static portFORCE_INLINE void vPortRaiseBASEPRI( void ) /* Set BASEPRI to the max syscall priority to effect a critical * section. */ /* *INDENT-OFF* */ + #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) + cpsid i + #endif msr basepri, ulNewBASEPRI dsb isb + #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) + cpsie i + #endif /* *INDENT-ON* */ } } @@ -366,9 +373,15 @@ static portFORCE_INLINE uint32_t ulPortRaiseBASEPRI( void ) * section. */ /* *INDENT-OFF* */ mrs ulReturn, basepri + #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) + cpsid i + #endif msr basepri, ulNewBASEPRI dsb isb + #if ( configENABLE_ERRATA_837070_WORKAROUND == 1 ) + cpsie i + #endif /* *INDENT-ON* */ }