]> begriffs open source - cmsis-freertos/blob - Source/portable/Paradigm/Tern_EE/small/port.c
Sources updated to FreeRTOS 10.2.0
[cmsis-freertos] / Source / portable / Paradigm / Tern_EE / small / port.c
1 /*
2  * FreeRTOS Kernel V10.2.0
3  * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * http://www.FreeRTOS.org
23  * http://aws.amazon.com/freertos
24  *
25  * 1 tab == 4 spaces!
26  */
27
28
29 /*-----------------------------------------------------------
30  * Implementation of functions defined in portable.h for the Tern EE 186
31  * port.
32  *----------------------------------------------------------*/
33
34 /* Library includes. */
35 #include <embedded.h>
36 #include <ae.h>
37
38 /* Scheduler includes. */
39 #include "FreeRTOS.h"
40 #include "task.h"
41 #include "portasm.h"
42
43 /* The timer increments every four clocks, hence the divide by 4. */
44 #define portPRESCALE_VALUE ( 16 )
45 #define portTIMER_COMPARE ( configCPU_CLOCK_HZ  / ( configTICK_RATE_HZ * 4UL ) )
46
47 /* From the RDC data sheet. */
48 #define portENABLE_TIMER_AND_INTERRUPT  ( uint16_t ) 0xe00b
49 #define portENABLE_TIMER                                ( uint16_t ) 0xC001
50
51 /* Interrupt control. */
52 #define portEIO_REGISTER 0xff22
53 #define portCLEAR_INTERRUPT 0x0008
54
55 /* Setup the hardware to generate the required tick frequency. */
56 static void prvSetupTimerInterrupt( void );
57
58 /* The ISR used depends on whether the preemptive or cooperative scheduler
59 is being used. */
60 #if( configUSE_PREEMPTION == 1 )
61         /* Tick service routine used by the scheduler when preemptive scheduling is
62         being used. */
63         static void __interrupt __far prvPreemptiveTick( void );
64 #else
65         /* Tick service routine used by the scheduler when cooperative scheduling is
66         being used. */
67         static void __interrupt __far prvNonPreemptiveTick( void );
68 #endif
69
70 /* Trap routine used by taskYIELD() to manually cause a context switch. */
71 static void __interrupt __far prvYieldProcessor( void );
72
73 /*-----------------------------------------------------------*/
74 /* See header file for description. */
75 StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters )
76 {
77 StackType_t DS_Reg = 0;
78
79         /* We need the true data segment. */
80         __asm{  MOV DS_Reg, DS };
81
82         /* Place a few bytes of known values on the bottom of the stack.
83         This is just useful for debugging. */
84
85         *pxTopOfStack = 0x1111;
86         pxTopOfStack--;
87         *pxTopOfStack = 0x2222;
88         pxTopOfStack--;
89         *pxTopOfStack = 0x3333;
90         pxTopOfStack--;
91
92         /* We are going to start the scheduler using a return from interrupt
93         instruction to load the program counter, so first there would be the
94         function call with parameters preamble. */
95         
96         *pxTopOfStack = FP_OFF( pvParameters );
97         pxTopOfStack--;
98         *pxTopOfStack = FP_OFF( pxCode );
99         pxTopOfStack--;
100
101         /* Next the status register and interrupt return address. */
102         *pxTopOfStack = portINITIAL_SW;
103         pxTopOfStack--;
104         *pxTopOfStack = FP_SEG( pxCode );
105         pxTopOfStack--;
106         *pxTopOfStack = FP_OFF( pxCode );
107         pxTopOfStack--;
108
109         /* The remaining registers would be pushed on the stack by our context
110         switch function.  These are loaded with values simply to make debugging
111         easier. */
112         *pxTopOfStack = ( StackType_t ) 0xAAAA; /* AX */
113         pxTopOfStack--;
114         *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BX */
115         pxTopOfStack--;
116         *pxTopOfStack = ( StackType_t ) 0xCCCC; /* CX */
117         pxTopOfStack--;
118         *pxTopOfStack = ( StackType_t ) 0xDDDD; /* DX */
119         pxTopOfStack--;
120         *pxTopOfStack = ( StackType_t ) 0xEEEE; /* ES */
121         pxTopOfStack--;
122
123         *pxTopOfStack = DS_Reg;                                         /* DS */
124         pxTopOfStack--;
125         *pxTopOfStack = ( StackType_t ) 0x0123; /* SI */
126         pxTopOfStack--;
127         *pxTopOfStack = ( StackType_t ) 0xDDDD; /* DI */
128         pxTopOfStack--;
129         *pxTopOfStack = ( StackType_t ) 0xBBBB; /* BP */
130
131         return pxTopOfStack;
132 }
133 /*-----------------------------------------------------------*/
134
135 BaseType_t xPortStartScheduler( void )
136 {
137         /* This is called with interrupts already disabled. */
138
139         /* Put our manual switch (yield) function on a known
140         vector. */
141         setvect( portSWITCH_INT_NUMBER, prvYieldProcessor );
142
143         /* Setup the tick interrupt. */
144         prvSetupTimerInterrupt();
145
146         /* Kick off the scheduler by setting up the context of the first task. */
147         portFIRST_CONTEXT();
148
149         /* Should not get here! */
150         return pdFALSE;
151 }
152 /*-----------------------------------------------------------*/
153
154 /* The ISR used depends on whether the preemptive or cooperative scheduler
155 is being used. */
156 #if( configUSE_PREEMPTION == 1 )
157         static void __interrupt __far prvPreemptiveTick( void )
158         {
159                 /* Get the scheduler to update the task states following the tick. */
160                 if( xTaskIncrementTick() != pdFALSE )
161                 {
162                         /* Switch in the context of the next task to be run. */
163                         portEND_SWITCHING_ISR();
164                 }
165
166                 /* Reset interrupt. */
167                 outport( portEIO_REGISTER, portCLEAR_INTERRUPT );
168         }
169 #else
170         static void __interrupt __far prvNonPreemptiveTick( void )
171         {
172                 /* Same as preemptive tick, but the cooperative scheduler is being used
173                 so we don't have to switch in the context of the next task. */
174                 xTaskIncrementTick();
175                 
176                 /* Reset interrupt. */
177                 outport( portEIO_REGISTER, portCLEAR_INTERRUPT );
178         }
179 #endif
180 /*-----------------------------------------------------------*/
181
182 static void __interrupt __far prvYieldProcessor( void )
183 {
184         /* Switch in the context of the next task to be run. */
185         portEND_SWITCHING_ISR();
186 }
187 /*-----------------------------------------------------------*/
188
189 void vPortEndScheduler( void )
190 {
191         /* Not implemented. */
192 }
193 /*-----------------------------------------------------------*/
194
195 static void prvSetupTimerInterrupt( void )
196 {
197 const uint32_t ulCompareValue = portTIMER_COMPARE;
198 uint16_t usTimerCompare;
199
200         usTimerCompare = ( uint16_t ) ( ulCompareValue >> 4 );
201     t2_init( portENABLE_TIMER, portPRESCALE_VALUE, NULL );
202
203         #if( configUSE_PREEMPTION == 1 )
204                 /* Tick service routine used by the scheduler when preemptive scheduling is
205                 being used. */
206                 t1_init( portENABLE_TIMER_AND_INTERRUPT, usTimerCompare, usTimerCompare, prvPreemptiveTick );
207         #else
208                 /* Tick service routine used by the scheduler when cooperative scheduling is
209                 being used. */
210                 t1_init( portENABLE_TIMER_AND_INTERRUPT, usTimerCompare, usTimerCompare, prvNonPreemptiveTick );
211         #endif
212 }
213
214
215
216
217
218
219