\r
***************************************************************************\r
\r
- Please ensure to read the configuration and relevant port sections of the \r
+ Please ensure to read the configuration and relevant port sections of the\r
online documentation.\r
\r
+++ http://www.FreeRTOS.org +++\r
- Documentation, latest information, license and contact details. \r
+ Documentation, latest information, license and contact details.\r
\r
+++ http://www.SafeRTOS.com +++\r
A version that is certified for use in safety critical systems.\r
#define portNVIC_SYSTICK_LOAD ( ( volatile unsigned portLONG *) 0xe000e014 )\r
#define portNVIC_INT_CTRL ( ( volatile unsigned portLONG *) 0xe000ed04 )\r
#define portNVIC_SYSPRI2 ( ( volatile unsigned portLONG *) 0xe000ed20 )\r
-#define portNVIC_SYSPRI1 ( ( volatile unsigned portLONG *) 0xe000ed1c )\r
#define portNVIC_SYSTICK_CLK 0x00000004\r
#define portNVIC_SYSTICK_INT 0x00000002\r
#define portNVIC_SYSTICK_ENABLE 0x00000001\r
static void prvSetupTimerInterrupt( void );\r
\r
/*\r
- * Set the MSP/PSP to a known value.\r
+ * Exception handlers.\r
*/\r
-extern void vSetMSP( unsigned long ulValue );\r
-extern void vSetPSP( unsigned long ulValue );\r
+void xPortSysTickHandler( void );\r
\r
/*\r
- * Utilities called from the assembler code.\r
+ * Start first task is a separate function so it can be tested in isolation.\r
*/\r
-void vPortSwitchContext( void );\r
-void vPortIncrementTick( void );\r
+extern void vPortStartFirstTask( unsigned portLONG ulValue );\r
\r
/*-----------------------------------------------------------*/\r
\r
pxTopOfStack--;\r
*pxTopOfStack = ( portSTACK_TYPE ) pxCode; /* PC */\r
pxTopOfStack--;\r
- *pxTopOfStack = 0xfffffffd; /* LR */\r
+ *pxTopOfStack = 0; /* LR */\r
pxTopOfStack -= 5; /* R12, R3, R2 and R1. */\r
*pxTopOfStack = ( portSTACK_TYPE ) pvParameters; /* R0 */\r
pxTopOfStack -= 9; /* R11, R10, R9, R8, R7, R6, R5 and R4. */\r
prvSetupTimerInterrupt();\r
\r
/* Start the first task. */\r
- vSetPSP( 0 );\r
- vSetMSP( *((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
/*-----------------------------------------------------------*/\r
\r
+void xPortSysTickHandler( void )\r
+{\r
+ vTaskIncrementTick();\r
+ \r
+ /* If using preemption, also force a context switch. */\r
+ #if configUSE_PREEMPTION == 1\r
+ *(portNVIC_INT_CTRL) |= portNVIC_PENDSVSET; \r
+ #endif\r
+}\r
+/*-----------------------------------------------------------*/\r
\r
/*\r
* Setup the systick timer to generate the tick interrupts at the required\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
***************************************************************************\r
\r
- Please ensure to read the configuration and relevant port sections of the \r
+ Please ensure to read the configuration and relevant port sections of the\r
online documentation.\r
\r
+++ http://www.FreeRTOS.org +++\r
- Documentation, latest information, license and contact details. \r
+ Documentation, latest information, license and contact details.\r
\r
+++ http://www.SafeRTOS.com +++\r
A version that is certified for use in safety critical systems.\r
thumb\r
\r
EXTERN vPortYieldFromISR\r
- EXTERN vPortSwitchContext\r
- EXTERN vPortIncrementTick\r
EXTERN uxCriticalNesting\r
EXTERN pxCurrentTCB\r
+ EXTERN vTaskSwitchContext\r
\r
- PUBLIC vSetPSP\r
PUBLIC vSetMSP\r
PUBLIC xPortPendSVHandler\r
- PUBLIC xPortSysTickHandler\r
PUBLIC vPortSetInterruptMask\r
PUBLIC vPortClearInterruptMask\r
+ PUBLIC vPortSVCHandler\r
+ PUBLIC vPortStartFirstTask\r
\r
\r
-vSetPSP:\r
- msr psp, r0\r
- bx lr\r
- \r
/*-----------------------------------------------------------*/\r
\r
vSetMSP\r
\r
xPortPendSVHandler:\r
mrs r0, psp \r
- cbz r0, no_save \r
- /* Save the context into the TCB. */\r
- stmdb r0!, {r4-r11} \r
- sub r0, r0, #0x04 \r
- ldr r1, =uxCriticalNesting\r
- ldr r2, =pxCurrentTCB \r
- ldr r1, [r1] \r
- ldr r2, [r2] \r
- str r1, [r0] \r
- str r0, [r2] \r
- \r
-no_save:\r
- push {r14} \r
- bl vPortSwitchContext \r
- pop {r14} \r
- /* Restore the context. */ \r
- ldr r1, =pxCurrentTCB\r
+ ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */\r
+ ldr r2, [r3] \r
+\r
+ ldr r1, =uxCriticalNesting /* Save the remaining registers and the critical nesting count onto the task stack. */\r
ldr r1, [r1] \r
- ldr r0, [r1] \r
- ldmia r0!, {r1, r4-r11} \r
- ldr r2, =uxCriticalNesting\r
- str r1, [r2] \r
+ stmdb r0!, {r1,r4-r11} \r
+ str r0, [r2] /* Save the new top of stack into the first member of the TCB. */\r
+\r
+ stmdb sp!, {r3, r14} \r
+ bl vTaskSwitchContext \r
+ ldmia sp!, {r3, r14} \r
+\r
+ ldr r1, [r3] \r
+ ldr r2, =uxCriticalNesting \r
+ ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */\r
+ ldmia r0!, {r1, r4-r11} /* Pop the registers and the critical nesting count. */\r
+ str r1, [r2] /* Save the new critical nesting value into ulCriticalNesting. */\r
msr psp, r0 \r
- orr r14, r14, #0xd \r
- /* Exit with interrupts in the state required by the task. */\r
- cbnz r1, sv_disable_interrupts \r
+ orr r14, r14, #13 \r
+\r
+ cbnz r1, sv_disable_interrupts /* If the nesting count is greater than 0 we need to exit with interrupts masked. */\r
bx r14 \r
- \r
+\r
sv_disable_interrupts: \r
mov r1, #configKERNEL_INTERRUPT_PRIORITY\r
- msr basepri, R1\r
+ msr basepri, r1\r
bx r14 \r
\r
-\r
-/*-----------------------------------------------------------*/\r
-\r
-xPortSysTickHandler:\r
- /* Call the scheduler tick function. */\r
- push {r14}\r
- bl vPortIncrementTick\r
- pop {r14}\r
- \r
- /* If using preemption, also force a context switch. */\r
- #if configUSE_PREEMPTION == 1\r
- push {r14}\r
- bl vPortYieldFromISR\r
- pop {r14}\r
- #endif\r
-\r
- /* Exit with interrupts in the correct state. */\r
- ldr r2, =uxCriticalNesting\r
- ldr r2, [r2]\r
- cbnz r2, tick_disable_interrupts\r
- bx r14\r
-\r
-tick_disable_interrupts:\r
- mov r1, #configKERNEL_INTERRUPT_PRIORITY\r
- msr basepri, R1\r
- \r
- bx r14\r
-\r
/*-----------------------------------------------------------*/\r
\r
vPortSetInterruptMask:\r
\r
/*-----------------------------------------------------------*/\r
\r
+vPortSVCHandler;\r
+ ldr r3, =pxCurrentTCB\r
+ ldr r1, [r3]\r
+ ldr r0, [r1]\r
+ ldmia r0!, {r1, r4-r11}\r
+ ldr r2, =uxCriticalNesting\r
+ str r1, [r2]\r
+ msr psp, r0\r
+ orr r14, r14, #13\r
+ bx r14\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+vPortStartFirstTask\r
+ msr msp, r0\r
+ svc 0\r
+\r
+\r
END\r
\ No newline at end of file