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