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