]> begriffs open source - freertos/blob - Source/portable/Paradigm/Tern_EE/large_untested/port.c
New port files for Tern E-Engine.
[freertos] / Source / portable / Paradigm / Tern_EE / large_untested / port.c
1 /*\r
2         FreeRTOS V4.0.1 - Copyright (C) 2003-2006 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS distribution.\r
5 \r
6         FreeRTOS is free software; you can redistribute it and/or modify\r
7         it under the terms of the GNU General Public License as published by\r
8         the Free Software Foundation; either version 2 of the License, or\r
9         (at your option) any later version.\r
10 \r
11         FreeRTOS is distributed in the hope that it will be useful,\r
12         but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14         GNU General Public License for more details.\r
15 \r
16         You should have received a copy of the GNU General Public License\r
17         along with FreeRTOS; if not, write to the Free Software\r
18         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
19 \r
20         A special exception to the GPL can be applied should you wish to distribute\r
21         a combined work that includes FreeRTOS, without being obliged to provide\r
22         the source code for any proprietary components.  See the licensing section\r
23         of http://www.FreeRTOS.org for full details of how and when the exception\r
24         can be applied.\r
25 \r
26         ***************************************************************************\r
27         See http://www.FreeRTOS.org for documentation, latest information, license\r
28         and contact details.  Please ensure to read the configuration and relevant\r
29         port sections of the online documentation.\r
30         ***************************************************************************\r
31 */\r
32 \r
33 \r
34 /*-----------------------------------------------------------\r
35  * Implementation of functions defined in portable.h for the Tern EE 186\r
36  * port.\r
37  *----------------------------------------------------------*/\r
38 \r
39 /* Library includes. */\r
40 #include <embedded.h>\r
41 #include <ae.h>\r
42 \r
43 /* Scheduler includes. */\r
44 #include "FreeRTOS.h"\r
45 #include "task.h"\r
46 #include "portasm.h"\r
47 \r
48 /* The timer increments every four clocks, hence the divide by 4. */\r
49 #define portTIMER_COMPARE ( unsigned portSHORT ) ( ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) / ( unsigned portLONG ) 4 )\r
50 \r
51 /* From the RDC data sheet. */\r
52 #define portENABLE_TIMER_AND_INTERRUPT ( unsigned portSHORT ) 0xe001\r
53 \r
54 /* Interrupt control. */\r
55 #define portEIO_REGISTER 0xff22\r
56 #define portCLEAR_INTERRUPT 0x0008\r
57 \r
58 /* Setup the hardware to generate the required tick frequency. */\r
59 static void prvSetupTimerInterrupt( void );\r
60 \r
61 /* The ISR used depends on whether the preemptive or cooperative scheduler\r
62 is being used. */\r
63 #if( configUSE_PREEMPTION == 1 )\r
64         /* Tick service routine used by the scheduler when preemptive scheduling is\r
65         being used. */\r
66         static void __interrupt __far prvPreemptiveTick( void );\r
67 #else\r
68         /* Tick service routine used by the scheduler when cooperative scheduling is\r
69         being used. */\r
70         static void __interrupt __far prvNonPreemptiveTick( void );\r
71 #endif\r
72 \r
73 /* Trap routine used by taskYIELD() to manually cause a context switch. */\r
74 static void __interrupt __far prvYieldProcessor( void );\r
75 \r
76 /*-----------------------------------------------------------*/\r
77 /* See header file for description. */\r
78 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )\r
79 {\r
80 portSTACK_TYPE DS_Reg = 0;\r
81 \r
82         /* Place a few bytes of known values on the bottom of the stack.\r
83         This is just useful for debugging. */\r
84 \r
85         *pxTopOfStack = 0x1111;\r
86         pxTopOfStack--;\r
87         *pxTopOfStack = 0x2222;\r
88         pxTopOfStack--;\r
89         *pxTopOfStack = 0x3333;\r
90         pxTopOfStack--;\r
91 \r
92         /* We are going to start the scheduler using a return from interrupt\r
93         instruction to load the program counter, so first there would be the\r
94         function call with parameters preamble. */\r
95         \r
96         *pxTopOfStack = FP_SEG( pvParameters );\r
97         pxTopOfStack--;\r
98         *pxTopOfStack = FP_OFF( pvParameters );\r
99         pxTopOfStack--;\r
100         *pxTopOfStack = FP_SEG( pxCode );\r
101         pxTopOfStack--;\r
102         *pxTopOfStack = FP_OFF( pxCode );\r
103         pxTopOfStack--;\r
104 \r
105         /* Next the status register and interrupt return address. */\r
106         *pxTopOfStack = portINITIAL_SW;\r
107         pxTopOfStack--;\r
108         *pxTopOfStack = FP_SEG( pxCode );\r
109         pxTopOfStack--;\r
110         *pxTopOfStack = FP_OFF( pxCode );\r
111         pxTopOfStack--;\r
112 \r
113         /* The remaining registers would be pushed on the stack by our context\r
114         switch function.  These are loaded with values simply to make debugging\r
115         easier. */\r
116         *pxTopOfStack = ( portSTACK_TYPE ) 0xAAAA;      /* AX */\r
117         pxTopOfStack--;\r
118         *pxTopOfStack = ( portSTACK_TYPE ) 0xBBBB;      /* BX */\r
119         pxTopOfStack--;\r
120         *pxTopOfStack = ( portSTACK_TYPE ) 0xCCCC;      /* CX */\r
121         pxTopOfStack--;\r
122         *pxTopOfStack = ( portSTACK_TYPE ) 0xDDDD;      /* DX */\r
123         pxTopOfStack--;\r
124         *pxTopOfStack = ( portSTACK_TYPE ) 0xEEEE;      /* ES */\r
125         pxTopOfStack--;\r
126 \r
127         /* We need the true data segment. */\r
128         __asm{  MOV DS_Reg, DS };\r
129 \r
130         *pxTopOfStack = DS_Reg;                                         /* DS */\r
131         pxTopOfStack--;\r
132         *pxTopOfStack = ( portSTACK_TYPE ) 0x0123;      /* SI */\r
133         pxTopOfStack--;\r
134         *pxTopOfStack = ( portSTACK_TYPE ) 0xDDDD;      /* DI */\r
135         pxTopOfStack--;\r
136         *pxTopOfStack = ( portSTACK_TYPE ) 0xBBBB;      /* BP */\r
137 \r
138         return pxTopOfStack;\r
139 }\r
140 /*-----------------------------------------------------------*/\r
141 \r
142 portBASE_TYPE xPortStartScheduler( void )\r
143 {\r
144         /* This is called with interrupts already disabled. */\r
145 \r
146         /* Put our manual switch (yield) function on a known\r
147         vector. */\r
148         setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );\r
149 \r
150         /* Setup the tick interrupt. */\r
151         prvSetupTimerInterrupt();\r
152 \r
153         /* Kick off the scheduler by setting up the context of the first task. */\r
154         portFIRST_CONTEXT();\r
155 \r
156         /* Should not get here! */\r
157         return pdFALSE;\r
158 }\r
159 /*-----------------------------------------------------------*/\r
160 \r
161 /* The ISR used depends on whether the preemptive or cooperative scheduler\r
162 is being used. */\r
163 #if( configUSE_PREEMPTION == 1 )\r
164         static void __interrupt __far prvPreemptiveTick( void )\r
165         {\r
166                 /* Get the scheduler to update the task states following the tick. */\r
167                 vTaskIncrementTick();\r
168 \r
169                 /* Switch in the context of the next task to be run. */\r
170                 portSWITCH_CONTEXT();\r
171 \r
172                 /* Reset interrupt. */\r
173                 outport( portEIO_REGISTER, portCLEAR_INTERRUPT );\r
174         }\r
175 #else\r
176         static void __interrupt __far prvNonPreemptiveTick( void )\r
177         {\r
178                 /* Same as preemptive tick, but the cooperative scheduler is being used\r
179                 so we don't have to switch in the context of the next task. */\r
180                 vTaskIncrementTick();\r
181                 /* Reset interrupt. */\r
182                 outport( portEIO_REGISTER, portCLEAR_INTERRUPT );\r
183         }\r
184 #endif\r
185 /*-----------------------------------------------------------*/\r
186 \r
187 static void __interrupt __far prvYieldProcessor( void )\r
188 {\r
189         /* Switch in the context of the next task to be run. */\r
190         portSWITCH_CONTEXT();\r
191 }\r
192 /*-----------------------------------------------------------*/\r
193 \r
194 void vPortEndScheduler( void )\r
195 {\r
196         /* Not implemented. */\r
197 }\r
198 /*-----------------------------------------------------------*/\r
199 \r
200 static void prvSetupTimerInterrupt( void )\r
201 {\r
202 const unsigned portSHORT usTimerACompare = portTIMER_COMPARE, usTimerAMode = portENABLE_TIMER_AND_INTERRUPT;\r
203 \r
204         #if( configUSE_PREEMPTION == 1 )\r
205                 /* Tick service routine used by the scheduler when preemptive scheduling is\r
206                 being used. */\r
207                 t2_init( usTimerAMode, usTimerACompare, prvPreemptiveTick );\r
208         #else\r
209                 /* Tick service routine used by the scheduler when cooperative scheduling is\r
210                 being used. */\r
211                 t2_init( usTimerAMode, usTimerACompare, prvNonPreemptiveTick );\r
212         #endif\r
213 }\r
214 \r
215 \r
216 \r
217 \r
218 \r
219 \r
220 \r