]> git.sur5r.net Git - freertos/blob - Source/portable/MPLAB/PIC24_dsPIC/port.c
Add PIC24, dsPIC and Coldfire files.
[freertos] / Source / portable / MPLAB / PIC24_dsPIC / port.c
1 /*\r
2         FreeRTOS.org V4.1.0 - Copyright (C) 2003-2006 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         See http://www.FreeRTOS.org for documentation, latest information, license \r
28         and contact details.  Please ensure to read the configuration and relevant \r
29         port sections of the online documentation.\r
30         ***************************************************************************\r
31 */\r
32 \r
33 /*-----------------------------------------------------------\r
34  * Implementation of functions defined in portable.h for the PIC24 port.\r
35  *----------------------------------------------------------*/\r
36 \r
37 /* Scheduler include files. */\r
38 #include "FreeRTOS.h"\r
39 #include "task.h"\r
40 \r
41 /* Hardware specifics. */\r
42 #define portBIT_SET 1\r
43 #define portTIMER_PRESCALE 8\r
44 #define portINITIAL_SR  0\r
45 \r
46 /* The program counter is only 23 bits. */\r
47 #define portUNUSED_PR_BITS      0x7f\r
48 \r
49 /* Records the nesting depth of calls to portENTER_CRITICAL(). */\r
50 unsigned portBASE_TYPE uxCriticalNesting = 0xef;\r
51 \r
52 #ifdef MPLAB_PIC24_PORT\r
53 \r
54         #define portRESTORE_CONTEXT()                                                                                                                                                                           \\r
55                 asm volatile(   "MOV    _pxCurrentTCB, W0               \n"     /* Restore the stack pointer for the task. */                           \\r
56                                                 "MOV    [W0], W15                               \n"                                                                                                                             \\r
57                                                 "POP    W0                                              \n"     /* Restore the critical nesting counter for the task. */        \\r
58                                                 "MOV    W0, _uxCriticalNesting  \n"                                                                                                                             \\r
59                                                 "POP    PSVPAG                                  \n"                                                                                                                             \\r
60                                                 "POP    CORCON                                  \n"                                                                                                                             \\r
61                                                 "POP    TBLPAG                                  \n"                                                                                                                             \\r
62                                                 "POP    RCOUNT                                  \n"     /* Restore the registers from the stack. */                                     \\r
63                                                 "POP    W14                                             \n"                                                                                                                             \\r
64                                                 "POP.D  W12                                             \n"                                                                                                                             \\r
65                                                 "POP.D  W10                                             \n"                                                                                                                             \\r
66                                                 "POP.D  W8                                              \n"                                                                                                                             \\r
67                                                 "POP.D  W6                                              \n"                                                                                                                             \\r
68                                                 "POP.D  W4                                              \n"                                                                                                                             \\r
69                                                 "POP.D  W2                                              \n"                                                                                                                             \\r
70                                                 "POP.D  W0                                              \n"                                                                                                                             \\r
71                                                 "POP    SR                                                " );\r
72 \r
73 \r
74         #define portSAVE_CONTEXT()                                                                                                                                                                                      \\r
75                 asm volatile(   "PUSH   SR                                              \n"     /* Save the SR used by the task.... */                                          \\r
76                                                 "PUSH   W0                                              \n"     /* ....then disable interrupts. */                                                      \\r
77                                                 "MOV    #224, W0                                \n"                                                                                                                             \\r
78                                                 "MOV    W0, SR                                  \n"                                                                                                                             \\r
79                                                 "PUSH   W1                                              \n"     /* Save registers to the stack. */                                                      \\r
80                                                 "PUSH.D W2                                              \n"                                                                                                                             \\r
81                                                 "PUSH.D W4                                              \n"                                                                                                                             \\r
82                                                 "PUSH.D W6                                              \n"                                                                                                                             \\r
83                                                 "PUSH.D W8                                              \n"                                                                                                                             \\r
84                                                 "PUSH.D W10                                             \n"                                                                                                                             \\r
85                                                 "PUSH.D W12                                             \n"                                                                                                                             \\r
86                                                 "PUSH   W14                                             \n"                                                                                                                             \\r
87                                                 "PUSH   RCOUNT                                  \n"                                                                                                                             \\r
88                                                 "PUSH   TBLPAG                                  \n"                                                                                                                             \\r
89                                                 "PUSH   CORCON                                  \n"                                                                                                                             \\r
90                                                 "PUSH   PSVPAG                                  \n"                                                                                                                             \\r
91                                                 "MOV    _uxCriticalNesting, W0  \n"     /* Save the critical nesting counter for the task. */           \\r
92                                                 "PUSH   W0                                              \n"                                                                                                                             \\r
93                                                 "MOV    _pxCurrentTCB, W0               \n"     /* Save the new top of stack into the TCB. */                           \\r
94                                                 "MOV    W15, [W0]                                 ");\r
95 \r
96 #endif /* MPLAB_PIC24_PORT */\r
97 \r
98 #ifdef MPLAB_DSPIC_PORT\r
99 \r
100         #define portRESTORE_CONTEXT()                                                                                                                                                                           \\r
101                 asm volatile(   "MOV    _pxCurrentTCB, W0               \n"     /* Restore the stack pointer for the task. */                           \\r
102                                                 "MOV    [W0], W15                               \n"                                                                                                                             \\r
103                                                 "POP    W0                                              \n"     /* Restore the critical nesting counter for the task. */        \\r
104                                                 "MOV    W0, _uxCriticalNesting  \n"                                                                                                                             \\r
105                                                 "POP    PSVPAG                                  \n"                                                                                                                             \\r
106                                                 "POP    CORCON                                  \n"                                                                                                                             \\r
107                                                 "POP    DOENDH                                  \n"                                                                                                                             \\r
108                                                 "POP    DOENDL                                  \n"                                                                                                                             \\r
109                                                 "POP    DOSTARTH                                \n"                                                                                                                             \\r
110                                                 "POP    DOSTARTL                                \n"                                                                                                                             \\r
111                                                 "POP    DCOUNT                                  \n"                                                                                                                             \\r
112                                                 "POP    ACCBU                                   \n"                                                                                                                             \\r
113                                                 "POP    ACCBH                                   \n"                                                                                                                             \\r
114                                                 "POP    ACCBL                                   \n"                                                                                                                             \\r
115                                                 "POP    ACCAU                                   \n"                                                                                                                             \\r
116                                                 "POP    ACCAH                                   \n"                                                                                                                             \\r
117                                                 "POP    ACCAL                                   \n"                                                                                                                             \\r
118                                                 "POP    TBLPAG                                  \n"                                                                                                                             \\r
119                                                 "POP    RCOUNT                                  \n"     /* Restore the registers from the stack. */                                     \\r
120                                                 "POP    W14                                             \n"                                                                                                                             \\r
121                                                 "POP.D  W12                                             \n"                                                                                                                             \\r
122                                                 "POP.D  W10                                             \n"                                                                                                                             \\r
123                                                 "POP.D  W8                                              \n"                                                                                                                             \\r
124                                                 "POP.D  W6                                              \n"                                                                                                                             \\r
125                                                 "POP.D  W4                                              \n"                                                                                                                             \\r
126                                                 "POP.D  W2                                              \n"                                                                                                                             \\r
127                                                 "POP.D  W0                                              \n"                                                                                                                             \\r
128                                                 "POP    SR                                                " );\r
129 \r
130 \r
131         #define portSAVE_CONTEXT()                                                                                                                                                                                      \\r
132                 asm volatile(   "PUSH   SR                                              \n"     /* Save the SR used by the task.... */                                          \\r
133                                                 "PUSH   W0                                              \n"     /* ....then disable interrupts. */                                                      \\r
134                                                 "MOV    #224, W0                                \n"                                                                                                                             \\r
135                                                 "MOV    W0, SR                                  \n"                                                                                                                             \\r
136                                                 "PUSH   W1                                              \n"     /* Save registers to the stack. */                                                      \\r
137                                                 "PUSH.D W2                                              \n"                                                                                                                             \\r
138                                                 "PUSH.D W4                                              \n"                                                                                                                             \\r
139                                                 "PUSH.D W6                                              \n"                                                                                                                             \\r
140                                                 "PUSH.D W8                                              \n"                                                                                                                             \\r
141                                                 "PUSH.D W10                                             \n"                                                                                                                             \\r
142                                                 "PUSH.D W12                                             \n"                                                                                                                             \\r
143                                                 "PUSH   W14                                             \n"                                                                                                                             \\r
144                                                 "PUSH   RCOUNT                                  \n"                                                                                                                             \\r
145                                                 "PUSH   TBLPAG                                  \n"                                                                                                                             \\r
146                                                 "PUSH   ACCAL                                   \n"                                                                                                                             \\r
147                                                 "PUSH   ACCAH                                   \n"                                                                                                                             \\r
148                                                 "PUSH   ACCAU                                   \n"                                                                                                                             \\r
149                                                 "PUSH   ACCBL                                   \n"                                                                                                                             \\r
150                                                 "PUSH   ACCBH                                   \n"                                                                                                                             \\r
151                                                 "PUSH   ACCBU                                   \n"                                                                                                                             \\r
152                                                 "PUSH   DCOUNT                                  \n"                                                                                                                             \\r
153                                                 "PUSH   DOSTARTL                                \n"                                                                                                                             \\r
154                                                 "PUSH   DOSTARTH                                \n"                                                                                                                             \\r
155                                                 "PUSH   DOENDL                                  \n"                                                                                                                             \\r
156                                                 "PUSH   DOENDH                                  \n"                                                                                                                             \\r
157                                                 "PUSH   CORCON                                  \n"                                                                                                                             \\r
158                                                 "PUSH   PSVPAG                                  \n"                                                                                                                             \\r
159                                                 "MOV    _uxCriticalNesting, W0  \n"     /* Save the critical nesting counter for the task. */           \\r
160                                                 "PUSH   W0                                              \n"                                                                                                                             \\r
161                                                 "MOV    _pxCurrentTCB, W0               \n"     /* Save the new top of stack into the TCB. */                           \\r
162                                                 "MOV    W15, [W0]                                 " );\r
163 \r
164 #endif /* MPLAB_DSPIC_PORT */\r
165 \r
166 /*\r
167  * Setup the timer used to generate the tick interrupt.\r
168  */\r
169 static void prvSetupTimerInterrupt( void );\r
170 \r
171 /* \r
172  * See header file for description. \r
173  */\r
174 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )\r
175 {\r
176 unsigned portSHORT usCode;\r
177 portBASE_TYPE i;\r
178 \r
179 const portSTACK_TYPE xInitialStack[] = \r
180 {\r
181         0x1111, /* W1 */\r
182         0x2222, /* W2 */\r
183         0x3333, /* W3 */\r
184         0x4444, /* W4 */\r
185         0x5555, /* W5 */\r
186         0x6666, /* W6 */\r
187         0x7777, /* W7 */\r
188         0x8888, /* W8 */\r
189         0x9999, /* W9 */\r
190         0xaaaa, /* W10 */\r
191         0xbbbb, /* W11 */\r
192         0xcccc, /* W12 */\r
193         0xdddd, /* W13 */\r
194         0xeeee, /* W14 */\r
195         0xcdce, /* RCOUNT */\r
196         0xabac, /* TBLPAG */\r
197 \r
198         /* dsPIC specific registers. */\r
199         #ifdef MPLAB_DSPIC_PORT\r
200                 0x0202, /* ACCAL */\r
201                 0x0303, /* ACCAH */\r
202                 0x0404, /* ACCAU */\r
203                 0x0505, /* ACCBL */\r
204                 0x0606, /* ACCBH */\r
205                 0x0707, /* ACCBU */\r
206                 0x0808, /* DCOUNT */\r
207                 0x090a, /* DOSTARTL */\r
208                 0x1010, /* DOSTARTH */\r
209                 0x1110, /* DOENDL */\r
210                 0x1212, /* DOENDH */\r
211         #endif\r
212 };\r
213 \r
214         /* Setup the stack as if a yield had occurred.\r
215 \r
216         Save the low bytes of the program counter. */\r
217         usCode = ( unsigned portSHORT ) pxCode;\r
218         *pxTopOfStack = ( portSTACK_TYPE ) usCode;\r
219         pxTopOfStack++;\r
220 \r
221         /* Save the high byte of the program counter.  This will always be zero\r
222         here as it is passed in a 16bit pointer.  If the address is greater than\r
223         16 bits then the pointer will point to a jump table. */\r
224         *pxTopOfStack = ( portSTACK_TYPE ) 0;\r
225         pxTopOfStack++;\r
226 \r
227         /* Status register with interrupts enabled. */\r
228         *pxTopOfStack = portINITIAL_SR;\r
229         pxTopOfStack++;\r
230 \r
231         /* Parameters are passed in W0. */\r
232         *pxTopOfStack = ( portSTACK_TYPE ) pvParameters;\r
233         pxTopOfStack++;\r
234 \r
235         for( i = 0; i < ( sizeof( xInitialStack ) / sizeof( portSTACK_TYPE ) ); i++ )\r
236         {\r
237                 *pxTopOfStack = xInitialStack[ i ];\r
238                 pxTopOfStack++;\r
239         }\r
240 \r
241         *pxTopOfStack = CORCON;\r
242         pxTopOfStack++;\r
243         *pxTopOfStack = PSVPAG;\r
244         pxTopOfStack++;\r
245 \r
246         /* Finally the critical nesting depth. */\r
247         *pxTopOfStack = 0x00;\r
248         pxTopOfStack++;\r
249 \r
250         return pxTopOfStack;\r
251 }\r
252 /*-----------------------------------------------------------*/\r
253 \r
254 portBASE_TYPE xPortStartScheduler( void )\r
255 {\r
256         /* Setup a timer for the tick ISR. */\r
257         prvSetupTimerInterrupt(); \r
258 \r
259         /* Restore the context of the first task to run. */\r
260         portRESTORE_CONTEXT();\r
261 \r
262         /* Simulate the end of the yield function. */\r
263         asm volatile ( "return" );\r
264 \r
265         /* Should not reach here. */\r
266         return pdTRUE;\r
267 }\r
268 /*-----------------------------------------------------------*/\r
269 \r
270 void vPortEndScheduler( void )\r
271 {\r
272         /* It is unlikely that the scheduler for the PIC port will get stopped\r
273         once running.  If required disable the tick interrupt here, then return \r
274         to xPortStartScheduler(). */\r
275 }\r
276 /*-----------------------------------------------------------*/\r
277 \r
278 /*\r
279  * Manual context switch.  This is similar to the tick context switch,\r
280  * but does not increment the tick count.  It must be identical to the\r
281  * tick context switch in how it stores the stack of a task.\r
282  */\r
283 void vPortYield( void )\r
284 {\r
285         portSAVE_CONTEXT();\r
286         vTaskSwitchContext();\r
287         portRESTORE_CONTEXT();\r
288 }\r
289 /*-----------------------------------------------------------*/\r
290 \r
291 /*\r
292  * Setup a timer for a regular tick.\r
293  */\r
294 static void prvSetupTimerInterrupt( void )\r
295 {\r
296 const unsigned portLONG ulCompareMatch = ( configCPU_CLOCK_HZ / portTIMER_PRESCALE ) / configTICK_RATE_HZ;\r
297 \r
298         /* Prescale of 8. */\r
299         T1CON = 0;\r
300         TMR1 = 0;\r
301 \r
302         PR1 = ( unsigned portSHORT ) ulCompareMatch;\r
303 \r
304         /* Setup timer 1 interrupt priority. */\r
305         IPC0bits.T1IP = portKERNEL_INTERRUPT_PRIORITY;\r
306 \r
307         /* Clear the interrupt as a starting condition. */\r
308         IFS0bits.T1IF = 0;\r
309 \r
310         /* Enable the interrupt. */\r
311         IEC0bits.T1IE = 1;\r
312 \r
313         /* Setup the prescale value. */\r
314         T1CONbits.TCKPS0 = 1;\r
315         T1CONbits.TCKPS1 = 0;\r
316 \r
317         /* Start the timer. */\r
318         T1CONbits.TON = 1;\r
319 }\r
320 /*-----------------------------------------------------------*/\r
321 \r
322 void vPortEnterCritical( void )\r
323 {\r
324         portDISABLE_INTERRUPTS();\r
325         uxCriticalNesting++;\r
326 }\r
327 /*-----------------------------------------------------------*/\r
328 \r
329 void vPortExitCritical( void )\r
330 {\r
331         uxCriticalNesting--;\r
332         if( uxCriticalNesting == 0 )\r
333         {\r
334                 portENABLE_INTERRUPTS();\r
335         }\r
336 }\r
337 /*-----------------------------------------------------------*/\r
338 \r
339 void __attribute__((__interrupt__)) _T1Interrupt( void )\r
340 {\r
341         vTaskIncrementTick();\r
342 \r
343         /* Clear the timer interrupt. */\r
344         IFS0bits.T1IF = 0;\r
345 \r
346         #if configUSE_PREEMPTION == 1\r
347                 portYIELD();\r
348         #endif\r
349 }\r