***************************************************************************\r
*/\r
\r
-/*\r
- Changes between V4.0.0 and V4.0.1\r
-\r
- + Reduced the code used to setup the initial stack frame.\r
- + The kernel no longer has to install or handle the fault interrupt.\r
- \r
- Change from V4.4.0:\r
-\r
- + Introduced usage of configKERNEL_INTERRUPT_PRIORITY macro to set the\r
- interrupt priority used by the kernel.\r
-*/\r
-\r
-\r
/*-----------------------------------------------------------\r
* Implementation of functions defined in portable.h for the ARM CM3 port.\r
*----------------------------------------------------------*/\r
* Exception handlers.\r
*/\r
void xPortPendSVHandler( void ) __attribute__ (( naked ));\r
-void xPortSysTickHandler( void ) __attribute__ (( naked ));\r
+void xPortSysTickHandler( void );\r
+void vPortSVCHandler( void ) __attribute__ (( naked ));\r
\r
/*\r
- * Set the MSP/PSP to a known value.\r
+ * Start first task is a separate function so it can be tested in isolation.\r
*/\r
-void prvSetMSP( unsigned long ulValue ) __attribute__ (( naked ));\r
-void prvSetPSP( unsigned long ulValue ) __attribute__ (( naked )); \r
+void vPortStartFirstTask( unsigned long ulValue ) __attribute__ (( naked ));\r
\r
/*-----------------------------------------------------------*/\r
\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void prvSetPSP( unsigned long ulValue )\r
+void vPortSVCHandler( void )\r
{\r
- asm volatile( "msr psp, r0" );\r
- asm volatile( "bx lr" );\r
+ asm volatile (\r
+ " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */\r
+ " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */\r
+ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */\r
+ " ldmia r0!, {r1, r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */\r
+ " ldr r2, uxCriticalNestingConst2 \n" /* Restore the critical nesting count used by the task. */\r
+ " str r1, [r2] \n"\r
+ " msr psp, r0 \n" /* Restore the task stack pointer. */\r
+ " orr r14, #0xd \n"\r
+ " bx r14 \n"\r
+ " \n"\r
+ " .align 2 \n"\r
+ "pxCurrentTCBConst2: .word pxCurrentTCB \n"\r
+ "uxCriticalNestingConst2: .word uxCriticalNesting \n"\r
+ );\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void prvSetMSP( unsigned long ulValue )\r
+void vPortStartFirstTask( unsigned long ulValue )\r
{\r
- asm volatile( "msr msp, r0" );\r
- asm volatile( "bx lr" );\r
+ /* ulValue is used from the asm code, but the compiler does not know\r
+ this so remove the warning. */\r
+ ( void ) ulValue;\r
+ \r
+ asm volatile( \r
+ " msr msp, r0 \n" /* Set the msp back to the start of the stack. */\r
+ " svc 0 \n" /* System call to start first task. */\r
+ );\r
}\r
/*-----------------------------------------------------------*/\r
\r
prvSetupTimerInterrupt();\r
\r
/* Start the first task. */\r
- prvSetPSP( 0 );\r
- prvSetMSP( *((unsigned portLONG *) 0 ) );\r
- *(portNVIC_INT_CTRL) |= portNVIC_PENDSVSET;\r
-\r
- /* Enable interrupts */\r
- portENABLE_INTERRUPTS();\r
+ vPortStartFirstTask( *((unsigned portLONG *) 0 ) );\r
\r
/* Should not get here! */\r
return 0;\r
\r
void xPortPendSVHandler( void )\r
{\r
- /* Start first task if the stack has not yet been setup. */\r
+ /* This is a naked function. */\r
+\r
__asm volatile\r
( \r
- " mrs r0, psp \n"\r
- " cbz r0, no_save \n"\r
- " \n" /* Save the context into the TCB. */ \r
- " stmdb r0!, {r4-r11} \n"\r
- " sub r0, #0x04 \n"\r
- " ldr r1, uxCriticalNestingConst \n"\r
- " ldr r2, pxCurrentTCBConst \n"\r
- " ldr r1, [r1] \n"\r
- " ldr r2, [r2] \n"\r
- " str r1, [r0] \n" \r
- " str r0, [r2] \n"\r
+ " mrs r0, psp \n" \r
" \n"\r
- "no_save:\n" \r
- " push {r14} \n"\r
- " bl vPortSwitchContext \n"\r
- " pop {r14} \n"\r
- " \n" /* Restore the context. */ \r
- " ldr r1, pxCurrentTCBConst \n"\r
+ " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */\r
+ " ldr r2, [r3] \n" \r
+ " \n" \r
+ " ldr r1, uxCriticalNestingConst \n" /* Save the remaining registers and the critical nesting count onto the task stack. */\r
" ldr r1, [r1] \n"\r
- " ldr r0, [r1] \n"\r
- " ldmia r0!, {r1, r4-r11} \n"\r
+ " stmdb r0!, {r1,r4-r11} \n"\r
+ " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */\r
+ " \n"\r
+ " stmdb sp!, {r3, r14} \n" \r
+ " bl vTaskSwitchContext \n"\r
+ " ldmia sp!, {r3, r14} \n"\r
+ " \n" /* Restore the context, including the critical nesting count. */\r
+ " ldr r1, [r3] \n" \r
" ldr r2, uxCriticalNestingConst \n"\r
- " str r1, [r2] \n"\r
- " msr psp, r0 \n"\r
+ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */\r
+ " ldmia r0!, {r1, r4-r11} \n" /* Pop the registers and the critical nesting count. */\r
+ " str r1, [r2] \n" /* Save the new critical nesting value into ulCriticalNesting. */ \r
+ " msr psp, r0 \n" \r
" orr r14, #0xd \n"\r
" \n" /* Exit with interrupts in the state required by the task. */ \r
- " cbnz r1, sv_disable_interrupts \n"\r
+ " cbnz r1, sv_disable_interrupts \n" /* If the nesting count is greater than 0 we need to exit with interrupts masked. */\r
" bx r14 \n"\r
" \n"\r
- "sv_disable_interrupts: \n"\r
+ "sv_disable_interrupts: \n" \r
" ldr r1, =ulKernelPriority \n"\r
" ldr r1, [r1] \n"\r
" msr basepri, r1 \n"\r
\r
void xPortSysTickHandler( void )\r
{\r
- extern void vTaskIncrementTick( void );\r
- extern void vPortYieldFromISR( void );\r
-\r
- /* Call the scheduler tick function. */\r
- __asm volatile\r
- ( \r
- " push {r14} \n"\r
- " bl vPortIncrementTick \n"\r
- " pop {r14}" \r
- );\r
-\r
+ vTaskIncrementTick();\r
+ \r
/* If using preemption, also force a context switch. */\r
#if configUSE_PREEMPTION == 1\r
- __asm volatile\r
- ( \r
- " push {r14} \n"\r
- " bl vPortYieldFromISR \n"\r
- " pop {r14}" \r
- );\r
+ *(portNVIC_INT_CTRL) |= portNVIC_PENDSVSET; \r
#endif\r
-\r
- /* Exit with interrupts in the correct state. */\r
- __asm volatile\r
- (\r
- " ldr r2, uxCriticalNestingConst2 \n" \r
- " ldr r2, [r2] \n"\r
- " cbnz r2, tick_disable_interrupts \n"\r
- " bx r14" \r
- );\r
-\r
- __asm volatile\r
- (\r
- "tick_disable_interrupts: \n"\r
- " ldr r1, =ulKernelPriority \n"\r
- " ldr r1, [r1] \n"\r
- " msr basepri, r1 \n"\r
- " bx r14 \n"\r
- " \n"\r
- " .align 2 \n"\r
- "uxCriticalNestingConst2: .word uxCriticalNesting"\r
- );\r
}\r
/*-----------------------------------------------------------*/\r
\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vPortSwitchContext( void )\r
-{\r
- vPortSetInterruptMask();\r
- vTaskSwitchContext();\r
- vPortClearInterruptMask();\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-void vPortIncrementTick( void )\r
-{\r
- vPortSetInterruptMask();\r
- vTaskIncrementTick();\r
- vPortClearInterruptMask();\r
-}\r
-\r
-/*-----------------------------------------------------------*/\r
-\r