]> git.sur5r.net Git - freertos/blob - Source/portable/Softune/MB91460/port.c
Revert to original critical section handling method.
[freertos] / Source / portable / Softune / MB91460 / port.c
1 /*\r
2         FreeRTOS.org V4.7.1 - Copyright (C) 2003-2008 Richard Barry.\r
3 \r
4         This file is part of the FreeRTOS.org distribution.\r
5 \r
6         FreeRTOS.org 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.org 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.org; 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.org, 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 \r
28         Please ensure to read the configuration and relevant port sections of the \r
29         online documentation.\r
30 \r
31         +++ http://www.FreeRTOS.org +++\r
32         Documentation, latest information, license and contact details.  \r
33 \r
34         +++ http://www.SafeRTOS.com +++\r
35         A version that is certified for use in safety critical systems.\r
36 \r
37         +++ http://www.OpenRTOS.com +++\r
38         Commercial support, development, porting, licensing and training services.\r
39 \r
40         ***************************************************************************\r
41 */\r
42 \r
43 #include "FreeRTOS.h"\r
44 #include "task.h"\r
45 #include "mb91467d.h"\r
46 \r
47 /*-----------------------------------------------------------*/\r
48 \r
49 /* We require the address of the pxCurrentTCB variable, but don't want to know\r
50 any details of its type. */\r
51 typedef void tskTCB;\r
52 extern volatile tskTCB * volatile pxCurrentTCB;\r
53 \r
54 /*-----------------------------------------------------------*/\r
55  \r
56 #pragma asm\r
57 #macro  SaveContext\r
58          ORCCR #0x20                                                            ;Switch to user stack\r
59          ST RP,@-R15                                                            ;Store RP\r
60          STM0 (R7,R6,R5,R4,R3,R2,R1,R0)                         ;Store R7-R0\r
61          STM1 (R14,R13,R12,R11,R10,R9,R8)                       ;Store R14-R8\r
62          ST MDH, @-R15                                                          ;Store MDH\r
63          ST MDL, @-R15                                                          ;Store MDL\r
64          \r
65          ANDCCR #0xDF                                                           ;Switch back to system stack\r
66          LD @R15+,R0                                                            ;Store PC to R0 \r
67          ORCCR #0x20                                                            ;Switch to user stack\r
68          ST R0,@-R15                                                            ;Store PC to User stack\r
69          \r
70          ANDCCR #0xDF                                                           ;Switch back to system stack\r
71          LD @R15+,R0                                                            ;Store PS to R0\r
72          ORCCR #0x20                                                            ;Switch to user stack\r
73          ST R0,@-R15                                                            ;Store PS to User stack\r
74          \r
75          LDI #_pxCurrentTCB, R0                                         ;Get pxCurrentTCB address\r
76          LD @R0, R0                                                                     ;Get the pxCurrentTCB->pxTopOfStack address\r
77          ST R15,@R0                                                                     ;Store USP to pxCurrentTCB->pxTopOfStack\r
78          \r
79          ANDCCR #0xDF                                                           ;Switch back to system stack for the rest of tick ISR\r
80 #endm\r
81 \r
82 #macro RestoreContext\r
83          LDI #_pxCurrentTCB, R0                                         ;Get pxCurrentTCB address\r
84          LD @R0, R0                                                                     ;Get the pxCurrentTCB->pxTopOfStack address\r
85          ORCCR #0x20                                                            ;Switch to user stack\r
86          LD @R0, R15                                                            ;Restore USP from pxCurrentTCB->pxTopOfStack\r
87 \r
88          LD @R15+,R0                                                            ;Store PS to R0\r
89          ANDCCR #0xDF                                                           ;Switch to system stack\r
90          ST R0,@-R15                                                            ;Store PS to system stack\r
91 \r
92          ORCCR #0x20                                                            ;Switch to user stack\r
93          LD @R15+,R0                                                            ;Store PC to R0\r
94          ANDCCR #0xDF                                                           ;Switch to system stack\r
95          ST R0,@-R15                                                            ;Store PC to system stack\r
96 \r
97          ORCCR #0x20                                                            ;Switch back to retrieve the remaining context\r
98 \r
99          LD @R15+, MDL                                                          ;Restore MDL\r
100          LD @R15+, MDH                                                          ;Restore MDH\r
101          LDM1 (R14,R13,R12,R11,R10,R9,R8)                       ;Restore R14-R8\r
102          LDM0 (R7,R6,R5,R4,R3,R2,R1,R0)                         ;Restore R7-R0\r
103          LD @R15+, RP                                                           ;Restore RP\r
104          \r
105          ANDCCR #0xDF                                                           ;Switch back to system stack for the rest of tick ISR\r
106 #endm\r
107 #pragma endasm\r
108 \r
109 /*-----------------------------------------------------------*/\r
110 \r
111 /*\r
112  * Perform hardware setup to enable ticks from timer 1,\r
113  */\r
114 static void prvSetupTimerInterrupt( void );\r
115 /*-----------------------------------------------------------*/\r
116 \r
117 /* \r
118  * Initialise the stack of a task to look exactly as if a call to \r
119  * portSAVE_CONTEXT had been called.\r
120  * \r
121  * See the header file portable.h.\r
122  */\r
123 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )\r
124 {\r
125         /* Place a few bytes of known values on the bottom of the stack. \r
126         This is just useful for debugging. */\r
127 \r
128         *pxTopOfStack = 0x11111111;\r
129         pxTopOfStack--;\r
130         *pxTopOfStack = 0x22222222;\r
131         pxTopOfStack--;\r
132         *pxTopOfStack = 0x33333333;\r
133         pxTopOfStack--;\r
134 \r
135         /* This is a redundant push to the stack, it may be required if \r
136         in some implementations of the compiler the parameter to the task \r
137         is passed on to the stack rather than in R4 register. */\r
138         *pxTopOfStack = (portSTACK_TYPE)(pvParameters);\r
139         pxTopOfStack--;                  \r
140     \r
141         *pxTopOfStack = ( portSTACK_TYPE ) 0x00000000;  /* RP */\r
142         pxTopOfStack--;\r
143         *pxTopOfStack = ( portSTACK_TYPE ) 0x00007777;  /* R7 */\r
144         pxTopOfStack--;\r
145         *pxTopOfStack = ( portSTACK_TYPE ) 0x00006666;  /* R6 */\r
146         pxTopOfStack--;\r
147         *pxTopOfStack = ( portSTACK_TYPE ) 0x00005555;  /* R5 */\r
148         pxTopOfStack--;\r
149         \r
150         /* In the current implementation of the compiler the first \r
151         parameter to the task (or function) is passed via R4 parameter \r
152         to the task, hence the pvParameters pointer is copied into the R4 \r
153         register. See compiler manual section 4.6.2 for more information. */\r
154         *pxTopOfStack = ( portSTACK_TYPE ) (pvParameters);      /* R4 */\r
155         pxTopOfStack--;\r
156         *pxTopOfStack = ( portSTACK_TYPE ) 0x00003333;  /* R3 */\r
157         pxTopOfStack--;\r
158         *pxTopOfStack = ( portSTACK_TYPE ) 0x00002222;  /* R2 */\r
159         pxTopOfStack--;\r
160         *pxTopOfStack = ( portSTACK_TYPE ) 0x00001111;  /* R1 */\r
161         pxTopOfStack--;\r
162         *pxTopOfStack = ( portSTACK_TYPE ) 0x00000001;  /* R0 */\r
163         pxTopOfStack--; \r
164         *pxTopOfStack = ( portSTACK_TYPE ) 0x0000EEEE;  /* R14 */\r
165         pxTopOfStack--;\r
166         *pxTopOfStack = ( portSTACK_TYPE ) 0x0000DDDD;  /* R13 */\r
167         pxTopOfStack--;\r
168         *pxTopOfStack = ( portSTACK_TYPE ) 0x0000CCCC;  /* R12 */\r
169         pxTopOfStack--;\r
170         *pxTopOfStack = ( portSTACK_TYPE ) 0x0000BBBB;  /* R11 */\r
171         pxTopOfStack--;\r
172         *pxTopOfStack = ( portSTACK_TYPE ) 0x0000AAAA;  /* R10 */\r
173         pxTopOfStack--;\r
174         *pxTopOfStack = ( portSTACK_TYPE ) 0x00009999;  /* R9 */\r
175         pxTopOfStack--;\r
176         *pxTopOfStack = ( portSTACK_TYPE ) 0x00008888;  /* R8 */\r
177         pxTopOfStack--; \r
178         *pxTopOfStack = ( portSTACK_TYPE ) 0x11110000;  /* MDH */\r
179         pxTopOfStack--;\r
180         *pxTopOfStack = ( portSTACK_TYPE ) 0x22220000;  /* MDL */\r
181         pxTopOfStack--;\r
182 \r
183         /* The start of the task code. */\r
184         *pxTopOfStack = ( portSTACK_TYPE ) pxCode;      /* PC */\r
185         pxTopOfStack--;\r
186          \r
187     /* PS - User Mode, USP, ILM=31, Interrupts enabled */\r
188         *pxTopOfStack = ( portSTACK_TYPE ) 0x001F0030;  /* PS */\r
189 \r
190         return pxTopOfStack;\r
191 }\r
192 /*-----------------------------------------------------------*/\r
193 \r
194 portBASE_TYPE xPortStartScheduler( void )\r
195 {\r
196         /* Setup the hardware to generate the tick. */\r
197         prvSetupTimerInterrupt();\r
198 \r
199         /* Restore the context of the first task that is going to run. */\r
200         #pragma asm\r
201                 RestoreContext\r
202         #pragma endasm\r
203 \r
204         /* Simulate a function call end as generated by the compiler.  We will now\r
205         jump to the start of the task the context of which we have just restored. */    \r
206         __asm(" reti ");\r
207 \r
208         /* Should not get here. */\r
209         return pdFAIL;\r
210 }\r
211 /*-----------------------------------------------------------*/\r
212 \r
213 void vPortEndScheduler( void )\r
214 {\r
215         /* Not implemented - unlikely to ever be required as there is nothing to\r
216         return to. */\r
217 }\r
218 /*-----------------------------------------------------------*/\r
219 \r
220 static void prvSetupTimerInterrupt( void )\r
221 {\r
222 /* The peripheral clock divided by 32 is used by the timer. */\r
223 const unsigned portSHORT usReloadValue = ( unsigned portSHORT ) ( ( ( configPER_CLOCK_HZ / configTICK_RATE_HZ ) / 32UL ) - 1UL );\r
224 \r
225         /* Setup RLT0 to generate a tick interrupt. */\r
226 \r
227         TMCSR0_CNTE = 0;                /* Count Disable */\r
228     TMCSR0_CSL = 0x2;           /* CLKP/32 */\r
229     TMCSR0_MOD = 0;                     /* Software trigger */\r
230     TMCSR0_RELD = 1;            /* Reload */\r
231     \r
232     TMCSR0_UF = 0;                      /* Clear underflow flag */\r
233         TMRLR0 = usReloadValue;\r
234         TMCSR0_INTE = 1;                /* Interrupt Enable */\r
235         TMCSR0_CNTE = 1;                /* Count Enable */\r
236         TMCSR0_TRG = 1;                 /* Trigger */\r
237         \r
238     PORTEN = 0x3;                       /* Port Enable */\r
239 }\r
240 /*-----------------------------------------------------------*/\r
241 \r
242 #if configUSE_PREEMPTION == 1\r
243 \r
244         /* \r
245          * Tick ISR for preemptive scheduler. The tick count is incremented \r
246          * after the context is saved. Then the context is switched if required,\r
247          * and last the context of the task which is to be resumed is restored.\r
248          */\r
249 \r
250         #pragma asm\r
251 \r
252         .global _ReloadTimer0_IRQHandler\r
253         _ReloadTimer0_IRQHandler:\r
254 \r
255         ANDCCR #0xEF                                                    ;Disable Interrupts\r
256         SaveContext                                                             ;Save context\r
257         ORCCR #0x10                                                             ;Re-enable Interrupts\r
258 \r
259         LDI #0xFFFB,R1\r
260         LDI #_tmcsr0, R0\r
261         AND R1,@R0                                                              ;Clear RLT0 interrupt flag\r
262 \r
263         CALL32   _vTaskIncrementTick,R12                ;Increment Tick\r
264         CALL32   _vTaskSwitchContext,R12                ;Switch context if required\r
265 \r
266         ANDCCR #0xEF                                                    ;Disable Interrupts\r
267         RestoreContext                                                  ;Restore context\r
268         ORCCR #0x10                                                             ;Re-enable Interrupts\r
269 \r
270         RETI\r
271 \r
272         #pragma endasm\r
273         \r
274 #else\r
275         \r
276         /* \r
277          * Tick ISR for the cooperative scheduler.  All this does is increment the\r
278          * tick count.  We don't need to switch context, this can only be done by\r
279          * manual calls to taskYIELD();\r
280          */\r
281         __interrupt void ReloadTimer0_IRQHandler( void )\r
282         {\r
283                 /* Clear RLT0 interrupt flag */\r
284                 TMCSR0_UF = 0; \r
285                 vTaskIncrementTick();\r
286         }\r
287 \r
288 #endif\r
289 \r
290 /*\r
291  * Manual context switch. We can use a __nosavereg attribute  as the context \r
292  * would be saved by PortSAVE_CONTEXT().  The context is switched and then \r
293  * the context of the new task is restored saved. \r
294  */\r
295 #pragma asm\r
296 \r
297         .global _vPortYieldDelayed\r
298         _vPortYieldDelayed:\r
299 \r
300         ANDCCR #0xEF                                                    ;Disable Interrupts\r
301         SaveContext                                                             ;Save context\r
302         ORCCR #0x10                                                             ;Re-enable Interrupts\r
303 \r
304         LDI #_dicr, R0\r
305         BANDL #0x0E, @R0                                                ;Clear Delayed interrupt flag\r
306 \r
307         CALL32   _vTaskSwitchContext,R12                ;Switch context if required\r
308 \r
309         ANDCCR #0xEF                                                    ;Disable Interrupts\r
310         RestoreContext                                                  ;Restore context\r
311         ORCCR #0x10                                                             ;Re-enable Interrupts\r
312 \r
313         RETI\r
314 \r
315 #pragma endasm\r
316 /*-----------------------------------------------------------*/\r
317 \r
318 /*\r
319  * Manual context switch. We can use a __nosavereg attribute  as the context \r
320  * would be saved by PortSAVE_CONTEXT().  The context is switched and then \r
321  * the context of the new task is restored saved. \r
322  */      \r
323 #pragma asm\r
324 \r
325         .global _vPortYield\r
326         _vPortYield:\r
327 \r
328         SaveContext                                                             ;Save context\r
329         CALL32   _vTaskSwitchContext,R12                ;Switch context if required\r
330         RestoreContext                                                  ;Restore context\r
331         \r
332         RETI\r
333 \r
334 #pragma endasm\r
335 /*-----------------------------------------------------------*/\r
336 \r