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 <aggarg@amazon.com>

* Change macro name to configENABLE_ERRATA_837070_WORKAROUND

Signed-off-by: Gaurav Aggarwal <aggarg@amazon.com>

Co-authored-by: Gaurav Aggarwal <aggarg@amazon.com>
diff --git a/portable/GCC/ARM_CM4_MPU/port.c b/portable/GCC/ARM_CM4_MPU/port.c
index a10d9b9..ecffbfe 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 @@
      * 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 @@
         "										\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 d77522b..cef1b04 100644
--- a/portable/GCC/ARM_CM4_MPU/portmacro.h
+++ b/portable/GCC/ARM_CM4_MPU/portmacro.h
@@ -71,6 +71,7 @@
  * not need to be guarded with a critical section. */

     #define portTICK_TYPE_IS_ATOMIC    1

 #endif

+

 /*-----------------------------------------------------------*/

 

 /* MPU specific constants. */

@@ -346,10 +347,16 @@
 

     __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 @@
 

     __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 df36423..130e187 100644
--- a/portable/GCC/ARM_CM7/r0p1/port.c
+++ b/portable/GCC/ARM_CM7/r0p1/port.c
@@ -445,11 +445,11 @@
         "										\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 5e8c723..c9a2541 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 @@
      * 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 1ea6fda..f37912b 100644
--- a/portable/IAR/ARM_CM4F_MPU/portasm.s
+++ b/portable/IAR/ARM_CM4F_MPU/portasm.s
@@ -70,9 +70,15 @@
 

 	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 ea7ecdd..659fb13 100644
--- a/portable/IAR/ARM_CM4F_MPU/portmacro.h
+++ b/portable/IAR/ARM_CM4F_MPU/portmacro.h
@@ -73,6 +73,7 @@
  * not need to be guarded with a critical section. */

     #define portTICK_TYPE_IS_ATOMIC    1

 #endif

+

 /*-----------------------------------------------------------*/

 

 /* MPU specific constants. */

@@ -253,12 +254,23 @@
 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 4d3c4a4..46fe89d 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 @@
      * 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 @@
 

     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 4e0ad0a..7c3d7b5 100644
--- a/portable/RVDS/ARM_CM4_MPU/portmacro.h
+++ b/portable/RVDS/ARM_CM4_MPU/portmacro.h
@@ -70,6 +70,7 @@
  * not need to be guarded with a critical section. */

     #define portTICK_TYPE_IS_ATOMIC    1

 #endif

+

 /*-----------------------------------------------------------*/

 

 /* MPU specific constants. */

@@ -334,9 +335,15 @@
         /* 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 @@
          * 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* */

     }