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