]> git.sur5r.net Git - freertos/blob - Source/portable/WizC/PIC18/portmacro.h
04953224ea306e72be0ea584f9ec61064f5396b5
[freertos] / Source / portable / WizC / PIC18 / portmacro.h
1 /*\r
2         FreeRTOS.org V4.2.1 - 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 V3.0.0\r
38 \r
39 Changes from V3.0.1\r
40 */\r
41 #ifndef PORTMACRO_H\r
42 #define PORTMACRO_H\r
43 \r
44 #if !defined(_SERIES) || _SERIES != 18\r
45         #error "WizC supports FreeRTOS on the Microchip PIC18-series only"\r
46 #endif\r
47 \r
48 #if !defined(QUICKCALL) || QUICKCALL != 1\r
49         #error "QuickCall must be enabled (see ProjectOptions/Optimisations)"\r
50 #endif\r
51 \r
52 #include <stddef.h>\r
53 #include <pic.h>\r
54 \r
55 #define portCHAR                char\r
56 #define portFLOAT               float\r
57 #define portDOUBLE              portFLOAT\r
58 #define portLONG                long\r
59 #define portSHORT               short\r
60 #define portSTACK_TYPE  unsigned char\r
61 #define portBASE_TYPE   char\r
62 \r
63 #if( configUSE_16_BIT_TICKS == 1 )\r
64         typedef unsigned portSHORT portTickType;\r
65         #define portMAX_DELAY ( portTickType )  ( 0xFFFF )\r
66 #else\r
67         typedef unsigned portLONG portTickType;\r
68         #define portMAX_DELAY ( portTickType )  ( 0xFFFFFFFF )\r
69 #endif\r
70 \r
71 #define portBYTE_ALIGNMENT                      1\r
72 \r
73 /*-----------------------------------------------------------*/\r
74 \r
75 /*\r
76  * Constant used for context switch macro when we require the interrupt \r
77  * enable state to be forced when the interrupted task is switched back in.\r
78  */\r
79 #define portINTERRUPTS_FORCED                           (0x01)\r
80 \r
81 /*\r
82  * Constant used for context switch macro when we require the interrupt \r
83  * enable state to be unchanged when the interrupted task is switched back in.\r
84  */\r
85 #define portINTERRUPTS_UNCHANGED                        (0x00)\r
86 \r
87 /* Initial interrupt enable state for newly created tasks.  This value is\r
88  * used when a task switches in for the first time.\r
89  */\r
90 #define portINTERRUPTS_INITIAL_STATE            (portINTERRUPTS_FORCED)\r
91 \r
92 /*\r
93  * Macros to modify the global interrupt enable bit in INTCON.\r
94  */\r
95 #define portDISABLE_INTERRUPTS()        \\r
96         do                                                              \\r
97         {                                                               \\r
98                 bGIE=0;                                         \\r
99         } while(bGIE)   // MicroChip recommends this check!\r
100         \r
101 #define portENABLE_INTERRUPTS()         \\r
102         do                                                              \\r
103         {                                                               \\r
104                 bGIE=1;                                         \\r
105         } while(0)\r
106 \r
107 /*-----------------------------------------------------------*/ \r
108 \r
109 /*\r
110  * Critical section macros.\r
111  */\r
112 extern unsigned portCHAR ucCriticalNesting;\r
113 \r
114 #define portNO_CRITICAL_SECTION_NESTING         ( ( unsigned portCHAR ) 0 )\r
115 \r
116 #define portENTER_CRITICAL()                                                                            \\r
117         do                                                                                                                              \\r
118         {                                                                                                                               \\r
119                 portDISABLE_INTERRUPTS();                                                                       \\r
120                                                                                                                                         \\r
121                 /*                                                                                                                      \\r
122                  * Now interrupts are disabled ucCriticalNesting                        \\r
123                  * can be accessed directly. Increment                                          \\r
124                  * ucCriticalNesting to keep a count of how                                     \\r
125                  * many times portENTER_CRITICAL() has been called.             \\r
126                  */                                                                                                                     \\r
127                 ucCriticalNesting++;                                                                            \\r
128         } while(0)\r
129 \r
130 #define portEXIT_CRITICAL()                                                                                     \\r
131         do                                                                                                                              \\r
132         {                                                                                                                               \\r
133                 if(ucCriticalNesting > portNO_CRITICAL_SECTION_NESTING)         \\r
134                 {                                                                                                                       \\r
135                         /*                                                                                                              \\r
136                          * Decrement the nesting count as we are leaving a              \\r
137                          * critical section.                                                                    \\r
138                          */                                                                                                             \\r
139                         ucCriticalNesting--;                                                                    \\r
140                 }                                                                                                                       \\r
141                                                                                                                                         \\r
142                 /*                                                                                                                      \\r
143                  * If the nesting level has reached zero then                           \\r
144                  * interrupts should be re-enabled.                                                     \\r
145                  */                                                                                                                     \\r
146                 if( ucCriticalNesting == portNO_CRITICAL_SECTION_NESTING )      \\r
147                 {                                                                                                                       \\r
148                         portENABLE_INTERRUPTS();                                                                \\r
149                 }                                                                                                                       \\r
150         } while(0)\r
151 \r
152 /*-----------------------------------------------------------*/\r
153 \r
154 /*\r
155  * The minimal stacksize is calculated on the first reference of\r
156  * portMINIMAL_STACK_SIZE. Some input to this calculation is\r
157  * compiletime determined, other input is port-defined (see port.c)\r
158  */\r
159 extern unsigned portSHORT usPortCALCULATE_MINIMAL_STACK_SIZE( void );\r
160 extern unsigned portSHORT usCalcMinStackSize;\r
161 \r
162 #define portMINIMAL_STACK_SIZE                                  \\r
163         ((usCalcMinStackSize == 0)                                      \\r
164                 ? usPortCALCULATE_MINIMAL_STACK_SIZE()  \\r
165                 : usCalcMinStackSize )\r
166 \r
167 /*\r
168  * WizC uses a downgrowing stack\r
169  */\r
170 #define portSTACK_GROWTH                        ( -1 )\r
171 \r
172 /*-----------------------------------------------------------*/\r
173 \r
174 /*\r
175  * Macro's that pushes all the registers that make up the context of a task onto\r
176  * the stack, then saves the new top of stack into the TCB. TOSU and TBLPTRU\r
177  * are only saved/restored on devices with more than 64kB (32k Words) ROM.\r
178  * \r
179  * The stackpointer is helt by WizC in FSR2 and points to the first free byte.\r
180  * WizC uses a "downgrowing" stack. There is no framepointer.\r
181  *\r
182  * We keep track of the interruptstatus using ucCriticalNesting. When this\r
183  * value equals zero, interrupts have to be enabled upon exit from the\r
184  * portRESTORE_CONTEXT macro.\r
185  * \r
186  * If this is called from an ISR then the interrupt enable bits must have been \r
187  * set for the ISR to ever get called.  Therefore we want to save\r
188  * ucCriticalNesting with value zero. This means the interrupts will again be\r
189  * re-enabled when the interrupted task is switched back in.\r
190  *\r
191  * If this is called from a manual context switch (i.e. from a call to yield),\r
192  * then we want to keep the current value of ucCritialNesting so it is restored\r
193  * with its current value. This allows a yield from within a critical section.\r
194  *\r
195  * The compiler uses some locations at the bottom of RAM for temporary\r
196  * storage. The compiler may also have been instructed to optimize\r
197  * function-parameters and local variables to global storage. The compiler\r
198  * uses an area called LocOpt for this wizC feature.\r
199  * The total overheadstorage has to be saved in it's entirety as part of\r
200  * a task context. These macro's store/restore from data address 0x0000 to\r
201  * (OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE - 1).\r
202  * OVERHEADPAGE0, LOCOPTSIZE and MAXLOCOPTSIZE are compiler-generated\r
203  * assembler definitions.\r
204  */\r
205 \r
206 #define portSAVE_CONTEXT( ucInterruptForced )                                           \\r
207         do                                                                                                                              \\r
208         {                                                                                                                               \\r
209                 portDISABLE_INTERRUPTS();                                                                       \\r
210                                                                                                                                         \\r
211                 _Pragma("asm")                                                                                          \\r
212                         dupmodoff                                                                                               \\r
213                         ;                                                                                                               \\r
214                         ; Push the relevant SFR's onto the task's stack                 \\r
215                         ;                                                                                                               \\r
216                         movff   STATUS,POSTDEC2                                                                 \\r
217                         movff   WREG,POSTDEC2                                                                   \\r
218                         movff   BSR,POSTDEC2                                                                    \\r
219                         movff   PRODH,POSTDEC2                                                                  \\r
220                         movff   PRODL,POSTDEC2                                                                  \\r
221                         movff   FSR0H,POSTDEC2                                                                  \\r
222                         movff   FSR0L,POSTDEC2                                                                  \\r
223                         movff   FSR1H,POSTDEC2                                                                  \\r
224                         movff   FSR1L,POSTDEC2                                                                  \\r
225                         movff   TABLAT,POSTDEC2                                                                 \\r
226                         if __ROMSIZE > 0x8000                                                                   \\r
227                                 movff   TBLPTRU,POSTDEC2                                                        \\r
228                         endif                                                                                                   \\r
229                         movff   TBLPTRH,POSTDEC2                                                                \\r
230                         movff   TBLPTRL,POSTDEC2                                                                \\r
231                         if __ROMSIZE > 0x8000                                                                   \\r
232                                 movff   PCLATU,POSTDEC2                                                         \\r
233                         endif                                                                                                   \\r
234                         movff   PCLATH,POSTDEC2                                                                 \\r
235                         ;                                                                                                               \\r
236                         ; Store the compiler-scratch-area as described above.   \\r
237                         ;                                                                                                               \\r
238                         movlw   OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE                  \\r
239                         clrf    FSR0L,ACCESS                                                                    \\r
240                         clrf    FSR0H,ACCESS                                                                    \\r
241                 _rtos_S1:                                                                                                       \\r
242                         movff   POSTINC0,POSTDEC2                                                               \\r
243                         decfsz  WREG,W,ACCESS                                                                   \\r
244                         SMARTJUMP _rtos_S1                                                                              \\r
245                         ;                                                                                                               \\r
246                         ; Save the pic call/return-stack belonging to the               \\r
247                         ; current task by copying it to the task's software-    \\r
248                         ; stack. We save the hardware stack pointer (which              \\r
249                         ; is the number of addresses on the stack) in the               \\r
250                         ; W-register first because we need it later and it              \\r
251                         ; is modified in the save-loop by executing pop's.              \\r
252                         ; After the loop the W-register is stored on the                \\r
253                         ; stack, too.                                                                                   \\r
254                         ;                                                                                                               \\r
255                         movf    STKPTR,W,ACCESS                                                                 \\r
256                         bz              _rtos_s3                                                                                \\r
257                 _rtos_S2:                                                                                                       \\r
258                         if __ROMSIZE > 0x8000                                                                   \\r
259                                 movff   TOSU,POSTDEC2                                                           \\r
260                         endif                                                                                                   \\r
261                         movff   TOSH,POSTDEC2                                                                   \\r
262                         movff   TOSL,POSTDEC2                                                                   \\r
263                         pop                                                                                                             \\r
264                         tstfsz  STKPTR,ACCESS                                                                   \\r
265                         SMARTJUMP _rtos_S2                                                                              \\r
266                 _rtos_s3:                                                                                                       \\r
267                         movwf   POSTDEC2,ACCESS                                                                 \\r
268                         ;                                                                                                               \\r
269                         ; Next the value for ucCriticalNesting used by the              \\r
270                         ; task is stored on the stack. When                                             \\r
271                         ; (ucInterruptForced == portINTERRUPTS_FORCED), we save \\r
272                         ; it as 0 (portNO_CRITICAL_SECTION_NESTING).                    \\r
273                         ;                                                                                                               \\r
274                         if ucInterruptForced == portINTERRUPTS_FORCED                   \\r
275                                 clrf POSTDEC2,ACCESS                                                            \\r
276                         else                                                                                                    \\r
277                                 movff   ucCriticalNesting,POSTDEC2                                      \\r
278                         endif                                                                                                   \\r
279                         ;                                                                                                               \\r
280                         ; Save the new top of the software stack in the TCB.    \\r
281                         ;                                                                                                               \\r
282                         movff   pxCurrentTCB,FSR0L                                                              \\r
283                         movff   pxCurrentTCB+1,FSR0H                                                    \\r
284                         movff   FSR2L,POSTINC0                                                                  \\r
285                         movff   FSR2H,POSTINC0                                                                  \\r
286                         dupmodon                                                                                                \\r
287                 _Pragma("asmend")                                                                                       \\r
288         } while(0)\r
289 \r
290 /************************************************************/\r
291 \r
292 /*\r
293  * This is the reverse of portSAVE_CONTEXT.\r
294  */\r
295 #define portRESTORE_CONTEXT()                                                                           \\r
296         do                                                                                                                              \\r
297         {                                                                                                                               \\r
298                 _Pragma("asm")                                                                                          \\r
299                         dupmodoff                                                                                               \\r
300                         ;                                                                                                               \\r
301                         ; Set FSR0 to point to pxCurrentTCB->pxTopOfStack.              \\r
302                         ;                                                                                                               \\r
303                         movff   pxCurrentTCB,FSR0L                                                              \\r
304                         movff   pxCurrentTCB+1,FSR0H                                                    \\r
305                         ;                                                                                                               \\r
306                         ; De-reference FSR0 to set the address it holds into    \\r
307                         ; FSR2 (i.e. *( pxCurrentTCB->pxTopOfStack ) ). FSR2    \\r
308                         ; is used by wizC as stackpointer.                                              \\r
309                         ;                                                                                                               \\r
310                         movff   POSTINC0,FSR2L                                                                  \\r
311                         movff   POSTINC0,FSR2H                                                                  \\r
312                         ;                                                                                                               \\r
313                         ; Next, the value for ucCriticalNesting used by the             \\r
314                         ; task is retrieved from the stack.                                             \\r
315                         ;                                                                                                               \\r
316                         movff   PREINC2,ucCriticalNesting                                               \\r
317                         ;                                                                                                               \\r
318                         ; Rebuild the pic call/return-stack. The number of              \\r
319                         ; return addresses is the next item on the task stack.  \\r
320                         ; Save this number in PRODL. Then fetch the addresses   \\r
321                         ; and store them on the hardwarestack.                                  \\r
322                         ; The datasheets say we can't use movff here...                 \\r
323                         ;                                                                                                               \\r
324                         movff   PREINC2,PRODL   // Use PRODL as tempregister    \\r
325                         clrf    STKPTR,ACCESS                                                                   \\r
326                 _rtos_R1:                                                                                                       \\r
327                         push                                                                                                    \\r
328                         movf    PREINC2,W,ACCESS                                                                \\r
329                         movwf   TOSL,ACCESS                                                                             \\r
330                         movf    PREINC2,W,ACCESS                                                                \\r
331                         movwf   TOSH,ACCESS                                                                             \\r
332                         if __ROMSIZE > 0x8000                                                                   \\r
333                                 movf    PREINC2,W,ACCESS                                                        \\r
334                                 movwf   TOSU,ACCESS                                                                     \\r
335                         else                                                                                                    \\r
336                                 clrf    TOSU,ACCESS                                                                     \\r
337                         endif                                                                                                   \\r
338                         decfsz  PRODL,F,ACCESS                                                                  \\r
339                         SMARTJUMP _rtos_R1                                                                              \\r
340                         ;                                                                                                               \\r
341                         ; Restore the compiler's working storage area to page 0 \\r
342                         ;                                                                                                               \\r
343                         movlw   OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE                  \\r
344                         movwf   FSR0L,ACCESS                                                                    \\r
345                         clrf    FSR0H,ACCESS                                                                    \\r
346                 _rtos_R2:                                                                                                       \\r
347                         decf    FSR0L,F,ACCESS                                                                  \\r
348                         movff   PREINC2,INDF0                                                                   \\r
349                         tstfsz  FSR0L,ACCESS                                                                    \\r
350                         SMARTJUMP _rtos_R2                                                                              \\r
351                         ;                                                                                                               \\r
352                         ; Restore the sfr's forming the tasks context.                  \\r
353                         ; We cannot yet restore bsr, w and status because               \\r
354                         ; we need these registers for a final test.                             \\r
355                         ;                                                                                                               \\r
356                         movff   PREINC2,PCLATH                                                                  \\r
357                         if __ROMSIZE > 0x8000                                                                   \\r
358                                 movff   PREINC2,PCLATU                                                          \\r
359                         else                                                                                                    \\r
360                                 clrf    PCLATU,ACCESS                                                           \\r
361                         endif                                                                                                   \\r
362                         movff   PREINC2,TBLPTRL                                                                 \\r
363                         movff   PREINC2,TBLPTRH                                                                 \\r
364                         if __ROMSIZE > 0x8000                                                                   \\r
365                                 movff   PREINC2,TBLPTRU                                                         \\r
366                         else                                                                                                    \\r
367                                 clrf    TBLPTRU,ACCESS                                                          \\r
368                         endif                                                                                                   \\r
369                         movff   PREINC2,TABLAT                                                                  \\r
370                         movff   PREINC2,FSR1L                                                                   \\r
371                         movff   PREINC2,FSR1H                                                                   \\r
372                         movff   PREINC2,FSR0L                                                                   \\r
373                         movff   PREINC2,FSR0H                                                                   \\r
374                         movff   PREINC2,PRODL                                                                   \\r
375                         movff   PREINC2,PRODH                                                                   \\r
376                         ;                                                                                                               \\r
377                         ; The return from portRESTORE_CONTEXT() depends on              \\r
378                         ; the value of ucCriticalNesting. When it is zero,              \\r
379                         ; interrupts need to be enabled. This is done via a             \\r
380                         ; retfie instruction because we need the                                \\r
381                         ; interrupt-enabling and the return to the restored             \\r
382                         ; task to be uninterruptable.                                                   \\r
383                         ; Because bsr, status and W are affected by the test    \\r
384                         ; they are restored after the test.                                             \\r
385                         ;                                                                                                               \\r
386                         movlb   ucCriticalNesting>>8                                                    \\r
387                         tstfsz  ucCriticalNesting,BANKED                                                \\r
388                         SMARTJUMP _rtos_R4                                                                              \\r
389                 _rtos_R3:                                                                                                       \\r
390                         movff   PREINC2,BSR                                                                             \\r
391                         movff   PREINC2,WREG                                                                    \\r
392                         movff   PREINC2,STATUS                                                                  \\r
393                         retfie  0               ; Return enabling interrupts                    \\r
394                 _rtos_R4:                                                                                                       \\r
395                         movff   PREINC2,BSR                                                                             \\r
396                         movff   PREINC2,WREG                                                                    \\r
397                         movff   PREINC2,STATUS                                                                  \\r
398                         return  0               ; Return without affecting interrupts   \\r
399                         dupmodon                                                                                                \\r
400                 _Pragma("asmend")                                                                                       \\r
401         } while(0)\r
402 \r
403 /*-----------------------------------------------------------*/\r
404 \r
405 #define portTICK_RATE_MS        ( ( portTickType ) 1000 / configTICK_RATE_HZ )          \r
406 \r
407 /*-----------------------------------------------------------*/\r
408 \r
409 extern void vPortYield( void );\r
410 #define portYIELD()                             vPortYield()\r
411 \r
412 #define portNOP()       _Pragma("asm")                                                                  \\r
413                                                 dupmodoff                                                                       \\r
414                                                 nop                                                                                     \\r
415                                                 dupmodon                                                                        \\r
416                                         _Pragma("asmend")\r
417 \r
418 /*-----------------------------------------------------------*/\r
419 \r
420 #define portTASK_FUNCTION( xFunction, pvParameters )            \\r
421         void pointed xFunction( void *pvParameters )            \\r
422         _Pragma(asmfunc xFunction)\r
423 \r
424 #define portTASK_FUNCTION_PROTO         portTASK_FUNCTION\r
425 /*-----------------------------------------------------------*/\r
426 \r
427 #define inline\r
428 #define volatile\r
429 #define register\r
430 \r
431 #endif /* PORTMACRO_H */\r
432 \r