--- /dev/null
+/* \r
+ FreeRTOS V3.2.3 - Copyright (C) 2003 - 2005 Richard Barry.\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ FreeRTOS is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with FreeRTOS; if not, write to the Free Software\r
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+\r
+ A special exception to the GPL can be applied should you wish to distribute\r
+ a combined work that includes FreeRTOS, without being obliged to provide\r
+ the source code for any proprietary components. See the licensing section \r
+ of http://www.FreeRTOS.org for full details of how and when the exception\r
+ can be applied.\r
+\r
+ ***************************************************************************\r
+ See http://www.FreeRTOS.org for documentation, latest information, license \r
+ and contact details. Please ensure to read the configuration and relevant \r
+ port sections of the online documentation.\r
+ ***************************************************************************\r
+*/\r
+\r
+/* GCC/HCS12 port by Jefferson L Smith, 2005 */\r
+\r
+/* Scheduler includes. */\r
+#include "FreeRTOS.h"\r
+#include "task.h"\r
+\r
+/* Port includes */\r
+#include <sys/ports_def.h>\r
+\r
+/*-----------------------------------------------------------\r
+ * Implementation of functions defined in portable.h for the HCS12 port.\r
+ *----------------------------------------------------------*/\r
+\r
+\r
+/*\r
+ * Configure a timer to generate the RTOS tick at the frequency specified \r
+ * within FreeRTOSConfig.h.\r
+ */\r
+static void prvSetupTimerInterrupt( void );\r
+\r
+/* NOTE: Interrupt service routines must be in non-banked memory - as does the\r
+scheduler startup function. */\r
+#define ATTR_NEAR __attribute__((near))\r
+\r
+/* Manual context switch function. This is the SWI ISR. */\r
+// __attribute__((interrupt))\r
+void ATTR_NEAR vPortYield( void );\r
+\r
+/* Tick context switch function. This is the timer ISR. */\r
+// __attribute__((interrupt))\r
+void ATTR_NEAR vPortTickInterrupt( void );\r
+\r
+/* Function in non-banked memory which actually switches to first task. */\r
+portBASE_TYPE ATTR_NEAR xStartSchedulerNear( void );\r
+\r
+/* Calls to portENTER_CRITICAL() can be nested. When they are nested the \r
+critical section should not be left (i.e. interrupts should not be re-enabled)\r
+until the nesting depth reaches 0. This variable simply tracks the nesting \r
+depth. Each task maintains it's own critical nesting depth variable so \r
+uxCriticalNesting is saved and restored from the task stack during a context\r
+switch. */\r
+volatile unsigned portBASE_TYPE uxCriticalNesting = 0x80; // un-initialized\r
+\r
+/*-----------------------------------------------------------*/\r
+\r
+/* \r
+ * See header file for description. \r
+ */\r
+portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )\r
+{\r
+\r
+\r
+ /* Setup the initial stack of the task. The stack is set exactly as \r
+ expected by the portRESTORE_CONTEXT() macro. In this case the stack as\r
+ expected by the HCS12 RTI instruction. */\r
+\r
+\r
+ /* The address of the task function is placed in the stack byte at a time. */\r
+ *pxTopOfStack = ( portSTACK_TYPE ) *( ((portSTACK_TYPE *) (&pxCode) ) + 1 );\r
+ *--pxTopOfStack = ( portSTACK_TYPE ) *( ((portSTACK_TYPE *) (&pxCode) ) + 0 );\r
+\r
+ /* Next are all the registers that form part of the task context. */\r
+\r
+ /* Y register */\r
+ *--pxTopOfStack = ( portSTACK_TYPE ) 0xff;\r
+ *--pxTopOfStack = ( portSTACK_TYPE ) 0xee;\r
+\r
+ /* X register */\r
+ *--pxTopOfStack = ( portSTACK_TYPE ) 0xdd;\r
+ *--pxTopOfStack = ( portSTACK_TYPE ) 0xcc;\r
+ \r
+ /* A register contains parameter high byte. */\r
+ *--pxTopOfStack = ( portSTACK_TYPE ) *( ((portSTACK_TYPE *) (&pvParameters) ) + 0 );\r
+\r
+ /* B register contains parameter low byte. */\r
+ *--pxTopOfStack = ( portSTACK_TYPE ) *( ((portSTACK_TYPE *) (&pvParameters) ) + 1 );\r
+\r
+ /* CCR: Note that when the task starts interrupts will be enabled since\r
+ "I" bit of CCR is cleared */\r
+ *--pxTopOfStack = ( portSTACK_TYPE ) 0x80; // keeps Stop disabled (MCU default)\r
+ \r
+ /* tmp softregs used by GCC. Values right now don't matter. */\r
+ __asm("\n\\r
+ movw _.frame, 2,-%0 \n\\r
+ movw _.tmp, 2,-%0 \n\\r
+ movw _.z, 2,-%0 \n\\r
+ movw _.xy, 2,-%0 \n\\r
+ ;movw _.d2, 2,-%0 \n\\r
+ ;movw _.d1, 2,-%0 \n\\r
+ ": "=A"(pxTopOfStack) : "0"(pxTopOfStack) );\r
+\r
+ #ifdef BANKED_MODEL\r
+ /* The page of the task. */\r
+ *--pxTopOfStack = 0x30; // can only directly start in PPAGE 0x30\r
+ #endif\r
+ \r
+ /* The critical nesting depth is initialised with 0 (meaning not in\r
+ a critical section). */\r
+ *--pxTopOfStack = ( portSTACK_TYPE ) 0x00;\r
+\r
+\r
+ return pxTopOfStack;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vPortEndScheduler( void )\r
+{\r
+ /* It is unlikely that the HCS12 port will get stopped. */\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+static void prvSetupTimerInterrupt( void )\r
+{\r
+ /* Enable hardware RTI timer */\r
+ /* Ignores configTICK_RATE_HZ */\r
+ RTICTL = 0x50; // 16 MHz xtal: 976.56 Hz, 1024mS \r
+ CRGINT |= 0x80; // RTIE\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+portBASE_TYPE xPortStartScheduler( void )\r
+{\r
+ /* xPortStartScheduler() does not start the scheduler directly because \r
+ the header file containing the xPortStartScheduler() prototype is part \r
+ of the common kernel code, and therefore cannot use the CODE_SEG pragma. \r
+ Instead it simply calls the locally defined xNearStartScheduler() - \r
+ which does use the CODE_SEG pragma. */\r
+\r
+ short register d;\r
+ __asm ("jmp xStartSchedulerNear ; will never return": "=d"(d));\r
+ return d;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+portBASE_TYPE xStartSchedulerNear( void )\r
+{\r
+ /* Configure the timer that will generate the RTOS tick. Interrupts are\r
+ disabled when this function is called. */\r
+ prvSetupTimerInterrupt();\r
+\r
+ /* Restore the context of the first task. */\r
+ portRESTORE_CONTEXT();\r
+\r
+ portISR_TAIL();\r
+\r
+ /* Should not get here! */\r
+ return pdFALSE;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * Context switch functions. These are interrupt service routines.\r
+ */\r
+\r
+/*\r
+ * Manual context switch forced by calling portYIELD(). This is the SWI\r
+ * handler.\r
+ */\r
+void vPortYield( void )\r
+{\r
+ portISR_HEAD();\r
+ /* NOTE: This is the trap routine (swi) although not defined as a trap.\r
+ It will fill the stack the same way as an ISR in order to mix preemtion\r
+ and cooperative yield. */\r
+\r
+ portSAVE_CONTEXT();\r
+ vTaskSwitchContext();\r
+ portRESTORE_CONTEXT();\r
+\r
+ portISR_TAIL();\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/*\r
+ * RTOS tick interrupt service routine. If the cooperative scheduler is \r
+ * being used then this simply increments the tick count. If the \r
+ * preemptive scheduler is being used a context switch can occur.\r
+ */\r
+void vPortTickInterrupt( void )\r
+{\r
+ portISR_HEAD();\r
+\r
+ /* Clear tick timer flag */\r
+ CRGFLG = 0x80;\r
+\r
+ #if configUSE_PREEMPTION == 1\r
+ {\r
+ /* A context switch might happen so save the context. */\r
+ portSAVE_CONTEXT();\r
+\r
+ /* Increment the tick ... */\r
+ vTaskIncrementTick();\r
+\r
+ /* ... then see if the new tick value has necessitated a\r
+ context switch. */\r
+ vTaskSwitchContext();\r
+\r
+ /* Restore the context of a task - which may be a different task\r
+ to that interrupted. */\r
+ portRESTORE_CONTEXT();\r
+ }\r
+ #else\r
+ {\r
+ vTaskIncrementTick();\r
+ }\r
+ #endif\r
+\r
+ portISR_TAIL();\r
+}\r
+\r
--- /dev/null
+/*\r
+ FreeRTOS V3.2.3 - Copyright (C) 2003 - 2005 Richard Barry.\r
+\r
+ This file is part of the FreeRTOS distribution.\r
+\r
+ FreeRTOS is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+\r
+ FreeRTOS is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with FreeRTOS; if not, write to the Free Software\r
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
+\r
+ A special exception to the GPL can be applied should you wish to distribute\r
+ a combined work that includes FreeRTOS, without being obliged to provide\r
+ the source code for any proprietary components. See the licensing section \r
+ of http://www.FreeRTOS.org for full details of how and when the exception\r
+ can be applied.\r
+\r
+ ***************************************************************************\r
+ See http://www.FreeRTOS.org for documentation, latest information, license \r
+ and contact details. Please ensure to read the configuration and relevant \r
+ port sections of the online documentation.\r
+ ***************************************************************************\r
+*/\r
+\r
+\r
+#ifndef PORTMACRO_H\r
+#define PORTMACRO_H\r
+\r
+/*-----------------------------------------------------------\r
+ * Port specific definitions. \r
+ *\r
+ * The settings in this file configure FreeRTOS correctly for the\r
+ * given hardware and compiler.\r
+ *\r
+ * These settings should not be altered.\r
+ *-----------------------------------------------------------\r
+ */\r
+\r
+/* Type definitions. */\r
+#define portCHAR char\r
+#define portFLOAT float\r
+#define portDOUBLE double\r
+#define portLONG long\r
+#define portSHORT short\r
+#define portSTACK_TYPE unsigned portCHAR\r
+#define portBASE_TYPE char\r
+\r
+#if( configUSE_16_BIT_TICKS == 1 )\r
+ typedef unsigned portSHORT portTickType;\r
+ #define portMAX_DELAY ( portTickType ) 0xffff\r
+#else\r
+ typedef unsigned portLONG portTickType;\r
+ #define portMAX_DELAY ( portTickType ) 0xffffffff\r
+#endif\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Hardware specifics. */\r
+#define portBYTE_ALIGNMENT 1\r
+#define portSTACK_GROWTH ( -1 )\r
+#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ )\r
+#define portYIELD() __asm( "swi" );\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Critical section handling. */\r
+#define portENABLE_INTERRUPTS() __asm( "cli" ) \r
+#define portDISABLE_INTERRUPTS() __asm( "sei" )\r
+\r
+/*\r
+ * Disable interrupts before incrementing the count of critical section nesting.\r
+ * The nesting count is maintained so we know when interrupts should be\r
+ * re-enabled. Once interrupts are disabled the nesting count can be accessed\r
+ * directly. Each task maintains its own nesting count.\r
+ */\r
+#define portENTER_CRITICAL() \\r
+{ \\r
+ extern volatile unsigned portBASE_TYPE uxCriticalNesting; \\r
+ \\r
+ portDISABLE_INTERRUPTS(); \\r
+ uxCriticalNesting++; \\r
+}\r
+\r
+/*\r
+ * Interrupts are disabled so we can access the nesting count directly. If the\r
+ * nesting is found to be 0 (no nesting) then we are leaving the critical \r
+ * section and interrupts can be re-enabled.\r
+ */\r
+#define portEXIT_CRITICAL() \\r
+{ \\r
+ extern volatile unsigned portBASE_TYPE uxCriticalNesting; \\r
+ \\r
+ uxCriticalNesting--; \\r
+ if( uxCriticalNesting == 0 ) \\r
+ { \\r
+ portENABLE_INTERRUPTS(); \\r
+ } \\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+/* Task utilities. */\r
+\r
+/* \r
+ * These macros are very simple as the processor automatically saves and \r
+ * restores its registers as interrupts are entered and exited. In\r
+ * addition to the (automatically stacked) registers we also stack the \r
+ * critical nesting count. Each task maintains its own critical nesting\r
+ * count as it is legitimate for a task to yield from within a critical\r
+ * section. If the banked memory model is being used then the PPAGE\r
+ * register is also stored as part of the tasks context.\r
+ */\r
+\r
+#ifdef BANKED_MODEL\r
+ /* \r
+ * Load the stack pointer for the task, then pull the critical nesting\r
+ * count and PPAGE register from the stack. The remains of the \r
+ * context are restored by the RTI instruction.\r
+ */\r
+ #define portRESTORE_CONTEXT() \\r
+ { \\r
+ __asm( " \n\\r
+ .globl pxCurrentTCB ; void * \n\\r
+ .globl uxCriticalNesting ; char \n\\r
+ \n\\r
+ ldx pxCurrentTCB \n\\r
+ lds 0,x ; Stack \n\\r
+ \n\\r
+ movb 1,sp+,uxCriticalNesting \n\\r
+ movb 1,sp+,0x30 ; PPAGE \n\\r
+ " ); \\r
+ }\r
+\r
+ /* \r
+ * By the time this macro is called the processor has already stacked the\r
+ * registers. Simply stack the nesting count and PPAGE value, then save \r
+ * the task stack pointer.\r
+ */\r
+ #define portSAVE_CONTEXT() \\r
+ { \\r
+ __asm( " \n\\r
+ .globl pxCurrentTCB ; void * \n\\r
+ .globl uxCriticalNesting ; char \n\\r
+ \n\\r
+ movb 0x30, 1,-sp ; PPAGE \n\\r
+ movb uxCriticalNesting, 1,-sp \n\\r
+ \n\\r
+ ldx pxCurrentTCB \n\\r
+ sts 0,x ; Stack \n\\r
+ " ); \\r
+ }\r
+#else\r
+\r
+ /* \r
+ * These macros are as per the BANKED versions above, but without saving\r
+ * and restoring the PPAGE register.\r
+ */\r
+\r
+ #define portRESTORE_CONTEXT() \\r
+ { \\r
+ __asm( " \n\\r
+ .globl pxCurrentTCB ; void * \n\\r
+ .globl uxCriticalNesting ; char \n\\r
+ \n\\r
+ ldx pxCurrentTCB \n\\r
+ lds 0,x ; Stack \n\\r
+ \n\\r
+ movb 1,sp+,uxCriticalNesting \n\\r
+ " ); \\r
+ }\r
+\r
+ #define portSAVE_CONTEXT() \\r
+ { \\r
+ __asm( " \n\\r
+ .globl pxCurrentTCB ; void * \n\\r
+ .globl uxCriticalNesting ; char \n\\r
+ \n\\r
+ movb uxCriticalNesting, 1,-sp \n\\r
+ \n\\r
+ ldx pxCurrentTCB \n\\r
+ sts 0,x ; Stack \n\\r
+ " ); \\r
+ }\r
+#endif\r
+\r
+/*\r
+ * Utility macros to save/restore correct software registers for GCC. This is\r
+ * useful when GCC does not generate appropriate ISR head/tail code.\r
+ */\r
+#define portISR_HEAD() \\r
+{ \\r
+ __asm(" \n\\r
+ movw _.frame, 2,-sp \n\\r
+ movw _.tmp, 2,-sp \n\\r
+ movw _.z, 2,-sp \n\\r
+ movw _.xy, 2,-sp \n\\r
+ ;movw _.d2, 2,-sp \n\\r
+ ;movw _.d1, 2,-sp \n\\r
+ "); \\r
+}\r
+\r
+#define portISR_TAIL() \\r
+{ \\r
+ __asm(" \n\\r
+ movw 2,sp+, _.xy \n\\r
+ movw 2,sp+, _.z \n\\r
+ movw 2,sp+, _.tmp \n\\r
+ movw 2,sp+, _.frame \n\\r
+ ;movw 2,sp+, _.d1 \n\\r
+ ;movw 2,sp+, _.d2 \n\\r
+ rti \n\\r
+ "); \\r
+}\r
+\r
+/*\r
+ * Utility macro to call macros above in correct order in order to perform a\r
+ * task switch from within a standard ISR. This macro can only be used if\r
+ * the ISR does not use any local (stack) variables. If the ISR uses stack\r
+ * variables portYIELD() should be used in it's place.\r
+ */\r
+\r
+#define portTASK_SWITCH_FROM_ISR() \\r
+ portSAVE_CONTEXT(); \\r
+ vTaskSwitchContext(); \\r
+ portRESTORE_CONTEXT();\r
+\r
+\r
+/* Task function macros as described on the FreeRTOS.org WEB site. */\r
+#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
+#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )\r
+\r
+\r
+#endif /* PORTMACRO_H */\r
+\r