]> begriffs open source - freertos/blob - Source/portable/MPLAB/PIC24_dsPIC/port.c
Prepare for V5.0.4 release.
[freertos] / Source / portable / MPLAB / PIC24_dsPIC / port.c
1 /*\r
2         FreeRTOS.org V5.0.4 - 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 #endif /* MPLAB_PIC24_PORT */\r
107 \r
108 #ifdef MPLAB_DSPIC_PORT\r
109 \r
110         #define portRESTORE_CONTEXT()                                                                                                                                                                           \\r
111                 asm volatile(   "MOV    _pxCurrentTCB, W0               \n"     /* Restore the stack pointer for the task. */                           \\r
112                                                 "MOV    [W0], W15                               \n"                                                                                                                             \\r
113                                                 "POP    W0                                              \n"     /* Restore the critical nesting counter for the task. */        \\r
114                                                 "MOV    W0, _uxCriticalNesting  \n"                                                                                                                             \\r
115                                                 "POP    PSVPAG                                  \n"                                                                                                                             \\r
116                                                 "POP    CORCON                                  \n"                                                                                                                             \\r
117                                                 "POP    DOENDH                                  \n"                                                                                                                             \\r
118                                                 "POP    DOENDL                                  \n"                                                                                                                             \\r
119                                                 "POP    DOSTARTH                                \n"                                                                                                                             \\r
120                                                 "POP    DOSTARTL                                \n"                                                                                                                             \\r
121                                                 "POP    DCOUNT                                  \n"                                                                                                                             \\r
122                                                 "POP    ACCBU                                   \n"                                                                                                                             \\r
123                                                 "POP    ACCBH                                   \n"                                                                                                                             \\r
124                                                 "POP    ACCBL                                   \n"                                                                                                                             \\r
125                                                 "POP    ACCAU                                   \n"                                                                                                                             \\r
126                                                 "POP    ACCAH                                   \n"                                                                                                                             \\r
127                                                 "POP    ACCAL                                   \n"                                                                                                                             \\r
128                                                 "POP    TBLPAG                                  \n"                                                                                                                             \\r
129                                                 "POP    RCOUNT                                  \n"     /* Restore the registers from the stack. */                                     \\r
130                                                 "POP    W14                                             \n"                                                                                                                             \\r
131                                                 "POP.D  W12                                             \n"                                                                                                                             \\r
132                                                 "POP.D  W10                                             \n"                                                                                                                             \\r
133                                                 "POP.D  W8                                              \n"                                                                                                                             \\r
134                                                 "POP.D  W6                                              \n"                                                                                                                             \\r
135                                                 "POP.D  W4                                              \n"                                                                                                                             \\r
136                                                 "POP.D  W2                                              \n"                                                                                                                             \\r
137                                                 "POP.D  W0                                              \n"                                                                                                                             \\r
138                                                 "POP    SR                                                " );\r
139 \r
140 #endif /* MPLAB_DSPIC_PORT */\r
141 \r
142 /*\r
143  * Setup the timer used to generate the tick interrupt.\r
144  */\r
145 static void prvSetupTimerInterrupt( void );\r
146 \r
147 /* \r
148  * See header file for description. \r
149  */\r
150 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )\r
151 {\r
152 unsigned portSHORT usCode;\r
153 portBASE_TYPE i;\r
154 \r
155 const portSTACK_TYPE xInitialStack[] = \r
156 {\r
157         0x1111, /* W1 */\r
158         0x2222, /* W2 */\r
159         0x3333, /* W3 */\r
160         0x4444, /* W4 */\r
161         0x5555, /* W5 */\r
162         0x6666, /* W6 */\r
163         0x7777, /* W7 */\r
164         0x8888, /* W8 */\r
165         0x9999, /* W9 */\r
166         0xaaaa, /* W10 */\r
167         0xbbbb, /* W11 */\r
168         0xcccc, /* W12 */\r
169         0xdddd, /* W13 */\r
170         0xeeee, /* W14 */\r
171         0xcdce, /* RCOUNT */\r
172         0xabac, /* TBLPAG */\r
173 \r
174         /* dsPIC specific registers. */\r
175         #ifdef MPLAB_DSPIC_PORT\r
176                 0x0202, /* ACCAL */\r
177                 0x0303, /* ACCAH */\r
178                 0x0404, /* ACCAU */\r
179                 0x0505, /* ACCBL */\r
180                 0x0606, /* ACCBH */\r
181                 0x0707, /* ACCBU */\r
182                 0x0808, /* DCOUNT */\r
183                 0x090a, /* DOSTARTL */\r
184                 0x1010, /* DOSTARTH */\r
185                 0x1110, /* DOENDL */\r
186                 0x1212, /* DOENDH */\r
187         #endif\r
188 };\r
189 \r
190         /* Setup the stack as if a yield had occurred.\r
191 \r
192         Save the low bytes of the program counter. */\r
193         usCode = ( unsigned portSHORT ) pxCode;\r
194         *pxTopOfStack = ( portSTACK_TYPE ) usCode;\r
195         pxTopOfStack++;\r
196 \r
197         /* Save the high byte of the program counter.  This will always be zero\r
198         here as it is passed in a 16bit pointer.  If the address is greater than\r
199         16 bits then the pointer will point to a jump table. */\r
200         *pxTopOfStack = ( portSTACK_TYPE ) 0;\r
201         pxTopOfStack++;\r
202 \r
203         /* Status register with interrupts enabled. */\r
204         *pxTopOfStack = portINITIAL_SR;\r
205         pxTopOfStack++;\r
206 \r
207         /* Parameters are passed in W0. */\r
208         *pxTopOfStack = ( portSTACK_TYPE ) pvParameters;\r
209         pxTopOfStack++;\r
210 \r
211         for( i = 0; i < ( sizeof( xInitialStack ) / sizeof( portSTACK_TYPE ) ); i++ )\r
212         {\r
213                 *pxTopOfStack = xInitialStack[ i ];\r
214                 pxTopOfStack++;\r
215         }\r
216 \r
217         *pxTopOfStack = CORCON;\r
218         pxTopOfStack++;\r
219         *pxTopOfStack = PSVPAG;\r
220         pxTopOfStack++;\r
221 \r
222         /* Finally the critical nesting depth. */\r
223         *pxTopOfStack = 0x00;\r
224         pxTopOfStack++;\r
225 \r
226         return pxTopOfStack;\r
227 }\r
228 /*-----------------------------------------------------------*/\r
229 \r
230 portBASE_TYPE xPortStartScheduler( void )\r
231 {\r
232         /* Setup a timer for the tick ISR. */\r
233         prvSetupTimerInterrupt(); \r
234 \r
235         /* Restore the context of the first task to run. */\r
236         portRESTORE_CONTEXT();\r
237 \r
238         /* Simulate the end of the yield function. */\r
239         asm volatile ( "return" );\r
240 \r
241         /* Should not reach here. */\r
242         return pdTRUE;\r
243 }\r
244 /*-----------------------------------------------------------*/\r
245 \r
246 void vPortEndScheduler( void )\r
247 {\r
248         /* It is unlikely that the scheduler for the PIC port will get stopped\r
249         once running.  If required disable the tick interrupt here, then return \r
250         to xPortStartScheduler(). */\r
251 }\r
252 /*-----------------------------------------------------------*/\r
253 \r
254 /*\r
255  * Setup a timer for a regular tick.\r
256  */\r
257 static void prvSetupTimerInterrupt( void )\r
258 {\r
259 const unsigned portLONG ulCompareMatch = ( configCPU_CLOCK_HZ / portTIMER_PRESCALE ) / configTICK_RATE_HZ;\r
260 \r
261         /* Prescale of 8. */\r
262         T1CON = 0;\r
263         TMR1 = 0;\r
264 \r
265         PR1 = ( unsigned portSHORT ) ulCompareMatch;\r
266 \r
267         /* Setup timer 1 interrupt priority. */\r
268         IPC0bits.T1IP = configKERNEL_INTERRUPT_PRIORITY;\r
269 \r
270         /* Clear the interrupt as a starting condition. */\r
271         IFS0bits.T1IF = 0;\r
272 \r
273         /* Enable the interrupt. */\r
274         IEC0bits.T1IE = 1;\r
275 \r
276         /* Setup the prescale value. */\r
277         T1CONbits.TCKPS0 = 1;\r
278         T1CONbits.TCKPS1 = 0;\r
279 \r
280         /* Start the timer. */\r
281         T1CONbits.TON = 1;\r
282 }\r
283 /*-----------------------------------------------------------*/\r
284 \r
285 void vPortEnterCritical( void )\r
286 {\r
287         portDISABLE_INTERRUPTS();\r
288         uxCriticalNesting++;\r
289 }\r
290 /*-----------------------------------------------------------*/\r
291 \r
292 void vPortExitCritical( void )\r
293 {\r
294         uxCriticalNesting--;\r
295         if( uxCriticalNesting == 0 )\r
296         {\r
297                 portENABLE_INTERRUPTS();\r
298         }\r
299 }\r
300 /*-----------------------------------------------------------*/\r
301 \r
302 void __attribute__((__interrupt__, auto_psv)) _T1Interrupt( void )\r
303 {\r
304         /* Clear the timer interrupt. */\r
305         IFS0bits.T1IF = 0;\r
306 \r
307         vTaskIncrementTick();\r
308 \r
309         #if configUSE_PREEMPTION == 1\r
310                 portYIELD();\r
311         #endif\r
312 }\r