]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/Paradigm/Tern_EE/large_untested/port.c
Update version number in readiness for V10.3.0 release. Sync SVN with reviewed releas...
[freertos] / FreeRTOS / Source / portable / Paradigm / Tern_EE / large_untested / port.c
1 /*\r
2  * FreeRTOS Kernel V10.3.0\r
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28 \r
29 /*-----------------------------------------------------------\r
30  * Implementation of functions defined in portable.h for the Tern EE 186\r
31  * port.\r
32  *----------------------------------------------------------*/\r
33 \r
34 /* Library includes. */\r
35 #include <embedded.h>\r
36 #include <ae.h>\r
37 \r
38 /* Scheduler includes. */\r
39 #include "FreeRTOS.h"\r
40 #include "task.h"\r
41 #include "portasm.h"\r
42 \r
43 /* The timer increments every four clocks, hence the divide by 4. */\r
44 #define portTIMER_COMPARE ( uint16_t ) ( ( configCPU_CLOCK_HZ / configTICK_RATE_HZ ) / ( uint32_t ) 4 )\r
45 \r
46 /* From the RDC data sheet. */\r
47 #define portENABLE_TIMER_AND_INTERRUPT ( uint16_t ) 0xe001\r
48 \r
49 /* Interrupt control. */\r
50 #define portEIO_REGISTER 0xff22\r
51 #define portCLEAR_INTERRUPT 0x0008\r
52 \r
53 /* Setup the hardware to generate the required tick frequency. */\r
54 static void prvSetupTimerInterrupt( void );\r
55 \r
56 /* The ISR used depends on whether the preemptive or cooperative scheduler\r
57 is being used. */\r
58 #if( configUSE_PREEMPTION == 1 )\r
59         /* Tick service routine used by the scheduler when preemptive scheduling is\r
60         being used. */\r
61         static void __interrupt __far prvPreemptiveTick( void );\r
62 #else\r
63         /* Tick service routine used by the scheduler when cooperative scheduling is\r
64         being used. */\r
65         static void __interrupt __far prvNonPreemptiveTick( void );\r
66 #endif\r
67 \r
68 /* Trap routine used by taskYIELD() to manually cause a context switch. */\r
69 static void __interrupt __far prvYieldProcessor( void );\r
70 \r
71 /* The timer initialisation functions leave interrupts enabled,\r
72 which is not what we want.  This ISR is installed temporarily in case\r
73 the timer fires before we get a change to disable interrupts again. */\r
74 static void __interrupt __far prvDummyISR( void );\r
75 \r
76 /*-----------------------------------------------------------*/\r
77 /* See header file for description. */\r
78 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )\r
79 {\r
80 StackType_t 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 = ( StackType_t ) 0xAAAA; /* AX */\r
117         pxTopOfStack--;\r
118         *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */\r
119         pxTopOfStack--;\r
120         *pxTopOfStack = ( StackType_t ) 0xCCCC; /* CX */\r
121         pxTopOfStack--;\r
122         *pxTopOfStack = ( StackType_t ) 0xDDDD; /* DX */\r
123         pxTopOfStack--;\r
124         *pxTopOfStack = ( StackType_t ) 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 = ( StackType_t ) 0x0123; /* SI */\r
133         pxTopOfStack--;\r
134         *pxTopOfStack = ( StackType_t ) 0xDDDD; /* DI */\r
135         pxTopOfStack--;\r
136         *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BP */\r
137 \r
138         return pxTopOfStack;\r
139 }\r
140 /*-----------------------------------------------------------*/\r
141 \r
142 BaseType_t 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 static void __interrupt __far prvDummyISR( void )\r
162 {\r
163         /* The timer initialisation functions leave interrupts enabled,\r
164         which is not what we want.  This ISR is installed temporarily in case\r
165         the timer fires before we get a change to disable interrupts again. */\r
166         outport( portEIO_REGISTER, portCLEAR_INTERRUPT );\r
167 }\r
168 /*-----------------------------------------------------------*/\r
169 \r
170 /* The ISR used depends on whether the preemptive or cooperative scheduler\r
171 is being used. */\r
172 #if( configUSE_PREEMPTION == 1 )\r
173         static void __interrupt __far prvPreemptiveTick( void )\r
174         {\r
175                 /* Get the scheduler to update the task states following the tick. */\r
176                 if( xTaskIncrementTick() != pdFALSE )\r
177                 {\r
178                         /* Switch in the context of the next task to be run. */\r
179                         portSWITCH_CONTEXT();\r
180                 }\r
181 \r
182                 /* Reset interrupt. */\r
183                 outport( portEIO_REGISTER, portCLEAR_INTERRUPT );\r
184         }\r
185 #else\r
186         static void __interrupt __far prvNonPreemptiveTick( void )\r
187         {\r
188                 /* Same as preemptive tick, but the cooperative scheduler is being used\r
189                 so we don't have to switch in the context of the next task. */\r
190                 xTaskIncrementTick();\r
191                 \r
192                 /* Reset interrupt. */\r
193                 outport( portEIO_REGISTER, portCLEAR_INTERRUPT );\r
194         }\r
195 #endif\r
196 /*-----------------------------------------------------------*/\r
197 \r
198 static void __interrupt __far prvYieldProcessor( void )\r
199 {\r
200         /* Switch in the context of the next task to be run. */\r
201         portSWITCH_CONTEXT();\r
202 }\r
203 /*-----------------------------------------------------------*/\r
204 \r
205 void vPortEndScheduler( void )\r
206 {\r
207         /* Not implemented. */\r
208 }\r
209 /*-----------------------------------------------------------*/\r
210 \r
211 static void prvSetupTimerInterrupt( void )\r
212 {\r
213 const uint16_t usTimerACompare = portTIMER_COMPARE, usTimerAMode = portENABLE_TIMER_AND_INTERRUPT;\r
214 const uint16_t usT2_IRQ = 0x13;\r
215 \r
216         /* Configure the timer, the dummy handler is used here as the init\r
217         function leaves interrupts enabled. */\r
218         t2_init( usTimerAMode, usTimerACompare, prvDummyISR );\r
219 \r
220         /* Disable interrupts again before installing the real handlers. */\r
221         portDISABLE_INTERRUPTS();\r
222 \r
223         #if( configUSE_PREEMPTION == 1 )\r
224                 /* Tick service routine used by the scheduler when preemptive scheduling is\r
225                 being used. */\r
226                 setvect( usT2_IRQ, prvPreemptiveTick );\r
227         #else\r
228                 /* Tick service routine used by the scheduler when cooperative scheduling is\r
229                 being used. */\r
230                 setvect( usT2_IRQ, prvNonPreemptiveTick );\r
231         #endif\r
232 }\r
233 \r
234 \r
235 \r
236 \r
237 \r
238 \r
239 \r