]> begriffs open source - freertos/blob - portable/Paradigm/Tern_EE/small/port.c
Style: uncrusitfy
[freertos] / portable / Paradigm / Tern_EE / small / port.c
1 /*\r
2  * FreeRTOS Kernel V10.3.1\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  */\r
26 \r
27 \r
28 /*-----------------------------------------------------------\r
29 * Implementation of functions defined in portable.h for the Tern EE 186\r
30 * port.\r
31 *----------------------------------------------------------*/\r
32 \r
33 /* Library includes. */\r
34 #include <embedded.h>\r
35 #include <ae.h>\r
36 \r
37 /* Scheduler includes. */\r
38 #include "FreeRTOS.h"\r
39 #include "task.h"\r
40 #include "portasm.h"\r
41 \r
42 /* The timer increments every four clocks, hence the divide by 4. */\r
43 #define portPRESCALE_VALUE                ( 16 )\r
44 #define portTIMER_COMPARE                 ( configCPU_CLOCK_HZ / ( configTICK_RATE_HZ * 4UL ) )\r
45 \r
46 /* From the RDC data sheet. */\r
47 #define portENABLE_TIMER_AND_INTERRUPT    ( uint16_t ) 0xe00b\r
48 #define portENABLE_TIMER                  ( uint16_t ) 0xC001\r
49 \r
50 /* Interrupt control. */\r
51 #define portEIO_REGISTER                  0xff22\r
52 #define portCLEAR_INTERRUPT               0x0008\r
53 \r
54 /* Setup the hardware to generate the required tick frequency. */\r
55 static void prvSetupTimerInterrupt( void );\r
56 \r
57 /* The ISR used depends on whether the preemptive or cooperative scheduler\r
58  * is being used. */\r
59 #if ( configUSE_PREEMPTION == 1 )\r
60 \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 \r
66 /* Tick service routine used by the scheduler when cooperative scheduling is\r
67  * being used. */\r
68     static void __interrupt __far prvNonPreemptiveTick( void );\r
69 #endif\r
70 \r
71 /* Trap routine used by taskYIELD() to manually cause a context switch. */\r
72 static void __interrupt __far prvYieldProcessor( void );\r
73 \r
74 /*-----------------------------------------------------------*/\r
75 /* See header file for description. */\r
76 StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,\r
77                                      TaskFunction_t pxCode,\r
78                                      void * pvParameters )\r
79 {\r
80     StackType_t DS_Reg = 0;\r
81 \r
82     /* We need the true data segment. */\r
83     __asm {\r
84         MOV DS_Reg, DS\r
85     };\r
86 \r
87     /* Place a few bytes of known values on the bottom of the stack.\r
88      * This is just useful for debugging. */\r
89 \r
90     *pxTopOfStack = 0x1111;\r
91     pxTopOfStack--;\r
92     *pxTopOfStack = 0x2222;\r
93     pxTopOfStack--;\r
94     *pxTopOfStack = 0x3333;\r
95     pxTopOfStack--;\r
96 \r
97     /* We are going to start the scheduler using a return from interrupt\r
98      * instruction to load the program counter, so first there would be the\r
99      * function call with parameters preamble. */\r
100 \r
101     *pxTopOfStack = FP_OFF( pvParameters );\r
102     pxTopOfStack--;\r
103     *pxTopOfStack = FP_OFF( pxCode );\r
104     pxTopOfStack--;\r
105 \r
106     /* Next the status register and interrupt return address. */\r
107     *pxTopOfStack = portINITIAL_SW;\r
108     pxTopOfStack--;\r
109     *pxTopOfStack = FP_SEG( pxCode );\r
110     pxTopOfStack--;\r
111     *pxTopOfStack = FP_OFF( pxCode );\r
112     pxTopOfStack--;\r
113 \r
114     /* The remaining registers would be pushed on the stack by our context\r
115      * switch function.  These are loaded with values simply to make debugging\r
116      * easier. */\r
117     *pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */\r
118     pxTopOfStack--;\r
119     *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */\r
120     pxTopOfStack--;\r
121     *pxTopOfStack = ( StackType_t ) 0xCCCC; /* CX */\r
122     pxTopOfStack--;\r
123     *pxTopOfStack = ( StackType_t ) 0xDDDD; /* DX */\r
124     pxTopOfStack--;\r
125     *pxTopOfStack = ( StackType_t ) 0xEEEE; /* ES */\r
126     pxTopOfStack--;\r
127 \r
128     *pxTopOfStack = DS_Reg;                 /* DS */\r
129     pxTopOfStack--;\r
130     *pxTopOfStack = ( StackType_t ) 0x0123; /* SI */\r
131     pxTopOfStack--;\r
132     *pxTopOfStack = ( StackType_t ) 0xDDDD; /* DI */\r
133     pxTopOfStack--;\r
134     *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BP */\r
135 \r
136     return pxTopOfStack;\r
137 }\r
138 /*-----------------------------------------------------------*/\r
139 \r
140 BaseType_t xPortStartScheduler( void )\r
141 {\r
142     /* This is called with interrupts already disabled. */\r
143 \r
144     /* Put our manual switch (yield) function on a known\r
145      * vector. */\r
146     setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );\r
147 \r
148     /* Setup the tick interrupt. */\r
149     prvSetupTimerInterrupt();\r
150 \r
151     /* Kick off the scheduler by setting up the context of the first task. */\r
152     portFIRST_CONTEXT();\r
153 \r
154     /* Should not get here! */\r
155     return pdFALSE;\r
156 }\r
157 /*-----------------------------------------------------------*/\r
158 \r
159 /* The ISR used depends on whether the preemptive or cooperative scheduler\r
160  * is being used. */\r
161 #if ( configUSE_PREEMPTION == 1 )\r
162     static void __interrupt __far prvPreemptiveTick( void )\r
163     {\r
164         /* Get the scheduler to update the task states following the tick. */\r
165         if( xTaskIncrementTick() != pdFALSE )\r
166         {\r
167             /* Switch in the context of the next task to be run. */\r
168             portEND_SWITCHING_ISR();\r
169         }\r
170 \r
171         /* Reset interrupt. */\r
172         outport( portEIO_REGISTER, portCLEAR_INTERRUPT );\r
173     }\r
174 #else  /* if ( configUSE_PREEMPTION == 1 ) */\r
175     static void __interrupt __far prvNonPreemptiveTick( void )\r
176     {\r
177         /* Same as preemptive tick, but the cooperative scheduler is being used\r
178          * so we don't have to switch in the context of the next task. */\r
179         xTaskIncrementTick();\r
180 \r
181         /* Reset interrupt. */\r
182         outport( portEIO_REGISTER, portCLEAR_INTERRUPT );\r
183     }\r
184 #endif /* if ( configUSE_PREEMPTION == 1 ) */\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     portEND_SWITCHING_ISR();\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 uint32_t ulCompareValue = portTIMER_COMPARE;\r
203     uint16_t       usTimerCompare;\r
204 \r
205     usTimerCompare = ( uint16_t ) ( ulCompareValue >> 4 );\r
206     t2_init( portENABLE_TIMER, portPRESCALE_VALUE, NULL );\r
207 \r
208     #if ( configUSE_PREEMPTION == 1 )\r
209 \r
210         /* Tick service routine used by the scheduler when preemptive scheduling is\r
211          * being used. */\r
212         t1_init( portENABLE_TIMER_AND_INTERRUPT, usTimerCompare, usTimerCompare, prvPreemptiveTick );\r
213     #else\r
214 \r
215         /* Tick service routine used by the scheduler when cooperative scheduling is\r
216          * being used. */\r
217         t1_init( portENABLE_TIMER_AND_INTERRUPT, usTimerCompare, usTimerCompare, prvNonPreemptiveTick );\r
218     #endif\r
219 }\r