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.
This commit is contained in:
Richard Barry 2016-06-27 13:13:05 +00:00
parent 6c975cd46a
commit c296e2cff8
23 changed files with 139 additions and 40 deletions

View file

@ -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. #error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details.
#endif #endif
#if configMAX_PRIORITIES < 1
#error configMAX_PRIORITIES must be defined to be greater than or equal to 1.
#endif
#ifndef configUSE_PREEMPTION #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. #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 #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. #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 #endif
#ifndef configMAX_PRIORITIES
#error configMAX_PRIORITIES must be defined to be greater than or equal to 1.
#endif
#ifndef configUSE_CO_ROUTINES #ifndef configUSE_CO_ROUTINES
#define configUSE_CO_ROUTINES 0 #define configUSE_CO_ROUTINES 0
#endif #endif

View file

@ -563,6 +563,10 @@ void vPortSetupTimerInterrupt( void )
} }
#endif /* configUSE_TICKLESS_IDLE */ #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. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; 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 ); portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );

View file

@ -123,6 +123,9 @@ xPortPendSVHandler: .asmfunc
;/* Save the new top of stack into the first member of the TCB. */ ;/* Save the new top of stack into the first member of the TCB. */
str r0, [r2] str r0, [r2]
;/* Ensure thread safety of atomic operations. */
clrex
stmdb sp!, {r3} stmdb sp!, {r3}
ldr r0, ulMaxSyscallInterruptPriorityConst ldr r0, ulMaxSyscallInterruptPriorityConst
ldr r1, [r0] ldr r1, [r0]

View file

@ -76,8 +76,9 @@
#include "task.h" #include "task.h"
/* Constants required to manipulate the NVIC. */ /* Constants required to manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t *) 0xe000e010 ) #define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t *) 0xe000e014 ) #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_INT_CTRL ( ( volatile uint32_t *) 0xe000ed04 )
#define portNVIC_SYSPRI2 ( ( volatile uint32_t *) 0xe000ed20 ) #define portNVIC_SYSPRI2 ( ( volatile uint32_t *) 0xe000ed20 )
#define portNVIC_SYSTICK_CLK 0x00000004 #define portNVIC_SYSTICK_CLK 0x00000004
@ -310,7 +311,7 @@ void xPortPendSVHandler( void )
" mov r5, r9 \n" " mov r5, r9 \n"
" mov r6, r10 \n" " mov r6, r10 \n"
" mov r7, r11 \n" " mov r7, r11 \n"
" stmia r0!, {r4-r7} \n" " stmia r0!, {r4-r7} \n"
" \n" " \n"
" push {r3, r14} \n" " push {r3, r14} \n"
" cpsid i \n" " cpsid i \n"
@ -330,7 +331,7 @@ void xPortPendSVHandler( void )
" msr psp, r0 \n" /* Remember the new top of stack for the task. */ " msr psp, r0 \n" /* Remember the new top of stack for the task. */
" \n" " \n"
" sub r0, r0, #32 \n" /* Go back for the low registers that are not automatically restored. */ " 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" " \n"
" bx r3 \n" " bx r3 \n"
" \n" " \n"
@ -363,6 +364,10 @@ uint32_t ulPreviousMask;
*/ */
void prvSetupTimerInterrupt( void ) 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. */ /* Configure SysTick to interrupt at the requested rate. */
*(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
*(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;

View file

@ -410,6 +410,7 @@ void xPortPendSVHandler( void )
" \n" " \n"
" stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */ " 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. */ " 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" " \n"
" stmdb sp!, {r3, r14} \n" " stmdb sp!, {r3, r14} \n"
" mov r0, %0 \n" " mov r0, %0 \n"
@ -622,6 +623,10 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
} }
#endif /* configUSE_TICKLESS_IDLE */ #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. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; 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 ); portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );

View file

@ -89,6 +89,7 @@ task.h is included from an application file. */
/* Constants required to access and manipulate the NVIC. */ /* Constants required to access and manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) #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_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
#define portNVIC_SYSPRI1_REG ( * ( ( volatile uint32_t * ) 0xe000ed1c ) ) #define portNVIC_SYSPRI1_REG ( * ( ( volatile uint32_t * ) 0xe000ed1c ) )
#define portNVIC_SYS_CTRL_STATE_REG ( * ( ( volatile uint32_t * ) 0xe000ed24 ) ) #define portNVIC_SYS_CTRL_STATE_REG ( * ( ( volatile uint32_t * ) 0xe000ed24 ) )
@ -449,6 +450,7 @@ void xPortPendSVHandler( void )
" mrs r1, control \n" " mrs r1, control \n"
" stmdb r0!, {r1, r4-r11} \n" /* Save the remaining registers. */ " 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. */ " 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" " \n"
" stmdb sp!, {r3, r14} \n" " stmdb sp!, {r3, r14} \n"
" mov r0, %0 \n" " mov r0, %0 \n"
@ -500,6 +502,10 @@ uint32_t ulDummy;
*/ */
static void prvSetupTimerInterrupt( void ) 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. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ( configCPU_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 | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;

View file

@ -449,8 +449,8 @@ void xPortPendSVHandler( void )
" vstmdbeq r0!, {s16-s31} \n" " vstmdbeq r0!, {s16-s31} \n"
" \n" " \n"
" stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */ " 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. */ " 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" " \n"
" stmdb sp!, {r3} \n" " stmdb sp!, {r3} \n"
" mov r0, %0 \n" " mov r0, %0 \n"
@ -679,6 +679,10 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
} }
#endif /* configUSE_TICKLESS_IDLE */ #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. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; 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 ); portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );

View file

@ -91,6 +91,7 @@ task.h is included from an application file. */
/* Constants required to access and manipulate the NVIC. */ /* Constants required to access and manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) #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_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
#define portNVIC_SYSPRI1_REG ( * ( ( volatile uint32_t * ) 0xe000ed1c ) ) #define portNVIC_SYSPRI1_REG ( * ( ( volatile uint32_t * ) 0xe000ed1c ) )
#define portNVIC_SYS_CTRL_STATE_REG ( * ( ( volatile uint32_t * ) 0xe000ed24 ) ) #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. * Function to enable the VFP.
*/ */
static void vPortEnableVFP( void ) __attribute__ (( naked )); static void vPortEnableVFP( void ) __attribute__ (( naked ));
/* /*
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
* FreeRTOS API functions are not called from interrupts that have been assigned * 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 = 0; /* LR */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */ *pxTopOfStack = ( StackType_t ) pvParameters; /* R0 */
/* A save method is being used that requires each task to maintain its /* A save method is being used that requires each task to maintain its
own exec return value. */ own exec return value. */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = portINITIAL_EXEC_RETURN; *pxTopOfStack = portINITIAL_EXEC_RETURN;
pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
if( xRunPrivileged == pdTRUE ) if( xRunPrivileged == pdTRUE )
@ -476,6 +477,7 @@ void xPortPendSVHandler( void )
" mrs r1, control \n" " mrs r1, control \n"
" stmdb r0!, {r1, r4-r11, r14} \n" /* Save the remaining registers. */ " 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. */ " 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" " \n"
" stmdb sp!, {r3} \n" " stmdb sp!, {r3} \n"
" mov r0, %0 \n" " mov r0, %0 \n"
@ -533,6 +535,10 @@ uint32_t ulDummy;
*/ */
static void prvSetupTimerInterrupt( void ) 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. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ( configCPU_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 | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;

View file

@ -437,8 +437,8 @@ void xPortPendSVHandler( void )
" vstmdbeq r0!, {s16-s31} \n" " vstmdbeq r0!, {s16-s31} \n"
" \n" " \n"
" stmdb r0!, {r4-r11, r14} \n" /* Save the core registers. */ " 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. */ " 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" " \n"
" stmdb sp!, {r3} \n" " stmdb sp!, {r3} \n"
" mov r0, %0 \n" " mov r0, %0 \n"
@ -669,6 +669,10 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
} }
#endif /* configUSE_TICKLESS_IDLE */ #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. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; 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 ); portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );

View file

@ -79,8 +79,9 @@
#include "task.h" #include "task.h"
/* Constants required to manipulate the NVIC. */ /* Constants required to manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t *) 0xe000e010 ) #define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t *) 0xe000e014 ) #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_SYSPRI2 ( ( volatile uint32_t *) 0xe000ed20 )
#define portNVIC_SYSTICK_CLK 0x00000004 #define portNVIC_SYSTICK_CLK 0x00000004
#define portNVIC_SYSTICK_INT 0x00000002 #define portNVIC_SYSTICK_INT 0x00000002
@ -247,6 +248,10 @@ uint32_t ulPreviousMask;
*/ */
static void prvSetupTimerInterrupt( void ) 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. */ /* Configure SysTick to interrupt at the requested rate. */
*(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
*(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;

View file

@ -535,6 +535,10 @@ __weak void vPortSetupTimerInterrupt( void )
} }
#endif /* configUSE_TICKLESS_IDLE */ #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. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; 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 ); portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );

View file

@ -91,6 +91,7 @@ xPortPendSVHandler:
stmdb r0!, {r4-r11} /* Save the remaining registers. */ stmdb r0!, {r4-r11} /* Save the remaining registers. */
str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ 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} stmdb sp!, {r3, r14}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY

View file

@ -576,6 +576,10 @@ __weak void vPortSetupTimerInterrupt( void )
} }
#endif /* configUSE_TICKLESS_IDLE */ #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. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; 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 ); portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );

View file

@ -101,6 +101,9 @@ xPortPendSVHandler:
/* Save the new top of stack into the first member of the TCB. */ /* Save the new top of stack into the first member of the TCB. */
str r0, [r2] str r0, [r2]
/* Ensure thread safety of atomic operations. */
clrex
stmdb sp!, {r3} stmdb sp!, {r3}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r0 msr basepri, r0

View file

@ -559,6 +559,10 @@ __weak void vPortSetupTimerInterrupt( void )
} }
#endif /* configUSE_TICKLESS_IDLE */ #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. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; 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 ); portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );

View file

@ -101,6 +101,9 @@ xPortPendSVHandler:
/* Save the new top of stack into the first member of the TCB. */ /* Save the new top of stack into the first member of the TCB. */
str r0, [r2] str r0, [r2]
/* Ensure thread safety of atomic operations. */
clrex
stmdb sp!, {r3} stmdb sp!, {r3}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
cpsid i cpsid i

View file

@ -457,7 +457,8 @@ void xPortPendSVHandler( void ) iv IVT_INT_PendSV ics ICS_OFF
stmdb r0!, (r4-r11, r14) /* Save the core registers. */ 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. */ 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) stmdb sp!, (r3)
ldr r0, =_ucMaxSyscallInterruptPriority ldr r0, =_ucMaxSyscallInterruptPriority
@ -670,20 +671,24 @@ void xPortSysTickHandler( void ) iv IVT_INT_SysTick ics ICS_AUTO
#if( configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 ) #if( configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 )
void vPortSetupTimerInterrupt( void ) void vPortSetupTimerInterrupt( void )
{ {
/* Calculate the constants required to configure the tick interrupt. */ /* Calculate the constants required to configure the tick interrupt. */
#if configUSE_TICKLESS_IDLE == 1 #if configUSE_TICKLESS_IDLE == 1
{ {
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ); ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick; xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ ); ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
} }
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/* Configure SysTick to interrupt at the requested rate. */ /* Reset SysTick. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_CTRL_REG = 0UL;
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT ); 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 */ #endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -76,8 +76,9 @@
#include "task.h" #include "task.h"
/* Constants required to manipulate the NVIC. */ /* Constants required to manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t *) 0xe000e010 ) #define portNVIC_SYSTICK_CTRL ( ( volatile uint32_t * ) 0xe000e010 )
#define portNVIC_SYSTICK_LOAD ( ( volatile uint32_t *) 0xe000e014 ) #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_INT_CTRL ( ( volatile uint32_t *) 0xe000ed04 )
#define portNVIC_SYSPRI2 ( ( volatile uint32_t *) 0xe000ed20 ) #define portNVIC_SYSPRI2 ( ( volatile uint32_t *) 0xe000ed20 )
#define portNVIC_SYSTICK_CLK 0x00000004 #define portNVIC_SYSTICK_CLK 0x00000004
@ -341,6 +342,10 @@ uint32_t ulPreviousMask;
*/ */
void prvSetupTimerInterrupt( void ) 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. */ /* Configure SysTick to interrupt at the requested rate. */
*(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; *(portNVIC_SYSTICK_LOAD) = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
*(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE; *(portNVIC_SYSTICK_CTRL) = portNVIC_SYSTICK_CLK | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;

View file

@ -407,6 +407,7 @@ __asm void xPortPendSVHandler( void )
stmdb r0!, {r4-r11} /* Save the remaining registers. */ stmdb r0!, {r4-r11} /* Save the remaining registers. */
str r0, [r2] /* Save the new top of stack into the first member of the TCB. */ 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} stmdb sp!, {r3, r14}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
@ -621,6 +622,10 @@ void xPortSysTickHandler( void )
} }
#endif /* configUSE_TICKLESS_IDLE */ #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. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; 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 ); portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );

View file

@ -479,6 +479,9 @@ __asm void xPortPendSVHandler( void )
/* Save the new top of stack into the first member of the TCB. */ /* Save the new top of stack into the first member of the TCB. */
str r0, [r2] str r0, [r2]
/* Ensure thread safety of atomic operations. */
clrex
stmdb sp!, {r3} stmdb sp!, {r3}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r0 msr basepri, r0
@ -696,7 +699,7 @@ void xPortSysTickHandler( void )
* Setup the SysTick timer to generate the tick interrupts at the required * Setup the SysTick timer to generate the tick interrupts at the required
* frequency. * frequency.
*/ */
#if configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 #if( configOVERRIDE_DEFAULT_TICK_CONFIGURATION == 0 )
void vPortSetupTimerInterrupt( void ) void vPortSetupTimerInterrupt( void )
{ {
@ -709,6 +712,10 @@ void xPortSysTickHandler( void )
} }
#endif /* configUSE_TICKLESS_IDLE */ #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. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; 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 ); portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );

View file

@ -91,6 +91,7 @@ task.h is included from an application file. */
/* Constants required to access and manipulate the NVIC. */ /* Constants required to access and manipulate the NVIC. */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) ) #define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) ) #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_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
#define portNVIC_SYSPRI1_REG ( * ( ( volatile uint32_t * ) 0xe000ed1c ) ) #define portNVIC_SYSPRI1_REG ( * ( ( volatile uint32_t * ) 0xe000ed1c ) )
#define portNVIC_SYS_CTRL_STATE_REG ( * ( ( volatile uint32_t * ) 0xe000ed24 ) ) #define portNVIC_SYS_CTRL_STATE_REG ( * ( ( volatile uint32_t * ) 0xe000ed24 ) )
@ -206,7 +207,7 @@ static void vPortEnableVFP( void );
* Utility function. * Utility function.
*/ */
static uint32_t prvPortGetIPSR( void ); static uint32_t prvPortGetIPSR( void );
/* /*
* Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure * Used by the portASSERT_IF_INTERRUPT_PRIORITY_INVALID() macro to ensure
* FreeRTOS API functions are not called from interrupts that have been assigned * FreeRTOS API functions are not called from interrupts that have been assigned
@ -297,7 +298,7 @@ uint32_t ulReg;
__asm void vPortSVCHandler( void ) __asm void vPortSVCHandler( void )
{ {
extern prvSVCHandler extern prvSVCHandler
PRESERVE8 PRESERVE8
/* Assumes psp was in use. */ /* Assumes psp was in use. */
@ -424,7 +425,7 @@ BaseType_t xPortStartScheduler( void )
__asm void prvStartFirstTask( void ) __asm void prvStartFirstTask( void )
{ {
PRESERVE8 PRESERVE8
ldr r0, =0xE000ED08 /* Use the NVIC offset register to locate the stack. */ ldr r0, =0xE000ED08 /* Use the NVIC offset register to locate the stack. */
ldr r0, [r0] ldr r0, [r0]
ldr r0, [r0] ldr r0, [r0]
@ -491,6 +492,7 @@ __asm void xPortPendSVHandler( void )
mrs r1, control mrs r1, control
stmdb r0!, {r1, r4-r11, r14} /* Save the remaining registers. */ 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. */ 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} stmdb sp!, {r3}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
@ -544,6 +546,10 @@ uint32_t ulDummy;
*/ */
static void prvSetupTimerInterrupt( void ) 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. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; portNVIC_SYSTICK_LOAD_REG = ( configCPU_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 | portNVIC_SYSTICK_INT | portNVIC_SYSTICK_ENABLE;
@ -553,18 +559,18 @@ static void prvSetupTimerInterrupt( void )
__asm void vPortSwitchToUserMode( void ) __asm void vPortSwitchToUserMode( void )
{ {
PRESERVE8 PRESERVE8
mrs r0, control mrs r0, control
orr r0, #1 orr r0, #1
msr control, r0 msr control, r0
bx r14 bx r14
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
__asm void vPortEnableVFP( void ) __asm void vPortEnableVFP( void )
{ {
PRESERVE8 PRESERVE8
ldr.w r0, =0xE000ED88 /* The FPU enable bits are in the CPACR. */ ldr.w r0, =0xE000ED88 /* The FPU enable bits are in the CPACR. */
ldr r1, [r0] ldr r1, [r0]
@ -682,7 +688,7 @@ extern uint32_t __SRAM_segment_end__;
extern uint32_t __privileged_data_start__; extern uint32_t __privileged_data_start__;
extern uint32_t __privileged_data_end__; extern uint32_t __privileged_data_end__;
int32_t lIndex; int32_t lIndex;
uint32_t ul; uint32_t ul;

View file

@ -463,6 +463,9 @@ __asm void xPortPendSVHandler( void )
/* Save the new top of stack into the first member of the TCB. */ /* Save the new top of stack into the first member of the TCB. */
str r0, [r2] str r0, [r2]
/* Ensure thread safety of atomic operations. */
clrex
stmdb sp!, {r3} stmdb sp!, {r3}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
cpsid i cpsid i
@ -695,6 +698,10 @@ void xPortSysTickHandler( void )
} }
#endif /* configUSE_TICKLESS_IDLE */ #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. */ /* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL; 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 ); portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );

View file

@ -1901,7 +1901,10 @@ BaseType_t xReturn;
/* If configGENERATE_RUN_TIME_STATS is defined then the following /* If configGENERATE_RUN_TIME_STATS is defined then the following
macro must be defined to configure the timer/counter used to generate 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(); portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
/* Setting up the timer tick is hardware specific and thus in the /* Setting up the timer tick is hardware specific and thus in the