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