]> git.sur5r.net Git - freertos/blob - FreeRTOS/Source/portable/WizC/PIC18/portmacro.h
d5cc8502d7cf870e0662645ef265bc0f4191c191
[freertos] / FreeRTOS / Source / portable / WizC / PIC18 / portmacro.h
1 /*\r
2     FreeRTOS V7.5.0 - Copyright (C) 2013 Real Time Engineers Ltd.\r
3 \r
4     VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.\r
5 \r
6     ***************************************************************************\r
7      *                                                                       *\r
8      *    FreeRTOS provides completely free yet professionally developed,    *\r
9      *    robust, strictly quality controlled, supported, and cross          *\r
10      *    platform software that has become a de facto standard.             *\r
11      *                                                                       *\r
12      *    Help yourself get started quickly and support the FreeRTOS         *\r
13      *    project by purchasing a FreeRTOS tutorial book, reference          *\r
14      *    manual, or both from: http://www.FreeRTOS.org/Documentation        *\r
15      *                                                                       *\r
16      *    Thank you!                                                         *\r
17      *                                                                       *\r
18     ***************************************************************************\r
19 \r
20     This file is part of the FreeRTOS distribution.\r
21 \r
22     FreeRTOS is free software; you can redistribute it and/or modify it under\r
23     the terms of the GNU General Public License (version 2) as published by the\r
24     Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.\r
25 \r
26     >>! NOTE: The modification to the GPL is included to allow you to distribute\r
27     >>! a combined work that includes FreeRTOS without being obliged to provide\r
28     >>! the source code for proprietary components outside of the FreeRTOS\r
29     >>! kernel.\r
30 \r
31     FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY\r
32     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS\r
33     FOR A PARTICULAR PURPOSE.  Full license text is available from the following\r
34     link: http://www.freertos.org/a00114.html\r
35 \r
36     1 tab == 4 spaces!\r
37 \r
38     ***************************************************************************\r
39      *                                                                       *\r
40      *    Having a problem?  Start by reading the FAQ "My application does   *\r
41      *    not run, what could be wrong?"                                     *\r
42      *                                                                       *\r
43      *    http://www.FreeRTOS.org/FAQHelp.html                               *\r
44      *                                                                       *\r
45     ***************************************************************************\r
46 \r
47     http://www.FreeRTOS.org - Documentation, books, training, latest versions,\r
48     license and Real Time Engineers Ltd. contact details.\r
49 \r
50     http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,\r
51     including FreeRTOS+Trace - an indispensable productivity tool, a DOS\r
52     compatible FAT file system, and our tiny thread aware UDP/IP stack.\r
53 \r
54     http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High\r
55     Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS\r
56     licenses offer ticketed support, indemnification and middleware.\r
57 \r
58     http://www.SafeRTOS.com - High Integrity Systems also provide a safety\r
59     engineered and independently SIL3 certified version for use in safety and\r
60     mission critical applications that require provable dependability.\r
61 \r
62     1 tab == 4 spaces!\r
63 */\r
64 \r
65 /* \r
66 Changes from V3.0.0\r
67 \r
68 Changes from V3.0.1\r
69 */\r
70 #ifndef PORTMACRO_H\r
71 #define PORTMACRO_H\r
72 \r
73 #if !defined(_SERIES) || _SERIES != 18\r
74         #error "WizC supports FreeRTOS on the Microchip PIC18-series only"\r
75 #endif\r
76 \r
77 #if !defined(QUICKCALL) || QUICKCALL != 1\r
78         #error "QuickCall must be enabled (see ProjectOptions/Optimisations)"\r
79 #endif\r
80 \r
81 #include <stddef.h>\r
82 #include <pic.h>\r
83 \r
84 #define portCHAR                char\r
85 #define portFLOAT               float\r
86 #define portDOUBLE              portFLOAT\r
87 #define portLONG                long\r
88 #define portSHORT               short\r
89 #define portSTACK_TYPE  unsigned char\r
90 #define portBASE_TYPE   char\r
91 \r
92 #if( configUSE_16_BIT_TICKS == 1 )\r
93         typedef unsigned portSHORT portTickType;\r
94         #define portMAX_DELAY ( portTickType )  ( 0xFFFF )\r
95 #else\r
96         typedef unsigned portLONG portTickType;\r
97         #define portMAX_DELAY ( portTickType )  ( 0xFFFFFFFF )\r
98 #endif\r
99 \r
100 #define portBYTE_ALIGNMENT                      1\r
101 \r
102 /*-----------------------------------------------------------*/\r
103 \r
104 /*\r
105  * Constant used for context switch macro when we require the interrupt \r
106  * enable state to be forced when the interrupted task is switched back in.\r
107  */\r
108 #define portINTERRUPTS_FORCED                           (0x01)\r
109 \r
110 /*\r
111  * Constant used for context switch macro when we require the interrupt \r
112  * enable state to be unchanged when the interrupted task is switched back in.\r
113  */\r
114 #define portINTERRUPTS_UNCHANGED                        (0x00)\r
115 \r
116 /* Initial interrupt enable state for newly created tasks.  This value is\r
117  * used when a task switches in for the first time.\r
118  */\r
119 #define portINTERRUPTS_INITIAL_STATE            (portINTERRUPTS_FORCED)\r
120 \r
121 /*\r
122  * Macros to modify the global interrupt enable bit in INTCON.\r
123  */\r
124 #define portDISABLE_INTERRUPTS()        \\r
125         do                                                              \\r
126         {                                                               \\r
127                 bGIE=0;                                         \\r
128         } while(bGIE)   // MicroChip recommends this check!\r
129         \r
130 #define portENABLE_INTERRUPTS()         \\r
131         do                                                              \\r
132         {                                                               \\r
133                 bGIE=1;                                         \\r
134         } while(0)\r
135 \r
136 /*-----------------------------------------------------------*/ \r
137 \r
138 /*\r
139  * Critical section macros.\r
140  */\r
141 extern unsigned portCHAR ucCriticalNesting;\r
142 \r
143 #define portNO_CRITICAL_SECTION_NESTING         ( ( unsigned portCHAR ) 0 )\r
144 \r
145 #define portENTER_CRITICAL()                                                                            \\r
146         do                                                                                                                              \\r
147         {                                                                                                                               \\r
148                 portDISABLE_INTERRUPTS();                                                                       \\r
149                                                                                                                                         \\r
150                 /*                                                                                                                      \\r
151                  * Now interrupts are disabled ucCriticalNesting                        \\r
152                  * can be accessed directly. Increment                                          \\r
153                  * ucCriticalNesting to keep a count of how                                     \\r
154                  * many times portENTER_CRITICAL() has been called.             \\r
155                  */                                                                                                                     \\r
156                 ucCriticalNesting++;                                                                            \\r
157         } while(0)\r
158 \r
159 #define portEXIT_CRITICAL()                                                                                     \\r
160         do                                                                                                                              \\r
161         {                                                                                                                               \\r
162                 if(ucCriticalNesting > portNO_CRITICAL_SECTION_NESTING)         \\r
163                 {                                                                                                                       \\r
164                         /*                                                                                                              \\r
165                          * Decrement the nesting count as we are leaving a              \\r
166                          * critical section.                                                                    \\r
167                          */                                                                                                             \\r
168                         ucCriticalNesting--;                                                                    \\r
169                 }                                                                                                                       \\r
170                                                                                                                                         \\r
171                 /*                                                                                                                      \\r
172                  * If the nesting level has reached zero then                           \\r
173                  * interrupts should be re-enabled.                                                     \\r
174                  */                                                                                                                     \\r
175                 if( ucCriticalNesting == portNO_CRITICAL_SECTION_NESTING )      \\r
176                 {                                                                                                                       \\r
177                         portENABLE_INTERRUPTS();                                                                \\r
178                 }                                                                                                                       \\r
179         } while(0)\r
180 \r
181 /*-----------------------------------------------------------*/\r
182 \r
183 /*\r
184  * The minimal stacksize is calculated on the first reference of\r
185  * portMINIMAL_STACK_SIZE. Some input to this calculation is\r
186  * compiletime determined, other input is port-defined (see port.c)\r
187  */\r
188 extern unsigned portSHORT usPortCALCULATE_MINIMAL_STACK_SIZE( void );\r
189 extern unsigned portSHORT usCalcMinStackSize;\r
190 \r
191 #define portMINIMAL_STACK_SIZE                                  \\r
192         ((usCalcMinStackSize == 0)                                      \\r
193                 ? usPortCALCULATE_MINIMAL_STACK_SIZE()  \\r
194                 : usCalcMinStackSize )\r
195 \r
196 /*\r
197  * WizC uses a downgrowing stack\r
198  */\r
199 #define portSTACK_GROWTH                        ( -1 )\r
200 \r
201 /*-----------------------------------------------------------*/\r
202 \r
203 /*\r
204  * Macro's that pushes all the registers that make up the context of a task onto\r
205  * the stack, then saves the new top of stack into the TCB. TOSU and TBLPTRU\r
206  * are only saved/restored on devices with more than 64kB (32k Words) ROM.\r
207  * \r
208  * The stackpointer is helt by WizC in FSR2 and points to the first free byte.\r
209  * WizC uses a "downgrowing" stack. There is no framepointer.\r
210  *\r
211  * We keep track of the interruptstatus using ucCriticalNesting. When this\r
212  * value equals zero, interrupts have to be enabled upon exit from the\r
213  * portRESTORE_CONTEXT macro.\r
214  * \r
215  * If this is called from an ISR then the interrupt enable bits must have been \r
216  * set for the ISR to ever get called.  Therefore we want to save\r
217  * ucCriticalNesting with value zero. This means the interrupts will again be\r
218  * re-enabled when the interrupted task is switched back in.\r
219  *\r
220  * If this is called from a manual context switch (i.e. from a call to yield),\r
221  * then we want to keep the current value of ucCritialNesting so it is restored\r
222  * with its current value. This allows a yield from within a critical section.\r
223  *\r
224  * The compiler uses some locations at the bottom of RAM for temporary\r
225  * storage. The compiler may also have been instructed to optimize\r
226  * function-parameters and local variables to global storage. The compiler\r
227  * uses an area called LocOpt for this wizC feature.\r
228  * The total overheadstorage has to be saved in it's entirety as part of\r
229  * a task context. These macro's store/restore from data address 0x0000 to\r
230  * (OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE - 1).\r
231  * OVERHEADPAGE0, LOCOPTSIZE and MAXLOCOPTSIZE are compiler-generated\r
232  * assembler definitions.\r
233  */\r
234 \r
235 #define portSAVE_CONTEXT( ucInterruptForced )                                           \\r
236         do                                                                                                                              \\r
237         {                                                                                                                               \\r
238                 portDISABLE_INTERRUPTS();                                                                       \\r
239                                                                                                                                         \\r
240                 _Pragma("asm")                                                                                          \\r
241                         ;                                                                                                               \\r
242                         ; Push the relevant SFR's onto the task's stack                 \\r
243                         ;                                                                                                               \\r
244                         movff   STATUS,POSTDEC2                                                                 \\r
245                         movff   WREG,POSTDEC2                                                                   \\r
246                         movff   BSR,POSTDEC2                                                                    \\r
247                         movff   PRODH,POSTDEC2                                                                  \\r
248                         movff   PRODL,POSTDEC2                                                                  \\r
249                         movff   FSR0H,POSTDEC2                                                                  \\r
250                         movff   FSR0L,POSTDEC2                                                                  \\r
251                         movff   FSR1H,POSTDEC2                                                                  \\r
252                         movff   FSR1L,POSTDEC2                                                                  \\r
253                         movff   TABLAT,POSTDEC2                                                                 \\r
254                         if __ROMSIZE > 0x8000                                                                   \\r
255                                 movff   TBLPTRU,POSTDEC2                                                        \\r
256                         endif                                                                                                   \\r
257                         movff   TBLPTRH,POSTDEC2                                                                \\r
258                         movff   TBLPTRL,POSTDEC2                                                                \\r
259                         if __ROMSIZE > 0x8000                                                                   \\r
260                                 movff   PCLATU,POSTDEC2                                                         \\r
261                         endif                                                                                                   \\r
262                         movff   PCLATH,POSTDEC2                                                                 \\r
263                         ;                                                                                                               \\r
264                         ; Store the compiler-scratch-area as described above.   \\r
265                         ;                                                                                                               \\r
266                         movlw   OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE                  \\r
267                         clrf    FSR0L,ACCESS                                                                    \\r
268                         clrf    FSR0H,ACCESS                                                                    \\r
269                 _rtos_S1:                                                                                                       \\r
270                         movff   POSTINC0,POSTDEC2                                                               \\r
271                         decfsz  WREG,W,ACCESS                                                                   \\r
272                         SMARTJUMP _rtos_S1                                                                              \\r
273                         ;                                                                                                               \\r
274                         ; Save the pic call/return-stack belonging to the               \\r
275                         ; current task by copying it to the task's software-    \\r
276                         ; stack. We save the hardware stack pointer (which              \\r
277                         ; is the number of addresses on the stack) in the               \\r
278                         ; W-register first because we need it later and it              \\r
279                         ; is modified in the save-loop by executing pop's.              \\r
280                         ; After the loop the W-register is stored on the                \\r
281                         ; stack, too.                                                                                   \\r
282                         ;                                                                                                               \\r
283                         movf    STKPTR,W,ACCESS                                                                 \\r
284                         bz              _rtos_s3                                                                                \\r
285                 _rtos_S2:                                                                                                       \\r
286                         if __ROMSIZE > 0x8000                                                                   \\r
287                                 movff   TOSU,POSTDEC2                                                           \\r
288                         endif                                                                                                   \\r
289                         movff   TOSH,POSTDEC2                                                                   \\r
290                         movff   TOSL,POSTDEC2                                                                   \\r
291                         pop                                                                                                             \\r
292                         tstfsz  STKPTR,ACCESS                                                                   \\r
293                         SMARTJUMP _rtos_S2                                                                              \\r
294                 _rtos_s3:                                                                                                       \\r
295                         movwf   POSTDEC2,ACCESS                                                                 \\r
296                         ;                                                                                                               \\r
297                         ; Next the value for ucCriticalNesting used by the              \\r
298                         ; task is stored on the stack. When                                             \\r
299                         ; (ucInterruptForced == portINTERRUPTS_FORCED), we save \\r
300                         ; it as 0 (portNO_CRITICAL_SECTION_NESTING).                    \\r
301                         ;                                                                                                               \\r
302                         if ucInterruptForced == portINTERRUPTS_FORCED                   \\r
303                                 clrf POSTDEC2,ACCESS                                                            \\r
304                         else                                                                                                    \\r
305                                 movff   ucCriticalNesting,POSTDEC2                                      \\r
306                         endif                                                                                                   \\r
307                         ;                                                                                                               \\r
308                         ; Save the new top of the software stack in the TCB.    \\r
309                         ;                                                                                                               \\r
310                         movff   pxCurrentTCB,FSR0L                                                              \\r
311                         movff   pxCurrentTCB+1,FSR0H                                                    \\r
312                         movff   FSR2L,POSTINC0                                                                  \\r
313                         movff   FSR2H,POSTINC0                                                                  \\r
314                 _Pragma("asmend")                                                                                       \\r
315         } while(0)\r
316 \r
317 /************************************************************/\r
318 \r
319 /*\r
320  * This is the reverse of portSAVE_CONTEXT.\r
321  */\r
322 #define portRESTORE_CONTEXT()                                                                           \\r
323         do                                                                                                                              \\r
324         {                                                                                                                               \\r
325                 _Pragma("asm")                                                                                          \\r
326                         ;                                                                                                               \\r
327                         ; Set FSR0 to point to pxCurrentTCB->pxTopOfStack.              \\r
328                         ;                                                                                                               \\r
329                         movff   pxCurrentTCB,FSR0L                                                              \\r
330                         movff   pxCurrentTCB+1,FSR0H                                                    \\r
331                         ;                                                                                                               \\r
332                         ; De-reference FSR0 to set the address it holds into    \\r
333                         ; FSR2 (i.e. *( pxCurrentTCB->pxTopOfStack ) ). FSR2    \\r
334                         ; is used by wizC as stackpointer.                                              \\r
335                         ;                                                                                                               \\r
336                         movff   POSTINC0,FSR2L                                                                  \\r
337                         movff   POSTINC0,FSR2H                                                                  \\r
338                         ;                                                                                                               \\r
339                         ; Next, the value for ucCriticalNesting used by the             \\r
340                         ; task is retrieved from the stack.                                             \\r
341                         ;                                                                                                               \\r
342                         movff   PREINC2,ucCriticalNesting                                               \\r
343                         ;                                                                                                               \\r
344                         ; Rebuild the pic call/return-stack. The number of              \\r
345                         ; return addresses is the next item on the task stack.  \\r
346                         ; Save this number in PRODL. Then fetch the addresses   \\r
347                         ; and store them on the hardwarestack.                                  \\r
348                         ; The datasheets say we can't use movff here...                 \\r
349                         ;                                                                                                               \\r
350                         movff   PREINC2,PRODL   // Use PRODL as tempregister    \\r
351                         clrf    STKPTR,ACCESS                                                                   \\r
352                 _rtos_R1:                                                                                                       \\r
353                         push                                                                                                    \\r
354                         movf    PREINC2,W,ACCESS                                                                \\r
355                         movwf   TOSL,ACCESS                                                                             \\r
356                         movf    PREINC2,W,ACCESS                                                                \\r
357                         movwf   TOSH,ACCESS                                                                             \\r
358                         if __ROMSIZE > 0x8000                                                                   \\r
359                                 movf    PREINC2,W,ACCESS                                                        \\r
360                                 movwf   TOSU,ACCESS                                                                     \\r
361                         else                                                                                                    \\r
362                                 clrf    TOSU,ACCESS                                                                     \\r
363                         endif                                                                                                   \\r
364                         decfsz  PRODL,F,ACCESS                                                                  \\r
365                         SMARTJUMP _rtos_R1                                                                              \\r
366                         ;                                                                                                               \\r
367                         ; Restore the compiler's working storage area to page 0 \\r
368                         ;                                                                                                               \\r
369                         movlw   OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE                  \\r
370                         movwf   FSR0L,ACCESS                                                                    \\r
371                         clrf    FSR0H,ACCESS                                                                    \\r
372                 _rtos_R2:                                                                                                       \\r
373                         decf    FSR0L,F,ACCESS                                                                  \\r
374                         movff   PREINC2,INDF0                                                                   \\r
375                         tstfsz  FSR0L,ACCESS                                                                    \\r
376                         SMARTJUMP _rtos_R2                                                                              \\r
377                         ;                                                                                                               \\r
378                         ; Restore the sfr's forming the tasks context.                  \\r
379                         ; We cannot yet restore bsr, w and status because               \\r
380                         ; we need these registers for a final test.                             \\r
381                         ;                                                                                                               \\r
382                         movff   PREINC2,PCLATH                                                                  \\r
383                         if __ROMSIZE > 0x8000                                                                   \\r
384                                 movff   PREINC2,PCLATU                                                          \\r
385                         else                                                                                                    \\r
386                                 clrf    PCLATU,ACCESS                                                           \\r
387                         endif                                                                                                   \\r
388                         movff   PREINC2,TBLPTRL                                                                 \\r
389                         movff   PREINC2,TBLPTRH                                                                 \\r
390                         if __ROMSIZE > 0x8000                                                                   \\r
391                                 movff   PREINC2,TBLPTRU                                                         \\r
392                         else                                                                                                    \\r
393                                 clrf    TBLPTRU,ACCESS                                                          \\r
394                         endif                                                                                                   \\r
395                         movff   PREINC2,TABLAT                                                                  \\r
396                         movff   PREINC2,FSR1L                                                                   \\r
397                         movff   PREINC2,FSR1H                                                                   \\r
398                         movff   PREINC2,FSR0L                                                                   \\r
399                         movff   PREINC2,FSR0H                                                                   \\r
400                         movff   PREINC2,PRODL                                                                   \\r
401                         movff   PREINC2,PRODH                                                                   \\r
402                         ;                                                                                                               \\r
403                         ; The return from portRESTORE_CONTEXT() depends on              \\r
404                         ; the value of ucCriticalNesting. When it is zero,              \\r
405                         ; interrupts need to be enabled. This is done via a             \\r
406                         ; retfie instruction because we need the                                \\r
407                         ; interrupt-enabling and the return to the restored             \\r
408                         ; task to be uninterruptable.                                                   \\r
409                         ; Because bsr, status and W are affected by the test    \\r
410                         ; they are restored after the test.                                             \\r
411                         ;                                                                                                               \\r
412                         movlb   ucCriticalNesting>>8                                                    \\r
413                         tstfsz  ucCriticalNesting,BANKED                                                \\r
414                         SMARTJUMP _rtos_R4                                                                              \\r
415                 _rtos_R3:                                                                                                       \\r
416                         movff   PREINC2,BSR                                                                             \\r
417                         movff   PREINC2,WREG                                                                    \\r
418                         movff   PREINC2,STATUS                                                                  \\r
419                         retfie  0               ; Return enabling interrupts                    \\r
420                 _rtos_R4:                                                                                                       \\r
421                         movff   PREINC2,BSR                                                                             \\r
422                         movff   PREINC2,WREG                                                                    \\r
423                         movff   PREINC2,STATUS                                                                  \\r
424                         return  0               ; Return without affecting interrupts   \\r
425                 _Pragma("asmend")                                                                                       \\r
426         } while(0)\r
427 \r
428 /*-----------------------------------------------------------*/\r
429 \r
430 #define portTICK_RATE_MS        ( ( portTickType ) 1000 / configTICK_RATE_HZ )          \r
431 \r
432 /*-----------------------------------------------------------*/\r
433 \r
434 extern void vPortYield( void );\r
435 #define portYIELD()                             vPortYield()\r
436 \r
437 #define portNOP()       _Pragma("asm")                                                                  \\r
438                                                 nop                                                                                     \\r
439                                         _Pragma("asmend")\r
440 \r
441 /*-----------------------------------------------------------*/\r
442 \r
443 #define portTASK_FUNCTION( xFunction, pvParameters )            \\r
444         void pointed xFunction( void *pvParameters )            \\r
445         _Pragma(asmfunc xFunction)\r
446 \r
447 #define portTASK_FUNCTION_PROTO         portTASK_FUNCTION\r
448 /*-----------------------------------------------------------*/\r
449 \r
450 \r
451 #define volatile\r
452 #define register\r
453 \r
454 #endif /* PORTMACRO_H */\r
455 \r