2 * FreeRTOS SMP Kernel V202110.00
3 * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
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:
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
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.
22 * https://www.FreeRTOS.org
23 * https://github.com/FreeRTOS
36 #if !defined(_SERIES) || _SERIES != 18
37 #error "WizC supports FreeRTOS on the Microchip PIC18-series only"
40 #if !defined(QUICKCALL) || QUICKCALL != 1
41 #error "QuickCall must be enabled (see ProjectOptions/Optimisations)"
48 #define portFLOAT float
49 #define portDOUBLE portFLOAT
51 #define portSHORT short
52 #define portSTACK_TYPE uint8_t
53 #define portBASE_TYPE char
55 typedef portSTACK_TYPE StackType_t;
56 typedef signed char BaseType_t;
57 typedef unsigned char UBaseType_t;
60 #if( configUSE_16_BIT_TICKS == 1 )
61 typedef uint16_t TickType_t;
62 #define portMAX_DELAY ( TickType_t ) ( 0xFFFF )
64 typedef uint32_t TickType_t;
65 #define portMAX_DELAY ( TickType_t ) ( 0xFFFFFFFF )
68 #define portBYTE_ALIGNMENT 1
70 /*-----------------------------------------------------------*/
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.
76 #define portINTERRUPTS_FORCED (0x01)
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.
82 #define portINTERRUPTS_UNCHANGED (0x00)
84 /* Initial interrupt enable state for newly created tasks. This value is
85 * used when a task switches in for the first time.
87 #define portINTERRUPTS_INITIAL_STATE (portINTERRUPTS_FORCED)
90 * Macros to modify the global interrupt enable bit in INTCON.
92 #define portDISABLE_INTERRUPTS() \
96 } while(bGIE) // MicroChip recommends this check!
98 #define portENABLE_INTERRUPTS() \
104 /*-----------------------------------------------------------*/
107 * Critical section macros.
109 extern uint8_t ucCriticalNesting;
111 #define portNO_CRITICAL_SECTION_NESTING ( ( uint8_t ) 0 )
113 #define portENTER_CRITICAL() \
116 portDISABLE_INTERRUPTS(); \
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. \
124 ucCriticalNesting++; \
127 #define portEXIT_CRITICAL() \
130 if(ucCriticalNesting > portNO_CRITICAL_SECTION_NESTING) \
133 * Decrement the nesting count as we are leaving a \
134 * critical section. \
136 ucCriticalNesting--; \
140 * If the nesting level has reached zero then \
141 * interrupts should be re-enabled. \
143 if( ucCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
145 portENABLE_INTERRUPTS(); \
149 /*-----------------------------------------------------------*/
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)
156 extern uint16_t usPortCALCULATE_MINIMAL_STACK_SIZE( void );
157 extern uint16_t usCalcMinStackSize;
159 #define portMINIMAL_STACK_SIZE \
160 ((usCalcMinStackSize == 0) \
161 ? usPortCALCULATE_MINIMAL_STACK_SIZE() \
162 : usCalcMinStackSize )
165 * WizC uses a downgrowing stack
167 #define portSTACK_GROWTH ( -1 )
169 /*-----------------------------------------------------------*/
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.
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.
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.
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.
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.
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.
203 #define portSAVE_CONTEXT( ucInterruptForced ) \
206 portDISABLE_INTERRUPTS(); \
210 ; Push the relevant SFR's onto the task's stack \
212 movff STATUS,POSTDEC2 \
213 movff WREG,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 \
225 movff TBLPTRH,POSTDEC2 \
226 movff TBLPTRL,POSTDEC2 \
227 if __ROMSIZE > 0x8000 \
228 movff PCLATU,POSTDEC2 \
230 movff PCLATH,POSTDEC2 \
232 ; Store the compiler-scratch-area as described above. \
234 movlw OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE \
238 movff POSTINC0,POSTDEC2 \
239 decfsz WREG,W,ACCESS \
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 \
251 movf STKPTR,W,ACCESS \
254 if __ROMSIZE > 0x8000 \
255 movff TOSU,POSTDEC2 \
257 movff TOSH,POSTDEC2 \
258 movff TOSL,POSTDEC2 \
260 tstfsz STKPTR,ACCESS \
263 movwf POSTDEC2,ACCESS \
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). \
270 if ucInterruptForced == portINTERRUPTS_FORCED \
271 clrf POSTDEC2,ACCESS \
273 movff ucCriticalNesting,POSTDEC2 \
276 ; Save the new top of the software stack in the TCB. \
278 movff pxCurrentTCB,FSR0L \
279 movff pxCurrentTCB+1,FSR0H \
280 movff FSR2L,POSTINC0 \
281 movff FSR2H,POSTINC0 \
285 /************************************************************/
288 * This is the reverse of portSAVE_CONTEXT.
290 #define portRESTORE_CONTEXT() \
295 ; Set FSR0 to point to pxCurrentTCB->pxTopOfStack. \
297 movff pxCurrentTCB,FSR0L \
298 movff pxCurrentTCB+1,FSR0H \
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. \
304 movff POSTINC0,FSR2L \
305 movff POSTINC0,FSR2H \
307 ; Next, the value for ucCriticalNesting used by the \
308 ; task is retrieved from the stack. \
310 movff PREINC2,ucCriticalNesting \
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... \
318 movff PREINC2,PRODL // Use PRODL as tempregister \
322 movf PREINC2,W,ACCESS \
324 movf PREINC2,W,ACCESS \
326 if __ROMSIZE > 0x8000 \
327 movf PREINC2,W,ACCESS \
332 decfsz PRODL,F,ACCESS \
335 ; Restore the compiler's working storage area to page 0 \
337 movlw OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE \
341 decf FSR0L,F,ACCESS \
342 movff PREINC2,INDF0 \
343 tstfsz FSR0L,ACCESS \
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. \
350 movff PREINC2,PCLATH \
351 if __ROMSIZE > 0x8000 \
352 movff PREINC2,PCLATU \
356 movff PREINC2,TBLPTRL \
357 movff PREINC2,TBLPTRH \
358 if __ROMSIZE > 0x8000 \
359 movff PREINC2,TBLPTRU \
361 clrf TBLPTRU,ACCESS \
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 \
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. \
380 movlb ucCriticalNesting>>8 \
381 tstfsz ucCriticalNesting,BANKED \
386 movff PREINC2,STATUS \
387 retfie 0 ; Return enabling interrupts \
391 movff PREINC2,STATUS \
392 return 0 ; Return without affecting interrupts \
396 /*-----------------------------------------------------------*/
398 #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
400 /*-----------------------------------------------------------*/
402 extern void vPortYield( void );
403 #define portYIELD() vPortYield()
405 #define portNOP() _Pragma("asm") \
409 /*-----------------------------------------------------------*/
411 #define portTASK_FUNCTION( xFunction, pvParameters ) \
412 void pointed xFunction( void *pvParameters ) \
413 _Pragma(asmfunc xFunction)
415 #define portTASK_FUNCTION_PROTO portTASK_FUNCTION
416 /*-----------------------------------------------------------*/
422 #endif /* PORTMACRO_H */