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