+/* \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