Introduce the prvTaskExitError() function for all ARM_CMn ports.

Introduce the configTASK_RETURN_ADDRESS macro for the GCC ARM_CMn ports.
Improve time slippage penalty when entering tickless mode is abandoned.
This commit is contained in:
Richard Barry 2013-10-08 11:30:40 +00:00
parent 81e141ad86
commit aedf7824cb
7 changed files with 217 additions and 29 deletions

View file

@ -86,6 +86,15 @@
/* Constants required to set up the initial stack. */ /* Constants required to set up the initial stack. */
#define portINITIAL_XPSR ( 0x01000000 ) #define portINITIAL_XPSR ( 0x01000000 )
/* Let the user override the pre-loading of the initial LR with the address of
prvTaskExitError() in case is messes up unwinding of the stack in the
debugger. */
#ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else
#define portTASK_RETURN_ADDRESS prvTaskExitError
#endif
/* Each task maintains its own interrupt status in the critical nesting /* Each task maintains its own interrupt status in the critical nesting
variable. */ variable. */
static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa;
@ -126,7 +135,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) prvTaskExitError; /* LR */ *pxTopOfStack = ( portSTACK_TYPE ) portTASK_RETURN_ADDRESS; /* LR */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */
pxTopOfStack -= 8; /* R11..R4. */ pxTopOfStack -= 8; /* R11..R4. */

View file

@ -118,6 +118,15 @@ occurred while the SysTick counter is stopped during tickless idle
calculations. */ calculations. */
#define portMISSED_COUNTS_FACTOR ( 45UL ) #define portMISSED_COUNTS_FACTOR ( 45UL )
/* Let the user override the pre-loading of the initial LR with the address of
prvTaskExitError() in case is messes up unwinding of the stack in the
debugger. */
#ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else
#define portTASK_RETURN_ADDRESS prvTaskExitError
#endif
/* Each task maintains its own interrupt status in the critical nesting /* Each task maintains its own interrupt status in the critical nesting
variable. */ variable. */
static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa;
@ -141,6 +150,11 @@ void vPortSVCHandler( void ) __attribute__ (( naked ));
*/ */
static void prvPortStartFirstTask( void ) __attribute__ (( naked )); static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
@ -191,7 +205,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0; /* LR */ *pxTopOfStack = ( portSTACK_TYPE ) portTASK_RETURN_ADDRESS; /* LR */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
@ -200,6 +214,20 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvTaskExitError( void )
{
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ;; );
}
/*-----------------------------------------------------------*/
void vPortSVCHandler( void ) void vPortSVCHandler( void )
{ {
__asm volatile ( __asm volatile (
@ -465,8 +493,16 @@ void xPortSysTickHandler( void )
to be unsuspended then abandon the low power entry. */ to be unsuspended then abandon the low power entry. */
if( eTaskConfirmSleepModeStatus() == eAbortSleep ) if( eTaskConfirmSleepModeStatus() == eAbortSleep )
{ {
/* Restart from whatever is left in the count register to complete
this tick period. */
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_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick
periods. */
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Re-enable interrupts - see comments above the cpsid instruction() /* Re-enable interrupts - see comments above the cpsid instruction()
above. */ above. */

View file

@ -120,6 +120,15 @@ occurred while the SysTick counter is stopped during tickless idle
calculations. */ calculations. */
#define portMISSED_COUNTS_FACTOR ( 45UL ) #define portMISSED_COUNTS_FACTOR ( 45UL )
/* Let the user override the pre-loading of the initial LR with the address of
prvTaskExitError() in case is messes up unwinding of the stack in the
debugger. */
#ifdef configTASK_RETURN_ADDRESS
#define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS
#else
#define portTASK_RETURN_ADDRESS prvTaskExitError
#endif
/* Each task maintains its own interrupt status in the critical nesting /* Each task maintains its own interrupt status in the critical nesting
variable. */ variable. */
static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa; static unsigned portBASE_TYPE uxCriticalNesting = 0xaaaaaaaa;
@ -148,6 +157,11 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
*/ */
static void vPortEnableVFP( void ) __attribute__ (( naked )); static void vPortEnableVFP( void ) __attribute__ (( naked ));
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
@ -174,7 +188,7 @@ static void prvPortStartFirstTask( void ) __attribute__ (( naked ));
#endif /* configUSE_TICKLESS_IDLE */ #endif /* configUSE_TICKLESS_IDLE */
/* /*
* 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
* a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY. * a priority above configMAX_SYSCALL_INTERRUPT_PRIORITY.
*/ */
@ -202,7 +216,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0; /* LR */ *pxTopOfStack = ( portSTACK_TYPE ) portTASK_RETURN_ADDRESS; /* LR */
/* Save code space by skipping register initialisation. */ /* Save code space by skipping register initialisation. */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
@ -219,6 +233,20 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvTaskExitError( void )
{
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ;; );
}
/*-----------------------------------------------------------*/
void vPortSVCHandler( void ) void vPortSVCHandler( void )
{ {
__asm volatile ( __asm volatile (
@ -406,7 +434,7 @@ void xPortPendSVHandler( void )
( (
" mrs r0, psp \n" " mrs r0, psp \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"
" \n" " \n"
" tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */ " tst r14, #0x10 \n" /* Is the task using the FPU context? If so, push high vfp registers. */
@ -435,6 +463,14 @@ void xPortPendSVHandler( void )
" vldmiaeq r0!, {s16-s31} \n" " vldmiaeq r0!, {s16-s31} \n"
" \n" " \n"
" msr psp, r0 \n" " msr psp, r0 \n"
" \n"
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata workaround. */
#if WORKAROUND_PMU_CM001 == 1
" push { r14 } \n"
" pop { pc } \n"
#endif
#endif
" \n"
" bx r14 \n" " bx r14 \n"
" \n" " \n"
" .align 2 \n" " .align 2 \n"
@ -500,9 +536,17 @@ void xPortSysTickHandler( void )
to be unsuspended then abandon the low power entry. */ to be unsuspended then abandon the low power entry. */
if( eTaskConfirmSleepModeStatus() == eAbortSleep ) if( eTaskConfirmSleepModeStatus() == eAbortSleep )
{ {
/* Restart from whatever is left in the count register to complete
this tick period. */
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_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick
periods. */
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* 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" );

View file

@ -97,7 +97,7 @@
#define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL ) #define portNVIC_PENDSV_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 16UL )
#define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL ) #define portNVIC_SYSTICK_PRI ( ( ( unsigned long ) configKERNEL_INTERRUPT_PRIORITY ) << 24UL )
/* Constants required to check the validity of an interrupt prority. */ /* Constants required to check the validity of an interrupt priority. */
#define portFIRST_USER_INTERRUPT_NUMBER ( 16 ) #define portFIRST_USER_INTERRUPT_NUMBER ( 16 )
#define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 ) #define portNVIC_IP_REGISTERS_OFFSET_16 ( 0xE000E3F0 )
#define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) ) #define portAIRCR_REG ( * ( ( volatile unsigned long * ) 0xE000ED0C ) )
@ -146,6 +146,11 @@ void xPortSysTickHandler( void );
*/ */
extern void vPortStartFirstTask( void ); extern void vPortStartFirstTask( void );
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
@ -196,7 +201,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0; /* LR */ *pxTopOfStack = ( portSTACK_TYPE ) prvTaskExitError; /* LR */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
@ -205,6 +210,20 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvTaskExitError( void )
{
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ;; );
}
/*-----------------------------------------------------------*/
/* /*
* See header file for description. * See header file for description.
*/ */
@ -367,8 +386,16 @@ void xPortSysTickHandler( void )
to be unsuspended then abandon the low power entry. */ to be unsuspended then abandon the low power entry. */
if( eTaskConfirmSleepModeStatus() == eAbortSleep ) if( eTaskConfirmSleepModeStatus() == eAbortSleep )
{ {
/* Restart from whatever is left in the count register to complete
this tick period. */
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_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick
periods. */
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Re-enable interrupts - see comments above __disable_interrupt() /* Re-enable interrupts - see comments above __disable_interrupt()
call above. */ call above. */

View file

@ -81,11 +81,11 @@
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
xPortPendSVHandler: xPortPendSVHandler:
mrs r0, psp mrs r0, psp
/* 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]
/* Is the task using the FPU context? If so, push high vfp registers. */ /* Is the task using the FPU context? If so, push high vfp registers. */
tst r14, #0x10 tst r14, #0x10
@ -93,34 +93,42 @@ xPortPendSVHandler:
vstmdbeq r0!, {s16-s31} vstmdbeq r0!, {s16-s31}
/* Save the core registers. */ /* Save the core registers. */
stmdb r0!, {r4-r11, r14} stmdb r0!, {r4-r11, r14}
/* 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]
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}
/* The first item in pxCurrentTCB is the task top of stack. */ /* The first item in pxCurrentTCB is the task top of stack. */
ldr r1, [r3] ldr r1, [r3]
ldr r0, [r1] ldr r0, [r1]
/* Pop the core registers. */ /* Pop the core registers. */
ldmia r0!, {r4-r11, r14} ldmia r0!, {r4-r11, r14}
/* Is the task using the FPU context? If so, pop the high vfp registers /* Is the task using the FPU context? If so, pop the high vfp registers
too. */ too. */
tst r14, #0x10 tst r14, #0x10
it eq it eq
vldmiaeq r0!, {s16-s31} vldmiaeq r0!, {s16-s31}
msr psp, r0 msr psp, r0
bx r14
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */
#if WORKAROUND_PMU_CM001 == 1
push { r14 }
pop { pc }
#endif
#endif
bx r14
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -130,7 +138,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:
@ -148,7 +156,7 @@ vPortSVCHandler:
ldmia r0!, {r4-r11, r14} ldmia r0!, {r4-r11, r14}
msr psp, r0 msr psp, r0
mov r0, #0 mov r0, #0
msr basepri, r0 msr basepri, r0
bx r14 bx r14
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -170,13 +178,13 @@ vPortEnableVFP:
/* The FPU enable bits are in the CPACR. */ /* The FPU enable bits are in the CPACR. */
ldr.w r0, =0xE000ED88 ldr.w r0, =0xE000ED88
ldr r1, [r0] ldr r1, [r0]
/* Enable CP10 and CP11 coprocessors, then save back. */ /* Enable CP10 and CP11 coprocessors, then save back. */
orr r1, r1, #( 0xf << 20 ) orr r1, r1, #( 0xf << 20 )
str r1, [r0] str r1, [r0]
bx r14 bx r14
END END

View file

@ -154,6 +154,11 @@ void vPortSVCHandler( void );
*/ */
static void prvStartFirstTask( void ); static void prvStartFirstTask( void );
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
@ -204,7 +209,8 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0; /* LR */ *pxTopOfStack = ( portSTACK_TYPE ) prvTaskExitError; /* LR */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */ *pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */
pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */ pxTopOfStack -= 8; /* R11, R10, R9, R8, R7, R6, R5 and R4. */
@ -213,6 +219,20 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvTaskExitError( void )
{
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ;; );
}
/*-----------------------------------------------------------*/
__asm void vPortSVCHandler( void ) __asm void vPortSVCHandler( void )
{ {
PRESERVE8 PRESERVE8
@ -442,8 +462,16 @@ void xPortSysTickHandler( void )
to be unsuspended then abandon the low power entry. */ to be unsuspended then abandon the low power entry. */
if( eTaskConfirmSleepModeStatus() == eAbortSleep ) if( eTaskConfirmSleepModeStatus() == eAbortSleep )
{ {
/* Restart from whatever is left in the count register to complete
this tick period. */
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_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick
periods. */
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Re-enable interrupts - see comments above __disable_irq() call /* Re-enable interrupts - see comments above __disable_irq() call
above. */ above. */

View file

@ -163,6 +163,12 @@ static void prvStartFirstTask( void );
* Functions defined in portasm.s to enable the VFP. * Functions defined in portasm.s to enable the VFP.
*/ */
static void prvEnableVFP( void ); static void prvEnableVFP( void );
/*
* Used to catch tasks that attempt to return from their implementing function.
*/
static void prvTaskExitError( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
/* /*
@ -217,7 +223,7 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */ *pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */
pxTopOfStack--; pxTopOfStack--;
*pxTopOfStack = 0; /* LR */ *pxTopOfStack = ( portSTACK_TYPE ) prvTaskExitError; /* LR */
/* Save code space by skipping register initialisation. */ /* Save code space by skipping register initialisation. */
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */ pxTopOfStack -= 5; /* R12, R3, R2 and R1. */
@ -234,6 +240,20 @@ portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvTaskExitError( void )
{
/* A function that implements a task must not exit or attempt to return to
its caller as there is nothing to return to. If a task wants to exit it
should instead call vTaskDelete( NULL ).
Artificially force an assert() to be triggered if configASSERT() is
defined, then stop here so application writers can catch the error. */
configASSERT( uxCriticalNesting == ~0UL );
portDISABLE_INTERRUPTS();
for( ;; );
}
/*-----------------------------------------------------------*/
__asm void vPortSVCHandler( void ) __asm void vPortSVCHandler( void )
{ {
PRESERVE8 PRESERVE8
@ -444,6 +464,14 @@ __asm void xPortPendSVHandler( void )
vldmiaeq r0!, {s16-s31} vldmiaeq r0!, {s16-s31}
msr psp, r0 msr psp, r0
#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */
#if WORKAROUND_PMU_CM001 == 1
push { r14 }
pop { pc }
#endif
#endif
bx r14 bx r14
nop nop
} }
@ -505,8 +533,16 @@ void xPortSysTickHandler( void )
to be unsuspended then abandon the low power entry. */ to be unsuspended then abandon the low power entry. */
if( eTaskConfirmSleepModeStatus() == eAbortSleep ) if( eTaskConfirmSleepModeStatus() == eAbortSleep )
{ {
/* Restart from whatever is left in the count register to complete
this tick period. */
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_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT;
/* Reset the reload register to the value required for normal tick
periods. */
portNVIC_SYSTICK_LOAD_REG = ulTimerCountsForOneTick - 1UL;
/* Re-enable interrupts - see comments above __disable_irq() call /* Re-enable interrupts - see comments above __disable_irq() call
above. */ above. */