From 14d2a053ab9f6a29631b9e9c8d25d6519f63cc1f Mon Sep 17 00:00:00 2001 From: rtel Date: Mon, 27 Jun 2016 13:13:05 +0000 Subject: [PATCH] Improvements to the Cortex-M ports: - Clear the SysTick current value register before starting the SysTick (only required if something uses SysTick before starting the scheduler). - Ensure atomic operations are thread safe by executing clrex in the context switch. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2465 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- FreeRTOS/Source/include/FreeRTOS.h | 8 ++--- FreeRTOS/Source/portable/CCS/ARM_CM4F/port.c | 4 +++ .../Source/portable/CCS/ARM_CM4F/portasm.asm | 3 ++ FreeRTOS/Source/portable/GCC/ARM_CM0/port.c | 13 +++++--- FreeRTOS/Source/portable/GCC/ARM_CM3/port.c | 5 +++ .../Source/portable/GCC/ARM_CM3_MPU/port.c | 6 ++++ FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c | 6 +++- .../Source/portable/GCC/ARM_CM4_MPU/port.c | 12 +++++-- .../Source/portable/GCC/ARM_CM7/r0p1/port.c | 6 +++- FreeRTOS/Source/portable/IAR/ARM_CM0/port.c | 9 +++-- FreeRTOS/Source/portable/IAR/ARM_CM3/port.c | 4 +++ .../Source/portable/IAR/ARM_CM3/portasm.s | 1 + FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c | 4 +++ .../Source/portable/IAR/ARM_CM4F/portasm.s | 3 ++ .../Source/portable/IAR/ARM_CM7/r0p1/port.c | 4 +++ .../portable/IAR/ARM_CM7/r0p1/portasm.s | 3 ++ .../Source/portable/MikroC/ARM_CM4F/port.c | 33 +++++++++++-------- FreeRTOS/Source/portable/RVDS/ARM_CM0/port.c | 9 +++-- FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c | 5 +++ FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c | 9 ++++- .../Source/portable/RVDS/ARM_CM4_MPU/port.c | 20 +++++++---- .../Source/portable/RVDS/ARM_CM7/r0p1/port.c | 7 ++++ FreeRTOS/Source/tasks.c | 5 ++- 23 files changed, 139 insertions(+), 40 deletions(-) diff --git a/FreeRTOS/Source/include/FreeRTOS.h b/FreeRTOS/Source/include/FreeRTOS.h index 08a6be4f6..292f3e229 100644 --- a/FreeRTOS/Source/include/FreeRTOS.h +++ b/FreeRTOS/Source/include/FreeRTOS.h @@ -126,6 +126,10 @@ extern "C" { #error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. #endif +#if configMAX_PRIORITIES < 1 + #error configMAX_PRIORITIES must be defined to be greater than or equal to 1. +#endif + #ifndef configUSE_PREEMPTION #error Missing definition: configUSE_PREEMPTION must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif @@ -142,10 +146,6 @@ extern "C" { #error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. #endif -#ifndef configMAX_PRIORITIES - #error configMAX_PRIORITIES must be defined to be greater than or equal to 1. -#endif - #ifndef configUSE_CO_ROUTINES #define configUSE_CO_ROUTINES 0 #endif diff --git a/FreeRTOS/Source/portable/CCS/ARM_CM4F/port.c b/FreeRTOS/Source/portable/CCS/ARM_CM4F/port.c index 631d68ec1..65a2a5fad 100644 --- a/FreeRTOS/Source/portable/CCS/ARM_CM4F/port.c +++ b/FreeRTOS/Source/portable/CCS/ARM_CM4F/port.c @@ -563,6 +563,10 @@ void vPortSetupTimerInterrupt( void ) } #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 | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); diff --git a/FreeRTOS/Source/portable/CCS/ARM_CM4F/portasm.asm b/FreeRTOS/Source/portable/CCS/ARM_CM4F/portasm.asm index a392583b0..aa4255980 100644 --- a/FreeRTOS/Source/portable/CCS/ARM_CM4F/portasm.asm +++ b/FreeRTOS/Source/portable/CCS/ARM_CM4F/portasm.asm @@ -123,6 +123,9 @@ xPortPendSVHandler: .asmfunc ;/* Save the new top of stack into the first member of the TCB. */ str r0, [r2] + ;/* Ensure thread safety of atomic operations. */ + clrex + stmdb sp!, {r3} ldr r0, ulMaxSyscallInterruptPriorityConst ldr r1, [r0] diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM0/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM0/port.c index 191d19c43..0b5888c63 100644 --- a/FreeRTOS/Source/portable/GCC/ARM_CM0/port.c +++ b/FreeRTOS/Source/portable/GCC/ARM_CM0/port.c @@ -76,8 +76,9 @@ #include "task.h" /* Constants required to manipulate the NVIC. */ -#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t *) 0xe000e010 ) -#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t *) 0xe000e014 ) +#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 ) +#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 ) +#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 ) #define portNVIC_INT_CTRL ( ( volatile uint32_t *) 0xe000ed04 ) #define portNVIC_SYSPRI2 ( ( volatile uint32_t *) 0xe000ed20 ) #define portNVIC_SYSTICK_CLK 0x00000004 @@ -310,7 +311,7 @@ void xPortPendSVHandler( void ) " mov r5, r9 \n" " mov r6, r10 \n" " mov r7, r11 \n" - " stmia r0!, {r4-r7} \n" + " stmia r0!, {r4-r7} \n" " \n" " push {r3, r14} \n" " cpsid i \n" @@ -330,7 +331,7 @@ void xPortPendSVHandler( void ) " msr psp, r0 \n" /* Remember the new top of stack for the task. */ " \n" " sub r0, r0, #32 \n" /* Go back for the low registers that are not automatically restored. */ - " ldmia r0!, {r4-r7} \n" /* Pop low registers. */ + " ldmia r0!, {r4-r7} \n" /* Pop low registers. */ " \n" " bx r3 \n" " \n" @@ -363,6 +364,10 @@ uint32_t ulPreviousMask; */ void prvSetupTimerInterrupt( void ) { + /* Stop and reset the SysTick. */ + *(portNVIC_SYSTICK_CTRL) = 0UL; + *(portNVIC_SYSTICK_CURRENT_VALUE) = 0UL; + /* 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; diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c index 6f3611b0b..0888579f8 100644 --- a/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c +++ b/FreeRTOS/Source/portable/GCC/ARM_CM3/port.c @@ -410,6 +410,7 @@ void xPortPendSVHandler( void ) " \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. */ + " clrex \n" /* Ensure thread safety of atomic operations. */ " \n" " stmdb sp!, {r3, r14} \n" " mov r0, %0 \n" @@ -622,6 +623,10 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void ) } #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 | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM3_MPU/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM3_MPU/port.c index 0f30f0161..986b98824 100644 --- a/FreeRTOS/Source/portable/GCC/ARM_CM3_MPU/port.c +++ b/FreeRTOS/Source/portable/GCC/ARM_CM3_MPU/port.c @@ -89,6 +89,7 @@ task.h is included from an application file. */ /* 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_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) #define portNVIC_SYSPRI1_REG ( * ( ( volatile uint32_t * ) 0xe000ed1c ) ) #define portNVIC_SYS_CTRL_STATE_REG ( * ( ( volatile uint32_t * ) 0xe000ed24 ) ) @@ -449,6 +450,7 @@ void xPortPendSVHandler( void ) " 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. */ + " clrex \n" /* Ensure thread safety of atomic operations. */ " \n" " stmdb sp!, {r3, r14} \n" " mov r0, %0 \n" @@ -500,6 +502,10 @@ uint32_t ulDummy; */ static void prvSetupTimerInterrupt( void ) { + /* Reset the SysTick timer. */ + portNVIC_SYSTICK_CTRL_REG = 0UL; + portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; + /* Configure SysTick to interrupt at the requested rate. */ portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c index 42f5b378b..2cb58683e 100644 --- a/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c +++ b/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c @@ -449,8 +449,8 @@ void xPortPendSVHandler( void ) " vstmdbeq r0!, {s16-s31} \n" " \n" " stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */ - " \n" " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ + " clrex \n" /* Ensure thread safety of atomic operations. */ " \n" " stmdb sp!, {r3} \n" " mov r0, %0 \n" @@ -679,6 +679,10 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void ) } #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 | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM4_MPU/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM4_MPU/port.c index 83e175301..a6b4c5a84 100644 --- a/FreeRTOS/Source/portable/GCC/ARM_CM4_MPU/port.c +++ b/FreeRTOS/Source/portable/GCC/ARM_CM4_MPU/port.c @@ -91,6 +91,7 @@ task.h is included from an application file. */ /* 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_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) #define portNVIC_SYSPRI1_REG ( * ( ( volatile uint32_t * ) 0xe000ed1c ) ) #define portNVIC_SYS_CTRL_STATE_REG ( * ( ( volatile uint32_t * ) 0xe000ed24 ) ) @@ -196,7 +197,7 @@ static void prvSVCHandler( uint32_t *pulRegisters ) __attribute__(( noinline )) * Function to enable the VFP. */ static void vPortEnableVFP( void ) __attribute__ (( naked )); - + /* * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure * FreeRTOS API functions are not called from interrupts that have been assigned @@ -225,12 +226,12 @@ StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t px *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_EXEC_RETURN; - + pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ if( xRunPrivileged == pdTRUE ) @@ -476,6 +477,7 @@ void xPortPendSVHandler( void ) " 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. */ + " clrex \n" /* Ensure thread safety of atomic operations. */ " \n" " stmdb sp!, {r3} \n" " mov r0, %0 \n" @@ -533,6 +535,10 @@ uint32_t ulDummy; */ static void prvSetupTimerInterrupt( void ) { + /* 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 = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; diff --git a/FreeRTOS/Source/portable/GCC/ARM_CM7/r0p1/port.c b/FreeRTOS/Source/portable/GCC/ARM_CM7/r0p1/port.c index ce19d6af5..51d1c1a66 100644 --- a/FreeRTOS/Source/portable/GCC/ARM_CM7/r0p1/port.c +++ b/FreeRTOS/Source/portable/GCC/ARM_CM7/r0p1/port.c @@ -437,8 +437,8 @@ void xPortPendSVHandler( void ) " vstmdbeq r0!, {s16-s31} \n" " \n" " stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */ - " \n" " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ + " clrex \n" /* Ensure thread safety of atomic operations. */ " \n" " stmdb sp!, {r3} \n" " mov r0, %0 \n" @@ -669,6 +669,10 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void ) } #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 | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM0/port.c b/FreeRTOS/Source/portable/IAR/ARM_CM0/port.c index ed00f2247..7ab3635f5 100644 --- a/FreeRTOS/Source/portable/IAR/ARM_CM0/port.c +++ b/FreeRTOS/Source/portable/IAR/ARM_CM0/port.c @@ -79,8 +79,9 @@ #include "task.h" /* Constants required to manipulate the NVIC. */ -#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t *) 0xe000e010 ) -#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t *) 0xe000e014 ) +#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 ) +#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 ) +#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 ) #define portNVIC_SYSPRI2 ( ( volatile uint32_t *) 0xe000ed20 ) #define portNVIC_SYSTICK_CLK 0x00000004 #define portNVIC_SYSTICK_INT 0x00000002 @@ -247,6 +248,10 @@ uint32_t ulPreviousMask; */ static void prvSetupTimerInterrupt( void ) { + /* Stop and reset the SysTick. */ + *(portNVIC_SYSTICK_CTRL) = 0UL; + *(portNVIC_SYSTICK_CURRENT_VALUE) = 0UL; + /* 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; diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c b/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c index c6f4ac291..595b49de8 100644 --- a/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c +++ b/FreeRTOS/Source/portable/IAR/ARM_CM3/port.c @@ -535,6 +535,10 @@ __weak void vPortSetupTimerInterrupt( void ) } #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 | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM3/portasm.s b/FreeRTOS/Source/portable/IAR/ARM_CM3/portasm.s index cf7a6a3a1..756602121 100644 --- a/FreeRTOS/Source/portable/IAR/ARM_CM3/portasm.s +++ b/FreeRTOS/Source/portable/IAR/ARM_CM3/portasm.s @@ -91,6 +91,7 @@ xPortPendSVHandler: stmdb r0!, {r4-r11} /* Save the remaining registers. */ str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ + clrex /* Ensure thread safety of atomic operations. */ stmdb sp!, {r3, r14} mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c b/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c index 3d102b6c6..094965f88 100644 --- a/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c +++ b/FreeRTOS/Source/portable/IAR/ARM_CM4F/port.c @@ -576,6 +576,10 @@ __weak void vPortSetupTimerInterrupt( void ) } #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 | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM4F/portasm.s b/FreeRTOS/Source/portable/IAR/ARM_CM4F/portasm.s index 758d6fa97..a6e07773d 100644 --- a/FreeRTOS/Source/portable/IAR/ARM_CM4F/portasm.s +++ b/FreeRTOS/Source/portable/IAR/ARM_CM4F/portasm.s @@ -101,6 +101,9 @@ xPortPendSVHandler: /* Save the new top of stack into the first member of the TCB. */ str r0, [r2] + /* Ensure thread safety of atomic operations. */ + clrex + stmdb sp!, {r3} mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY msr basepri, r0 diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/port.c b/FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/port.c index da08e4971..34a1b25a4 100644 --- a/FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/port.c +++ b/FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/port.c @@ -559,6 +559,10 @@ __weak void vPortSetupTimerInterrupt( void ) } #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 | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); diff --git a/FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/portasm.s b/FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/portasm.s index 2ab809a0e..e90dfb261 100644 --- a/FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/portasm.s +++ b/FreeRTOS/Source/portable/IAR/ARM_CM7/r0p1/portasm.s @@ -101,6 +101,9 @@ xPortPendSVHandler: /* Save the new top of stack into the first member of the TCB. */ str r0, [r2] + /* Ensure thread safety of atomic operations. */ + clrex + stmdb sp!, {r3} mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY cpsid i diff --git a/FreeRTOS/Source/portable/MikroC/ARM_CM4F/port.c b/FreeRTOS/Source/portable/MikroC/ARM_CM4F/port.c index 97a7c8dd1..8bd991d3c 100644 --- a/FreeRTOS/Source/portable/MikroC/ARM_CM4F/port.c +++ b/FreeRTOS/Source/portable/MikroC/ARM_CM4F/port.c @@ -457,7 +457,8 @@ void xPortPendSVHandler( void ) iv IVT_INT_PendSV ics ICS_OFF stmdb r0!, (r4-r11, r14) /* Save the core registers. */ str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ -/*_RB_? mrs r0, psp why was this here? */ + + clrex /* Ensure thread safety of atomic operations. */ stmdb sp!, (r3) ldr r0, =_ucMaxSyscallInterruptPriority @@ -670,20 +671,24 @@ void xPortSysTickHandler( void ) iv IVT_INT_SysTick ics ICS_AUTO #if( configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 ) 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 */ + { + /* 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 */ - /* 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 | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); - } + /* Reset 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 | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); + } #endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */ /*-----------------------------------------------------------*/ diff --git a/FreeRTOS/Source/portable/RVDS/ARM_CM0/port.c b/FreeRTOS/Source/portable/RVDS/ARM_CM0/port.c index 6fc1e94b6..1de444935 100644 --- a/FreeRTOS/Source/portable/RVDS/ARM_CM0/port.c +++ b/FreeRTOS/Source/portable/RVDS/ARM_CM0/port.c @@ -76,8 +76,9 @@ #include "task.h" /* Constants required to manipulate the NVIC. */ -#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t *) 0xe000e010 ) -#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t *) 0xe000e014 ) +#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 ) +#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t * ) 0xe000e014 ) +#define portNVIC_SYSTICK_CURRENT_VALUE ( ( volatile uint32_t * ) 0xe000e018 ) #define portNVIC_INT_CTRL ( ( volatile uint32_t *) 0xe000ed04 ) #define portNVIC_SYSPRI2 ( ( volatile uint32_t *) 0xe000ed20 ) #define portNVIC_SYSTICK_CLK 0x00000004 @@ -341,6 +342,10 @@ uint32_t ulPreviousMask; */ void prvSetupTimerInterrupt( void ) { + /* Stop and reset the SysTick. */ + *(portNVIC_SYSTICK_CTRL) = 0UL; + *(portNVIC_SYSTICK_CURRENT_VALUE) = 0UL; + /* 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; diff --git a/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c b/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c index 61d85967d..8ce6d098d 100644 --- a/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c +++ b/FreeRTOS/Source/portable/RVDS/ARM_CM3/port.c @@ -407,6 +407,7 @@ __asm void xPortPendSVHandler( void ) stmdb r0!, {r4-r11} /* Save the remaining registers. */ str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ + clrex /* Ensure thread safety of atomic operations. */ stmdb sp!, {r3, r14} mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY @@ -621,6 +622,10 @@ void xPortSysTickHandler( void ) } #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 | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); diff --git a/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c b/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c index 1dc1b5b00..aaf9efd21 100644 --- a/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c +++ b/FreeRTOS/Source/portable/RVDS/ARM_CM4F/port.c @@ -479,6 +479,9 @@ __asm void xPortPendSVHandler( void ) /* Save the new top of stack into the first member of the TCB. */ str r0, [r2] + /* Ensure thread safety of atomic operations. */ + clrex + stmdb sp!, {r3} mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY msr basepri, r0 @@ -696,7 +699,7 @@ void xPortSysTickHandler( void ) * Setup the SysTick timer to generate the tick interrupts at the required * frequency. */ -#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 +#if( configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 ) void vPortSetupTimerInterrupt( void ) { @@ -709,6 +712,10 @@ void xPortSysTickHandler( void ) } #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 | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); diff --git a/FreeRTOS/Source/portable/RVDS/ARM_CM4_MPU/port.c b/FreeRTOS/Source/portable/RVDS/ARM_CM4_MPU/port.c index bbe2a96a8..0623859e8 100644 --- a/FreeRTOS/Source/portable/RVDS/ARM_CM4_MPU/port.c +++ b/FreeRTOS/Source/portable/RVDS/ARM_CM4_MPU/port.c @@ -91,6 +91,7 @@ task.h is included from an application file. */ /* 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_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) ) #define portNVIC_SYSPRI1_REG ( * ( ( volatile uint32_t * ) 0xe000ed1c ) ) #define portNVIC_SYS_CTRL_STATE_REG ( * ( ( volatile uint32_t * ) 0xe000ed24 ) ) @@ -206,7 +207,7 @@ static void vPortEnableVFP( void ); * Utility function. */ static uint32_t prvPortGetIPSR( void ); - + /* * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure * FreeRTOS API functions are not called from interrupts that have been assigned @@ -297,7 +298,7 @@ uint32_t ulReg; __asm void vPortSVCHandler( void ) { extern prvSVCHandler - + PRESERVE8 /* Assumes psp was in use. */ @@ -424,7 +425,7 @@ BaseType_t xPortStartScheduler( void ) __asm void prvStartFirstTask( void ) { PRESERVE8 - + ldr r0, =0xE000ED08 /* Use the NVIC offset register to locate the stack. */ ldr r0, [r0] ldr r0, [r0] @@ -491,6 +492,7 @@ __asm void xPortPendSVHandler( void ) mrs r1, control stmdb r0!, {r1, r4-r11, r14} /* Save the remaining registers. */ str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ + clrex /* Ensure thread safety of atomic operations. */ stmdb sp!, {r3} mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY @@ -544,6 +546,10 @@ uint32_t ulDummy; */ static void prvSetupTimerInterrupt( void ) { + /* Reset 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 = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; @@ -553,18 +559,18 @@ static void prvSetupTimerInterrupt( void ) __asm void vPortSwitchToUserMode( void ) { PRESERVE8 - + mrs r0, control orr r0, #1 msr control, r0 bx r14 } /*-----------------------------------------------------------*/ - + __asm void vPortEnableVFP( void ) { PRESERVE8 - + ldr.w r0, =0xE000ED88 /* The FPU enable bits are in the CPACR. */ ldr r1, [r0] @@ -682,7 +688,7 @@ extern uint32_t __SRAM_segment_end__; extern uint32_t __privileged_data_start__; extern uint32_t __privileged_data_end__; - + int32_t lIndex; uint32_t ul; diff --git a/FreeRTOS/Source/portable/RVDS/ARM_CM7/r0p1/port.c b/FreeRTOS/Source/portable/RVDS/ARM_CM7/r0p1/port.c index ef34402f6..9f0dc3330 100644 --- a/FreeRTOS/Source/portable/RVDS/ARM_CM7/r0p1/port.c +++ b/FreeRTOS/Source/portable/RVDS/ARM_CM7/r0p1/port.c @@ -463,6 +463,9 @@ __asm void xPortPendSVHandler( void ) /* Save the new top of stack into the first member of the TCB. */ str r0, [r2] + /* Ensure thread safety of atomic operations. */ + clrex + stmdb sp!, {r3} mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY cpsid i @@ -695,6 +698,10 @@ void xPortSysTickHandler( void ) } #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 | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); diff --git a/FreeRTOS/Source/tasks.c b/FreeRTOS/Source/tasks.c index 8aea1cd91..d2d7b1159 100644 --- a/FreeRTOS/Source/tasks.c +++ b/FreeRTOS/Source/tasks.c @@ -1901,7 +1901,10 @@ BaseType_t xReturn; /* If configGENERATE_RUN_TIME_STATS is defined then the following macro must be defined to configure the timer/counter used to generate - the run time counter time base. */ + the run time counter time base. NOTE: If configGENERATE_RUN_TIME_STATS + is set to 0 and the following line fails to build then ensure you do not + have portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() defined in your + FreeRTOSConfig.h file. */ portCONFIGURE_TIMER_FOR_RUN_TIME_STATS(); /* Setting up the timer tick is hardware specific and thus in the -- 2.39.2