/* Library includes. */\r
#include "string.h"\r
\r
-#define portINITIAL_SR 0UL /* No interrupts masked. */\r
+/*-----------------------------------------------------------*/\r
+\r
+/* The SR assigned to a newly created task. The only important thing in this\r
+value is for all interrupts to be enabled. */\r
+#define portINITIAL_SR ( 0UL )\r
\r
-/* Allocate enough space for FPR0 to FPR15, FPUL and FPSCR, each of which is 4\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
\r
/*-----------------------------------------------------------*/\r
\r
-/*\r
- * Setup a peripheral timer to generate the RTOS tick interrupt.\r
- */\r
-static void prvSetupTimerInterrupt( void );\r
-\r
/*\r
* The TRAPA handler used to force a context switch.\r
*/\r
\r
portBASE_TYPE xPortStartScheduler( void )\r
{\r
- /* Start the tick interrupt. */\r
- prvSetupTimerInterrupt();\r
- \r
- /* Start the first task. */\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
+\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
\r
/* Should not get here. */\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void vPortTickInterrupt( void )\r
-{\r
- vTaskIncrementTick();\r
- #if configUSE_PREEMPTION == 1\r
- vTaskSwitchContext();\r
- #endif\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-static void prvSetupTimerInterrupt( void )\r
-{\r
-extern void vApplicationSetupTimerInterrupt( void );\r
-\r
- /* Call an application function to set up the timer. This way the application\r
- can decide which peripheral to use. A demo application is provided to show a\r
- suitable example. */\r
- vApplicationSetupTimerInterrupt();\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
void vPortYield( void )\r
{\r
long lInterruptMask;\r
\r
+ /* Ensure the yield trap runs at the same priority as the other interrupts\r
+ that can cause a context switch. */\r
lInterruptMask = get_imask();\r
\r
/* taskYIELD() can only be called from a task, not an interrupt, so the\r
\r
trapa( portYIELD_TRAP_NO );\r
\r
+ /* Restore the interrupt mask to whatever it was previously (when the\r
+ function was entered. */\r
set_imask( ( int ) lInterruptMask );\r
}\r
/*-----------------------------------------------------------*/\r
portBASE_TYPE xReturn;\r
extern void * volatile pxCurrentTCB;\r
\r
+ /* This function tells the kernel that the task referenced by xTask is\r
+ going to use the floating point registers and therefore requires the\r
+ floating point registers saved as part of its context. */\r
+\r
+ /* Passing NULL as xTask is used to indicate that the calling task is the\r
+ subject task - so pxCurrentTCB is the task handle. */\r
if( xTask == NULL )\r
{\r
- xTask = pxCurrentTCB;\r
+ xTask = ( xTaskHandle ) pxCurrentTCB;\r
}\r
\r
/* Allocate a buffer large enough to hold all the flop registers. */\r
\r
if( pulFlopBuffer != NULL )\r
{\r
+ /* Start with the registers in a benign state. */\r
memset( ( void * ) pulFlopBuffer, 0x00, portFLOP_STORAGE_SIZE );\r
\r
+ /* The first thing to get saved in the buffer is the FPSCR value -\r
+ initialise this to the current FPSCR value. */\r
*pulFlopBuffer = get_fpscr();\r
\r
- /* Use the task tag to point to the flop buffer. Pass pointer to just above\r
- the buffer because the flop save routine uses a pre-decrement. */\r
+ /* Use the task tag to point to the flop buffer. Pass pointer to just \r
+ above the buffer because the flop save routine uses a pre-decrement. */\r
vTaskSetApplicationTaskTag( xTask, ( void * ) ( pulFlopBuffer + portFLOP_REGISTERS_TO_STORE ) ); \r
xReturn = pdPASS;\r
}\r
*-----------------------------------------------------------\r
*/\r
\r
-/* Type definitions. */\r
+/* Type definitions - these are a bit legacy and not really used now, other than\r
+portSTACK_TYPE and portBASE_TYPE. */\r
#define portCHAR char\r
#define portFLOAT float\r
#define portDOUBLE double\r
/*-----------------------------------------------------------*/\r
\r
/* Hardware specifics. */\r
-#define portBYTE_ALIGNMENT 4\r
+#define portBYTE_ALIGNMENT 8\r
#define portSTACK_GROWTH -1\r
#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) \r
#define portNOP() nop()\r
void vPortYield( void );\r
#define portYIELD() vPortYield()\r
\r
+/* \r
+ * This function tells the kernel that the task referenced by xTask is going to \r
+ * use the floating point registers and therefore requires the floating point \r
+ * registers saved as part of its context. \r
+ */\r
portBASE_TYPE xPortUsesFloatingPoint( void* xTask );\r
+\r
+/*\r
+ * The flop save and restore functions are defined in portasm.src and called by\r
+ * the trace "task switched in" and "trace task switched out" macros. \r
+ */\r
void vPortSaveFlopRegisters( void *pulBuffer );\r
void vPortRestoreFlopRegisters( void *pulBuffer );\r
+\r
+/*\r
+ * pxTaskTag is used to point to the buffer into which the floating point \r
+ * context should be saved. If pxTaskTag is NULL then the task does not use\r
+ * a floating point context.\r
+ */\r
#define traceTASK_SWITCHED_OUT() if( pxCurrentTCB->pxTaskTag != NULL ) vPortSaveFlopRegisters( pxCurrentTCB->pxTaskTag )\r
#define traceTASK_SWITCHED_IN() if( pxCurrentTCB->pxTaskTag != NULL ) vPortRestoreFlopRegisters( pxCurrentTCB->pxTaskTag )\r
\r
-/*-----------------------------------------------------------*/\r
-\r
+/*\r
+ * These macros should be called directly, but through the taskENTER_CRITICAL()\r
+ * and taskEXIT_CRITICAL() macros.\r
+ */\r
#define portENABLE_INTERRUPTS() set_imask( 0x00 )\r
#define portDISABLE_INTERRUPTS() set_imask( portKERNEL_INTERRUPT_PRIORITY )\r
\r
-/* Critical section handling. */\r
+/* Critical nesting counts are stored in the TCB. */\r
#define portCRITICAL_NESTING_IN_TCB ( 1 )\r
+\r
+/* The critical nesting functions defined within tasks.c. */\r
extern void vTaskEnterCritical( void );\r
extern void vTaskExitCritical( void );\r
#define portENTER_CRITICAL() vTaskEnterCritical();\r