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

@ -237,6 +237,7 @@ void vPortSVCHandler( void )
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ " ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
" msr psp, r0 \n" /* Restore the task stack pointer. */ " msr psp, r0 \n" /* Restore the task stack pointer. */
" isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" orr r14, #0xd \n" " orr r14, #0xd \n"
@ -256,6 +257,8 @@ static void prvPortStartFirstTask( void )
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */ " msr msp, r0 \n" /* Set the msp back to the start of the stack. */
" cpsie i \n" /* Globally enable interrupts. */ " cpsie i \n" /* Globally enable interrupts. */
" dsb \n"
" isb \n"
" svc 0 \n" /* System call to start first task. */ " svc 0 \n" /* System call to start first task. */
" nop \n" " nop \n"
); );
@ -342,8 +345,9 @@ portBASE_TYPE xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the CM3 port will require this function as there /* Not implemented in ports where there is nothing to return to.
is nothing to return to. */ Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -370,6 +374,7 @@ void vPortEnterCritical( void )
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
configASSERT( uxCriticalNesting );
uxCriticalNesting--; uxCriticalNesting--;
if( uxCriticalNesting == 0 ) if( uxCriticalNesting == 0 )
{ {
@ -416,6 +421,7 @@ void xPortPendSVHandler( void )
__asm volatile __asm volatile
( (
" mrs r0, psp \n" " mrs r0, psp \n"
" isb \n"
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n" " ldr r2, [r3] \n"
@ -435,6 +441,7 @@ void xPortPendSVHandler( void )
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r4-r11} \n" /* Pop the registers. */ " ldmia r0!, {r4-r11} \n" /* Pop the registers. */
" msr psp, r0 \n" " msr psp, r0 \n"
" isb \n"
" bx r14 \n" " bx r14 \n"
" \n" " \n"
" .align 2 \n" " .align 2 \n"
@ -468,7 +475,7 @@ void xPortSysTickHandler( void )
__attribute__((weak)) void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) __attribute__((weak)) void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
{ {
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
portTickType xModifiableIdleTime; portTickType xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */ /* Make sure the SysTick reload value does not overflow the counter. */
@ -481,7 +488,7 @@ void xPortSysTickHandler( void )
is accounted for as best it can be, but using the tickless mode will 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 inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */ 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 /* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way tick periods. -1 is used because this code will execute part way
@ -505,7 +512,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */ /* 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 /* Reset the reload register to the value required for normal tick
periods. */ periods. */
@ -525,7 +532,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */ /* 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 /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains set its parameter to 0 to indicate that its implementation contains
@ -546,13 +553,14 @@ void xPortSysTickHandler( void )
accounted for as best it can be, but using the tickless mode will 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 inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */ 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 the cpsid instruction() /* Re-enable interrupts - see comments above the cpsid instruction()
above. */ above. */
__asm volatile( "cpsie i" ); __asm volatile( "cpsie i" );
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{ {
unsigned long ulCalculatedLoadValue; unsigned long ulCalculatedLoadValue;
@ -604,7 +612,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portENTER_CRITICAL(); 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 ); vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
} }
@ -632,7 +640,7 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
/* 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_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -256,6 +256,7 @@ void vPortSVCHandler( void )
" ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */
" ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ " ldmia r0!, {r4-r11, r14} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
" msr psp, r0 \n" /* Restore the task stack pointer. */ " msr psp, r0 \n" /* Restore the task stack pointer. */
" isb \n"
" mov r0, #0 \n" " mov r0, #0 \n"
" msr basepri, r0 \n" " msr basepri, r0 \n"
" bx r14 \n" " bx r14 \n"
@ -274,6 +275,8 @@ static void prvPortStartFirstTask( void )
" ldr r0, [r0] \n" " ldr r0, [r0] \n"
" msr msp, r0 \n" /* Set the msp back to the start of the stack. */ " msr msp, r0 \n" /* Set the msp back to the start of the stack. */
" cpsie i \n" /* Globally enable interrupts. */ " cpsie i \n" /* Globally enable interrupts. */
" dsb \n"
" isb \n"
" svc 0 \n" /* System call to start first task. */ " svc 0 \n" /* System call to start first task. */
" nop \n" " nop \n"
); );
@ -366,8 +369,9 @@ portBASE_TYPE xPortStartScheduler( void )
void vPortEndScheduler( void ) void vPortEndScheduler( void )
{ {
/* It is unlikely that the CM4F port will require this function as there /* Not implemented in ports where there is nothing to return to.
is nothing to return to. */ Artificially force an assert. */
configASSERT( uxCriticalNesting == 1000UL );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -394,6 +398,7 @@ void vPortEnterCritical( void )
void vPortExitCritical( void ) void vPortExitCritical( void )
{ {
configASSERT( uxCriticalNesting );
uxCriticalNesting--; uxCriticalNesting--;
if( uxCriticalNesting == 0 ) if( uxCriticalNesting == 0 )
{ {
@ -440,6 +445,7 @@ void xPortPendSVHandler( void )
__asm volatile __asm volatile
( (
" mrs r0, psp \n" " mrs r0, psp \n"
" isb \n"
" \n" " \n"
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n" " ldr r2, [r3] \n"
@ -470,6 +476,7 @@ void xPortPendSVHandler( void )
" vldmiaeq r0!, {s16-s31} \n" " vldmiaeq r0!, {s16-s31} \n"
" \n" " \n"
" msr psp, r0 \n" " msr psp, r0 \n"
" isb \n"
" \n" " \n"
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */ #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */
#if WORKAROUND_PMU_CM001 == 1 #if WORKAROUND_PMU_CM001 == 1
@ -511,7 +518,7 @@ void xPortSysTickHandler( void )
__attribute__((weak)) void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) __attribute__((weak)) void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
{ {
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
portTickType xModifiableIdleTime; portTickType xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */ /* Make sure the SysTick reload value does not overflow the counter. */
@ -524,7 +531,7 @@ void xPortSysTickHandler( void )
is accounted for as best it can be, but using the tickless mode will 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 inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */ 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 /* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way tick periods. -1 is used because this code will execute part way
@ -548,7 +555,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */ /* 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 /* Reset the reload register to the value required for normal tick
periods. */ periods. */
@ -568,7 +575,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */ /* 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 /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains set its parameter to 0 to indicate that its implementation contains
@ -589,13 +596,14 @@ void xPortSysTickHandler( void )
accounted for as best it can be, but using the tickless mode will 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 inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */ 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 the cpsid instruction() /* Re-enable interrupts - see comments above the cpsid instruction()
above. */ above. */
__asm volatile( "cpsie i" ); __asm volatile( "cpsie i" );
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{ {
unsigned long ulCalculatedLoadValue; unsigned long ulCalculatedLoadValue;
@ -647,7 +655,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portENTER_CRITICAL(); 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 ); vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
} }
@ -675,7 +683,7 @@ __attribute__(( weak )) void vPortSetupTimerInterrupt( void )
/* 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_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -357,7 +357,7 @@ void xPortSysTickHandler( void )
__weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
{ {
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
portTickType xModifiableIdleTime; portTickType xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */ /* 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 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 inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */ 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 /* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way 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; portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */ /* 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 /* Reset the reload register to the value required for normal tick
periods. */ periods. */
@ -414,7 +414,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */ /* 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 /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains 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 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 inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */ 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() /* Re-enable interrupts - see comments above __disable_interrupt()
call above. */ call above. */
__enable_interrupt(); __enable_interrupt();
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{ {
unsigned long ulCalculatedLoadValue; unsigned long ulCalculatedLoadValue;
@ -493,7 +494,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portENTER_CRITICAL(); 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 ); vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
} }
@ -521,7 +522,7 @@ __weak void vPortSetupTimerInterrupt( void )
/* 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_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 All rights reserved
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
@ -82,9 +82,10 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
xPortPendSVHandler: xPortPendSVHandler:
mrs r0, psp mrs r0, psp
isb
ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */
ldr r2, [r3] ldr r2, [r3]
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. */
@ -92,16 +93,17 @@ xPortPendSVHandler:
stmdb sp!, {r3, r14} stmdb sp!, {r3, r14}
mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r0 msr basepri, r0
bl vTaskSwitchContext bl vTaskSwitchContext
mov r0, #0 mov r0, #0
msr basepri, r0 msr basepri, r0
ldmia sp!, {r3, r14} ldmia sp!, {r3, r14}
ldr r1, [r3] ldr r1, [r3]
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
ldmia r0!, {r4-r11} /* Pop the registers. */ ldmia r0!, {r4-r11} /* Pop the registers. */
msr psp, r0 msr psp, r0
bx r14 isb
bx r14
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -111,7 +113,7 @@ ulPortSetInterruptMask:
mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY mov r1, #configMAX_SYSCALL_INTERRUPT_PRIORITY
msr basepri, r1 msr basepri, r1
bx r14 bx r14
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
vPortClearInterruptMask: vPortClearInterruptMask:
@ -128,6 +130,7 @@ vPortSVCHandler:
/* Pop the core registers. */ /* Pop the core registers. */
ldmia r0!, {r4-r11} ldmia r0!, {r4-r11}
msr psp, r0 msr psp, r0
isb
mov r0, #0 mov r0, #0
msr basepri, r0 msr basepri, r0
orr r14, r14, #13 orr r14, r14, #13
@ -144,7 +147,8 @@ vPortStartFirstTask
msr msp, r0 msr msp, r0
/* Call SVC to start the first task. */ /* Call SVC to start the first task. */
cpsie i cpsie i
dsb
isb
svc 0 svc 0
END END

View file

@ -383,7 +383,7 @@ void xPortSysTickHandler( void )
__weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
{ {
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
portTickType xModifiableIdleTime; portTickType xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */ /* 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 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 inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */ 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 /* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way 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; portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */ /* 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 /* Reset the reload register to the value required for normal tick
periods. */ periods. */
@ -440,7 +440,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */ /* 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 /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains 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 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 inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */ 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() /* Re-enable interrupts - see comments above __disable_interrupt()
call above. */ call above. */
__enable_interrupt(); __enable_interrupt();
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{ {
unsigned long ulCalculatedLoadValue; unsigned long ulCalculatedLoadValue;
@ -519,7 +520,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portENTER_CRITICAL(); 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 ); vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
} }
@ -547,7 +548,7 @@ __weak void vPortSetupTimerInterrupt( void )
/* 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_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

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

View file

@ -243,6 +243,7 @@ __asm void vPortSVCHandler( void )
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
ldmia r0!, {r4-r11} /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ ldmia r0!, {r4-r11} /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */
msr psp, r0 /* Restore the task stack pointer. */ msr psp, r0 /* Restore the task stack pointer. */
isb
mov r0, #0 mov r0, #0
msr basepri, r0 msr basepri, r0
orr r14, #0xd orr r14, #0xd
@ -262,6 +263,8 @@ __asm void prvStartFirstTask( void )
msr msp, r0 msr msp, r0
/* Globally enable interrupts. */ /* Globally enable interrupts. */
cpsie i cpsie i
dsb
isb
/* Call SVC to start the first task. */ /* Call SVC to start the first task. */
svc 0 svc 0
nop nop
@ -385,6 +388,7 @@ __asm void xPortPendSVHandler( void )
PRESERVE8 PRESERVE8
mrs r0, psp mrs r0, psp
isb
ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */ ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */
ldr r2, [r3] ldr r2, [r3]
@ -404,6 +408,7 @@ __asm void xPortPendSVHandler( void )
ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */ ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
ldmia r0!, {r4-r11} /* Pop the registers and the critical nesting count. */ ldmia r0!, {r4-r11} /* Pop the registers and the critical nesting count. */
msr psp, r0 msr psp, r0
isb
bx r14 bx r14
nop nop
} }
@ -433,7 +438,7 @@ void xPortSysTickHandler( void )
__weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
{ {
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
portTickType xModifiableIdleTime; portTickType xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */ /* Make sure the SysTick reload value does not overflow the counter. */
@ -446,7 +451,7 @@ void xPortSysTickHandler( void )
is accounted for as best it can be, but using the tickless mode will 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 inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */ 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 /* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way tick periods. -1 is used because this code will execute part way
@ -470,7 +475,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */ /* 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 /* Reset the reload register to the value required for normal tick
periods. */ periods. */
@ -490,7 +495,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */ /* 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 /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains set its parameter to 0 to indicate that its implementation contains
@ -511,13 +516,14 @@ void xPortSysTickHandler( void )
accounted for as best it can be, but using the tickless mode will 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 inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */ 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_irq() call /* Re-enable interrupts - see comments above __disable_irq() call
above. */ above. */
__enable_irq(); __enable_irq();
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{ {
unsigned long ulCalculatedLoadValue; unsigned long ulCalculatedLoadValue;
@ -569,7 +575,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portENTER_CRITICAL(); 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 ); vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
} }
@ -600,7 +606,7 @@ void xPortSysTickHandler( void )
/* 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_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
} }
#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */ #endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */

View file

@ -266,6 +266,7 @@ __asm void vPortSVCHandler( void )
/* Pop the core registers. */ /* Pop the core registers. */
ldmia r0!, {r4-r11, r14} ldmia r0!, {r4-r11, r14}
msr psp, r0 msr psp, r0
isb
mov r0, #0 mov r0, #0
msr basepri, r0 msr basepri, r0
bx r14 bx r14
@ -284,6 +285,8 @@ __asm void prvStartFirstTask( void )
msr msp, r0 msr msp, r0
/* Globally enable interrupts. */ /* Globally enable interrupts. */
cpsie i cpsie i
dsb
isb
/* Call SVC to start the first task. */ /* Call SVC to start the first task. */
svc 0 svc 0
nop nop
@ -429,7 +432,7 @@ __asm void xPortPendSVHandler( void )
PRESERVE8 PRESERVE8
mrs r0, psp mrs r0, psp
isb
/* Get the location of the current TCB. */ /* Get the location of the current TCB. */
ldr r3, =pxCurrentTCB ldr r3, =pxCurrentTCB
ldr r2, [r3] ldr r2, [r3]
@ -467,11 +470,12 @@ __asm void xPortPendSVHandler( void )
vldmiaeq r0!, {s16-s31} vldmiaeq r0!, {s16-s31}
msr psp, r0 msr psp, r0
isb
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */ #ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */
#if WORKAROUND_PMU_CM001 == 1 #if WORKAROUND_PMU_CM001 == 1
push { r14 } push { r14 }
pop { pc } pop { pc }
nop
#endif #endif
#endif #endif
@ -504,7 +508,7 @@ void xPortSysTickHandler( void )
__weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime ) __weak void vPortSuppressTicksAndSleep( portTickType xExpectedIdleTime )
{ {
unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements; unsigned long ulReloadValue, ulCompleteTickPeriods, ulCompletedSysTickDecrements, ulSysTickCTRL;
portTickType xModifiableIdleTime; portTickType xModifiableIdleTime;
/* Make sure the SysTick reload value does not overflow the counter. */ /* Make sure the SysTick reload value does not overflow the counter. */
@ -517,7 +521,7 @@ void xPortSysTickHandler( void )
is accounted for as best it can be, but using the tickless mode will 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 inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */ 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 /* Calculate the reload value required to wait xExpectedIdleTime
tick periods. -1 is used because this code will execute part way tick periods. -1 is used because this code will execute part way
@ -541,7 +545,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG; portNVIC_SYSTICK_LOAD_REG = portNVIC_SYSTICK_CURRENT_VALUE_REG;
/* Restart SysTick. */ /* 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 /* Reset the reload register to the value required for normal tick
periods. */ periods. */
@ -561,7 +565,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
/* Restart SysTick. */ /* 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 /* Sleep until something happens. configPRE_SLEEP_PROCESSING() can
set its parameter to 0 to indicate that its implementation contains set its parameter to 0 to indicate that its implementation contains
@ -582,13 +586,14 @@ void xPortSysTickHandler( void )
accounted for as best it can be, but using the tickless mode will 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 inevitably result in some tiny drift of the time maintained by the
kernel with respect to calendar time. */ 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_irq() call /* Re-enable interrupts - see comments above __disable_irq() call
above. */ above. */
__enable_irq(); __enable_irq();
if( ( portNVIC_SYSTICK_CTRL_REG & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 ) if( ( ulSysTickCTRL & portNVIC_SYSTICK_COUNT_FLAG_BIT ) != 0 )
{ {
unsigned long ulCalculatedLoadValue; unsigned long ulCalculatedLoadValue;
@ -640,7 +645,7 @@ void xPortSysTickHandler( void )
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL; portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;
portENTER_CRITICAL(); 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 ); vTaskStepTick( ulCompleteTickPeriods );
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL; portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
} }
@ -671,7 +676,7 @@ void xPortSysTickHandler( void )
/* 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_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
} }
#endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */ #endif /* configOVERRIDE_DEFAULT_TICK_CONFIGURATION */

View file

@ -73,6 +73,7 @@
_vector_14: .type func _vector_14: .type func
mrs r0, psp mrs r0, psp
isb
;Get the location of the current TCB. ;Get the location of the current TCB.
ldr.w r3, =pxCurrentTCB ldr.w r3, =pxCurrentTCB
@ -110,6 +111,7 @@ _vector_14: .type func
vldmiaeq r0!, {s16-s31} vldmiaeq r0!, {s16-s31}
msr psp, r0 msr psp, r0
isb
bx r14 bx r14
.size _vector_14, $-_vector_14 .size _vector_14, $-_vector_14
@ -125,6 +127,7 @@ _vector_14: .type func
_lc_ref__vector_pp_14: .type func _lc_ref__vector_pp_14: .type func
mrs r0, psp mrs r0, psp
isb
;Get the location of the current TCB. ;Get the location of the current TCB.
ldr.w r3, =pxCurrentTCB ldr.w r3, =pxCurrentTCB
@ -162,6 +165,7 @@ _lc_ref__vector_pp_14: .type func
vldmiaeq r0!, {s16-s31} vldmiaeq r0!, {s16-s31}
msr psp, r0 msr psp, r0
isb
push { lr } push { lr }
pop { pc } ; XMC4000 specific errata workaround. Do not used "bx lr" here. pop { pc } ; XMC4000 specific errata workaround. Do not used "bx lr" here.
@ -181,6 +185,7 @@ SVC_Handler: .type func
;Pop the core registers. ;Pop the core registers.
ldmia r0!, {r4-r11, r14} ldmia r0!, {r4-r11, r14}
msr psp, r0 msr psp, r0
isb
mov r0, #0 mov r0, #0
msr basepri, r0 msr basepri, r0
bx r14 bx r14
@ -201,6 +206,8 @@ vPortStartFirstTask .type func
msr msp, r0 msr msp, r0
;Call SVC to start the first task. ;Call SVC to start the first task.
cpsie i cpsie i
dsb
isb
svc 0 svc 0
.size vPortStartFirstTask, $-vPortStartFirstTask .size vPortStartFirstTask, $-vPortStartFirstTask
.endsec .endsec

View file

@ -242,12 +242,12 @@ portBASE_TYPE xReturn = pdFAIL;
{ {
/* Create the timer task, storing its handle in xTimerTaskHandle so /* Create the timer task, storing its handle in xTimerTaskHandle so
it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */ it can be returned by the xTimerGetTimerDaemonTaskHandle() function. */
xReturn = xTaskCreate( prvTimerTask, ( const signed char * const ) "Tmr Svc", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle ); xReturn = xTaskCreate( prvTimerTask, ( signed char * ) "Tmr Svc", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, &xTimerTaskHandle );
} }
#else #else
{ {
/* Create the timer task without storing its handle. */ /* Create the timer task without storing its handle. */
xReturn = xTaskCreate( prvTimerTask, ( const signed char * const ) "Tmr Svc", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, NULL); xReturn = xTaskCreate( prvTimerTask, ( signed char * ) "Tmr Svc", ( unsigned short ) configTIMER_TASK_STACK_DEPTH, NULL, ( ( unsigned portBASE_TYPE ) configTIMER_TASK_PRIORITY ) | portPRIVILEGE_BIT, NULL);
} }
#endif #endif
} }