\r
/*-----------------------------------------------------------*/\r
\r
-/* Dimensions the array into which the floating point context is saved. \r
-Allocate enough space for FPR0 to FPR15, FPUL and FPSCR, each of which is 4\r
-bytes big. If this number is changed then the 72 in portasm.src also needs\r
-changing. */\r
-#define portFLOP_REGISTERS_TO_STORE ( 18 )\r
-#define portFLOP_STORAGE_SIZE ( portFLOP_REGISTERS_TO_STORE * 4 )\r
-\r
/* Tasks should start with interrupts enabled, therefore PSW is set with U,I,PM \r
flags set and IPL clear. */\r
-#define portINITIAL_PSW ( ( portSTACK_TYPE ) 0x00130000 )\r
+/* \r
+ U = 1 User stack pointer.\r
+ I = 1 Interrupts enabled.\r
+ PM = 0 Supervisor mode.\r
+ IPL = 0 All interrupt priorities enabled.\r
+*/\r
+#define portINITIAL_PSW ( ( portSTACK_TYPE ) 0x00030000 )\r
#define portINITIAL_FPSW ( ( portSTACK_TYPE ) 0x00000100 )\r
\r
\r
*/\r
void vPortStartFirstTask( void );\r
\r
+void vPortPendContextSwitch( void );\r
+\r
+static void prvStartFirstTask( void );\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+extern void *pxCurrentTCB;\r
+\r
+unsigned char ucIPLToRestore = 0;\r
+\r
/*-----------------------------------------------------------*/\r
\r
/* \r
{\r
extern void vApplicationSetupTimerInterrupt( void );\r
\r
- /* Call an application function to set up the timer that will generate the\r
- tick interrupt. This way the application can decide which peripheral to \r
- use. A demo application is provided to show a suitable example. */\r
- vApplicationSetupTimerInterrupt();\r
+ /* Use pxCurrentTCB just so it does not get optimised away. */\r
+ if( pxCurrentTCB != NULL )\r
+ {\r
+ /* Call an application function to set up the timer that will generate the\r
+ tick interrupt. This way the application can decide which peripheral to \r
+ use. A demo application is provided to show a suitable example. */\r
+ vApplicationSetupTimerInterrupt();\r
\r
- /* Start the first task. This will only restore the standard registers and\r
- not the flop registers. This does not really matter though because the only\r
- flop register that is initialised to a particular value is fpscr, and it is\r
- only initialised to the current value, which will still be the current value\r
- when the first task starts executing. */\r
- //trapa( portSTART_SCHEDULER_TRAP_NO );\r
+ /* Start the first task. */\r
+ prvStartFirstTask();\r
+ }\r
\r
/* Should not get here. */\r
return pdFAIL;\r
}\r
/*-----------------------------------------------------------*/\r
\r
+#pragma interrupt (vTickISR(vect=configTICK_VECTOR,enable))\r
+void vTickISR( void )\r
+{\r
+ /* Restore previous IPL on exit. */\r
+ //set_ipl( configMAX_SYSCALL_INTERRUPT_PRIORITY );\r
+ \r
+ /* Clear the interrupt. */\r
+ vTaskIncrementTick();\r
+ \r
+ #if( configUSE_PREEMPTION == 1 )\r
+ taskYIELD();\r
+ #endif\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vPortSetInterruptMask( void )\r
+{\r
+unsigned char ucPreviousIPL;\r
+\r
+ /* Store the current IPL to ensure it is restored correctly later if it is\r
+ not currently 0. This is a stack variable, so there should not be a race\r
+ condition even if there is an interrupt or context switch before the new\r
+ IPL value gets set. */\r
+ ucPreviousIPL = get_ipl();\r
+ \r
+ /* Set the mask up to the max syscall priority. */\r
+ set_ipl( configMAX_SYSCALL_INTERRUPT_PRIORITY );\r
+ \r
+ /* Now the mask is set there will not be a context switch, so the previous\r
+ and current IPL values can be compared. This ensures against the IPL being\r
+ set back to zero too early when critical sections nest. */\r
+ if( ucPreviousIPL < configMAX_SYSCALL_INTERRUPT_PRIORITY )\r
+ {\r
+ ucIPLToRestore = ucPreviousIPL;\r
+ }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+#pragma inline_asm prvStartFirstTask\r
+static void prvStartFirstTask( void )\r
+{\r
+ /* When starting the scheduler there is nothing that needs moving to the\r
+ interrupt stack because the function is not called from an interrupt.\r
+ Just ensure the current stack is the user stack. */\r
+ SETPSW U\r
+\r
+ /* Obtain the location of the stack associated with which ever task \r
+ pxCurrentTCB is currently pointing to. */\r
+ MOV.L #_pxCurrentTCB,R15\r
+ MOV.L [R15],R15\r
+ MOV.L [R15],R0\r
+\r
+ /* Restore the registers from the stack of the task pointed to by \r
+ pxCurrentTCB. */\r
+ POP R15\r
+ MVTACLO R15 /* Accumulator low 32 bits. */\r
+ POP R15\r
+ MVTACHI R15 /* Accumulator high 32 bits. */\r
+ POP R15\r
+ MVTC R15,FPSW /* Floating point status word. */\r
+ POPM R1-R15 /* R1 to R15 - R0 is not included as it is the SP. */\r
+ RTE /* This pops the remaining registers. */\r
+ NOP\r
+ NOP\r
+}\r