Update Cortex-M3 and Cortex-M4F ports to allow the SysTick to be clocked at a different speed than the system clock (as is done in the recent STM32L demo. ).

Add additional asserts and isb instructions into the Cortex-M3 and Cortex-M4F ports.
This commit is contained in:
Richard Barry 2013-12-12 14:07:20 +00:00
parent 6b3393b4b6
commit 0d1e12522b
10 changed files with 110 additions and 67 deletions

View file

@ -357,7 +357,7 @@ void xPortSysTickHandler( void )
__weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
{
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
portTickType xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */
@ -370,7 +370,7 @@ void xPortSysTickHandler( void )
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 | portNVIC_SYSTICK_INT_BIT;
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
/* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way
@ -394,7 +394,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick
periods. */
@ -414,7 +414,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
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
@ -435,13 +435,14 @@ void xPortSysTickHandler( void )
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 | portNVIC_SYSTICK_INT_BIT;
ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
/* Re-enable interrupts - see comments above __disable_interrupt()
call above. */
__enable_interrupt();
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
unsigned long ulCalculatedLoadValue;
@ -493,7 +494,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portENTER_CRITICAL();
{
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
}
@ -521,7 +522,7 @@ __weak void vPortSetupTimerInterrupt( void )
/* 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;
portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
}
/*-----------------------------------------------------------*/

View file

@ -1,5 +1,5 @@
/*
FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
FreeRTOS V7.6.0 - Copyright (C) 2013 Real Time Engineers Ltd.
All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -82,9 +82,10 @@
/*-----------------------------------------------------------*/
xPortPendSVHandler:
mrs r0, psp
mrs r0, psp
isb
ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */
ldr r2, [r3]
ldr r2, [r3]
stmdb r0!, {r4-r11} /* Save the remaining registers. */
str r0, [r2] /* Save the new top of stack into the first member of the TCB. */
@ -92,16 +93,17 @@ xPortPendSVHandler:
stmdb sp!, {r3, r14}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r0
bl vTaskSwitchContext
bl vTaskSwitchContext
mov r0, #0
msr basepri, r0
ldmia sp!, {r3, r14}
ldr r1, [r3]
ldr r1, [r3]
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
ldmia r0!, {r4-r11} /* Pop the registers. */
msr psp, r0
bx r14
msr psp, r0
isb
bx r14
/*-----------------------------------------------------------*/
@ -111,7 +113,7 @@ ulPortSetInterruptMask:
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r1
bx r14
/*-----------------------------------------------------------*/
vPortClearInterruptMask:
@ -128,6 +130,7 @@ vPortSVCHandler:
/* Pop the core registers. */
ldmia r0!, {r4-r11}
msr psp, r0
isb
mov r0, #0
msr basepri, r0
orr r14, r14, #13
@ -144,7 +147,8 @@ vPortStartFirstTask
msr msp, r0
/* Call SVC to start the first task. */
cpsie i
dsb
isb
svc 0
END

View file

@ -383,7 +383,7 @@ void xPortSysTickHandler( void )
__weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
{
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements;
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
portTickType xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */
@ -396,7 +396,7 @@ void xPortSysTickHandler( void )
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 | portNVIC_SYSTICK_INT_BIT;
portNVIC_SYSTICK_CTRL_REG &= ~portNVIC_SYSTICK_ENABLE_BIT;
/* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way
@ -420,7 +420,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick
periods. */
@ -440,7 +440,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
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
@ -461,13 +461,14 @@ void xPortSysTickHandler( void )
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 | portNVIC_SYSTICK_INT_BIT;
ulSysTickCTRL = portNVIC_SYSTICK_CTRL_REG;
portNVIC_SYSTICK_CTRL_REG = ( ulSysTickCTRL & ~portNVIC_SYSTICK_ENABLE_BIT );
/* Re-enable interrupts - see comments above __disable_interrupt()
call above. */
__enable_interrupt();
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{
unsigned long ulCalculatedLoadValue;
@ -519,7 +520,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portENTER_CRITICAL();
{
portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
portNVIC_SYSTICK_CTRL_REG |= portNVIC_SYSTICK_ENABLE_BIT;
vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
}
@ -547,7 +548,7 @@ __weak void vPortSetupTimerInterrupt( void )
/* 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;
portNVIC_SYSTICK_CTRL_REG |= ( portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
}
/*-----------------------------------------------------------*/

View file

@ -83,7 +83,7 @@
xPortPendSVHandler:
mrs r0, psp
isb
/* Get the location of the current TCB. */
ldr r3, =pxCurrentTCB
ldr r2, [r3]
@ -121,7 +121,7 @@ xPortPendSVHandler:
vldmiaeq r0!, {s16-s31}
msr psp, r0
isb
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */
#if WORKAROUND_PMU_CM001 == 1
push { r14 }
@ -156,6 +156,7 @@ vPortSVCHandler:
/* Pop the core registers. */
ldmia r0!, {r4-r11, r14}
msr psp, r0
isb
mov r0, #0
msr basepri, r0
bx r14
@ -171,6 +172,8 @@ vPortStartFirstTask
msr msp, r0
/* Call SVC to start the first task. */
cpsie i
dsb
isb
svc 0
/*-----------------------------------------------------------*/