]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/Paradigm/Tern_EE/small/port.c
Update version number in readiness for V10.3.0 release. Sync SVN with reviewed releas...
[freertos] / FreeRTOS / Source / portable / Paradigm / Tern_EE / small / 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 portPRESCALE_VALUE ( 16 )\r
45 #define portTIMER_COMPARE ( configCPU_CLOCK_HZ  / ( configTICK_RATE_HZ * 4UL ) )\r
46 \r
47 /* From the RDC data sheet. */\r
48 #define portENABLE_TIMER_AND_INTERRUPT  ( uint16_t ) 0xe00b\r
49 #define portENABLE_TIMER                                ( uint16_t ) 0xC001\r
50 \r
51 /* Interrupt control. */\r
52 #define portEIO_REGISTER 0xff22\r
53 #define portCLEAR_INTERRUPT 0x0008\r
54 \r
55 /* Setup the hardware to generate the required tick frequency. */\r
56 static void prvSetupTimerInterrupt( void );\r
57 \r
58 /* The ISR used depends on whether the preemptive or cooperative scheduler\r
59 is being used. */\r
60 #if( configUSE_PREEMPTION == 1 )\r
61         /* Tick service routine used by the scheduler when preemptive scheduling is\r
62         being used. */\r
63         static void __interrupt __far prvPreemptiveTick( void );\r
64 #else\r
65         /* Tick service routine used by the scheduler when cooperative scheduling is\r
66         being used. */\r
67         static void __interrupt __far prvNonPreemptiveTick( void );\r
68 #endif\r
69 \r
70 /* Trap routine used by taskYIELD() to manually cause a context switch. */\r
71 static void __interrupt __far prvYieldProcessor( void );\r
72 \r
73 /*-----------------------------------------------------------*/\r
74 /* See header file for description. */\r
75 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )\r
76 {\r
77 StackType_t DS_Reg = 0;\r
78 \r
79         /* We need the true data segment. */\r
80         __asm{  MOV DS_Reg, DS };\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_OFF( pvParameters );\r
97         pxTopOfStack--;\r
98         *pxTopOfStack = FP_OFF( pxCode );\r
99         pxTopOfStack--;\r
100 \r
101         /* Next the status register and interrupt return address. */\r
102         *pxTopOfStack = portINITIAL_SW;\r
103         pxTopOfStack--;\r
104         *pxTopOfStack = FP_SEG( pxCode );\r
105         pxTopOfStack--;\r
106         *pxTopOfStack = FP_OFF( pxCode );\r
107         pxTopOfStack--;\r
108 \r
109         /* The remaining registers would be pushed on the stack by our context\r
110         switch function.  These are loaded with values simply to make debugging\r
111         easier. */\r
112         *pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */\r
113         pxTopOfStack--;\r
114         *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */\r
115         pxTopOfStack--;\r
116         *pxTopOfStack = ( StackType_t ) 0xCCCC; /* CX */\r
117         pxTopOfStack--;\r
118         *pxTopOfStack = ( StackType_t ) 0xDDDD; /* DX */\r
119         pxTopOfStack--;\r
120         *pxTopOfStack = ( StackType_t ) 0xEEEE; /* ES */\r
121         pxTopOfStack--;\r
122 \r
123         *pxTopOfStack = DS_Reg;                                         /* DS */\r
124         pxTopOfStack--;\r
125         *pxTopOfStack = ( StackType_t ) 0x0123; /* SI */\r
126         pxTopOfStack--;\r
127         *pxTopOfStack = ( StackType_t ) 0xDDDD; /* DI */\r
128         pxTopOfStack--;\r
129         *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BP */\r
130 \r
131         return pxTopOfStack;\r
132 }\r
133 /*-----------------------------------------------------------*/\r
134 \r
135 BaseType_t xPortStartScheduler( void )\r
136 {\r
137         /* This is called with interrupts already disabled. */\r
138 \r
139         /* Put our manual switch (yield) function on a known\r
140         vector. */\r
141         setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );\r
142 \r
143         /* Setup the tick interrupt. */\r
144         prvSetupTimerInterrupt();\r
145 \r
146         /* Kick off the scheduler by setting up the context of the first task. */\r
147         portFIRST_CONTEXT();\r
148 \r
149         /* Should not get here! */\r
150         return pdFALSE;\r
151 }\r
152 /*-----------------------------------------------------------*/\r
153 \r
154 /* The ISR used depends on whether the preemptive or cooperative scheduler\r
155 is being used. */\r
156 #if( configUSE_PREEMPTION == 1 )\r
157         static void __interrupt __far prvPreemptiveTick( void )\r
158         {\r
159                 /* Get the scheduler to update the task states following the tick. */\r
160                 if( xTaskIncrementTick() != pdFALSE )\r
161                 {\r
162                         /* Switch in the context of the next task to be run. */\r
163                         portEND_SWITCHING_ISR();\r
164                 }\r
165 \r
166                 /* Reset interrupt. */\r
167                 outport( portEIO_REGISTER, portCLEAR_INTERRUPT );\r
168         }\r
169 #else\r
170         static void __interrupt __far prvNonPreemptiveTick( void )\r
171         {\r
172                 /* Same as preemptive tick, but the cooperative scheduler is being used\r
173                 so we don't have to switch in the context of the next task. */\r
174                 xTaskIncrementTick();\r
175                 \r
176                 /* Reset interrupt. */\r
177                 outport( portEIO_REGISTER, portCLEAR_INTERRUPT );\r
178         }\r
179 #endif\r
180 /*-----------------------------------------------------------*/\r
181 \r
182 static void __interrupt __far prvYieldProcessor( void )\r
183 {\r
184         /* Switch in the context of the next task to be run. */\r
185         portEND_SWITCHING_ISR();\r
186 }\r
187 /*-----------------------------------------------------------*/\r
188 \r
189 void vPortEndScheduler( void )\r
190 {\r
191         /* Not implemented. */\r
192 }\r
193 /*-----------------------------------------------------------*/\r
194 \r
195 static void prvSetupTimerInterrupt( void )\r
196 {\r
197 const uint32_t ulCompareValue = portTIMER_COMPARE;\r
198 uint16_t usTimerCompare;\r
199 \r
200         usTimerCompare = ( uint16_t ) ( ulCompareValue >> 4 );\r
201     t2_init( portENABLE_TIMER, portPRESCALE_VALUE, NULL );\r
202 \r
203         #if( configUSE_PREEMPTION == 1 )\r
204                 /* Tick service routine used by the scheduler when preemptive scheduling is\r
205                 being used. */\r
206                 t1_init( portENABLE_TIMER_AND_INTERRUPT, usTimerCompare, usTimerCompare, prvPreemptiveTick );\r
207         #else\r
208                 /* Tick service routine used by the scheduler when cooperative scheduling is\r
209                 being used. */\r
210                 t1_init( portENABLE_TIMER_AND_INTERRUPT, usTimerCompare, usTimerCompare, prvNonPreemptiveTick );\r
211         #endif\r
212 }\r
213 \r
214 \r
215 \r
216 \r
217 \r
218 \r
219 \r