2 * FreeRTOS Kernel V10.0.0
\r
3 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\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
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
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
23 * http://www.FreeRTOS.org
\r
24 * http://aws.amazon.com/freertos
\r
26 * 1 tab == 4 spaces!
\r
37 #if !defined(_SERIES) || _SERIES != 18
\r
38 #error "WizC supports FreeRTOS on the Microchip PIC18-series only"
\r
41 #if !defined(QUICKCALL) || QUICKCALL != 1
\r
42 #error "QuickCall must be enabled (see ProjectOptions/Optimisations)"
\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
56 typedef portSTACK_TYPE StackType_t;
\r
57 typedef signed char BaseType_t;
\r
58 typedef unsigned char UBaseType_t;
\r
61 #if( configUSE_16_BIT_TICKS == 1 )
\r
62 typedef uint16_t TickType_t;
\r
63 #define portMAX_DELAY ( TickType_t ) ( 0xFFFF )
\r
65 typedef uint32_t TickType_t;
\r
66 #define portMAX_DELAY ( TickType_t ) ( 0xFFFFFFFF )
\r
69 #define portBYTE_ALIGNMENT 1
\r
71 /*-----------------------------------------------------------*/
\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
77 #define portINTERRUPTS_FORCED (0x01)
\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
83 #define portINTERRUPTS_UNCHANGED (0x00)
\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
88 #define portINTERRUPTS_INITIAL_STATE (portINTERRUPTS_FORCED)
\r
91 * Macros to modify the global interrupt enable bit in INTCON.
\r
93 #define portDISABLE_INTERRUPTS() \
\r
97 } while(bGIE) // MicroChip recommends this check!
\r
99 #define portENABLE_INTERRUPTS() \
\r
105 /*-----------------------------------------------------------*/
\r
108 * Critical section macros.
\r
110 extern uint8_t ucCriticalNesting;
\r
112 #define portNO_CRITICAL_SECTION_NESTING ( ( uint8_t ) 0 )
\r
114 #define portENTER_CRITICAL() \
\r
117 portDISABLE_INTERRUPTS(); \
\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
125 ucCriticalNesting++; \
\r
128 #define portEXIT_CRITICAL() \
\r
131 if(ucCriticalNesting > portNO_CRITICAL_SECTION_NESTING) \
\r
134 * Decrement the nesting count as we are leaving a \
\r
135 * critical section. \
\r
137 ucCriticalNesting--; \
\r
141 * If the nesting level has reached zero then \
\r
142 * interrupts should be re-enabled. \
\r
144 if( ucCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
\r
146 portENABLE_INTERRUPTS(); \
\r
150 /*-----------------------------------------------------------*/
\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
157 extern uint16_t usPortCALCULATE_MINIMAL_STACK_SIZE( void );
\r
158 extern uint16_t usCalcMinStackSize;
\r
160 #define portMINIMAL_STACK_SIZE \
\r
161 ((usCalcMinStackSize == 0) \
\r
162 ? usPortCALCULATE_MINIMAL_STACK_SIZE() \
\r
163 : usCalcMinStackSize )
\r
166 * WizC uses a downgrowing stack
\r
168 #define portSTACK_GROWTH ( -1 )
\r
170 /*-----------------------------------------------------------*/
\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
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
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
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
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
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
204 #define portSAVE_CONTEXT( ucInterruptForced ) \
\r
207 portDISABLE_INTERRUPTS(); \
\r
211 ; Push the relevant SFR's onto the task's stack \
\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
226 movff TBLPTRH,POSTDEC2 \
\r
227 movff TBLPTRL,POSTDEC2 \
\r
228 if __ROMSIZE > 0x8000 \
\r
229 movff PCLATU,POSTDEC2 \
\r
231 movff PCLATH,POSTDEC2 \
\r
233 ; Store the compiler-scratch-area as described above. \
\r
235 movlw OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE \
\r
236 clrf FSR0L,ACCESS \
\r
237 clrf FSR0H,ACCESS \
\r
239 movff POSTINC0,POSTDEC2 \
\r
240 decfsz WREG,W,ACCESS \
\r
241 SMARTJUMP _rtos_S1 \
\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
252 movf STKPTR,W,ACCESS \
\r
255 if __ROMSIZE > 0x8000 \
\r
256 movff TOSU,POSTDEC2 \
\r
258 movff TOSH,POSTDEC2 \
\r
259 movff TOSL,POSTDEC2 \
\r
261 tstfsz STKPTR,ACCESS \
\r
262 SMARTJUMP _rtos_S2 \
\r
264 movwf POSTDEC2,ACCESS \
\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
271 if ucInterruptForced == portINTERRUPTS_FORCED \
\r
272 clrf POSTDEC2,ACCESS \
\r
274 movff ucCriticalNesting,POSTDEC2 \
\r
277 ; Save the new top of the software stack in the TCB. \
\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
286 /************************************************************/
\r
289 * This is the reverse of portSAVE_CONTEXT.
\r
291 #define portRESTORE_CONTEXT() \
\r
296 ; Set FSR0 to point to pxCurrentTCB->pxTopOfStack. \
\r
298 movff pxCurrentTCB,FSR0L \
\r
299 movff pxCurrentTCB+1,FSR0H \
\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
305 movff POSTINC0,FSR2L \
\r
306 movff POSTINC0,FSR2H \
\r
308 ; Next, the value for ucCriticalNesting used by the \
\r
309 ; task is retrieved from the stack. \
\r
311 movff PREINC2,ucCriticalNesting \
\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
319 movff PREINC2,PRODL // Use PRODL as tempregister \
\r
320 clrf STKPTR,ACCESS \
\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
333 decfsz PRODL,F,ACCESS \
\r
334 SMARTJUMP _rtos_R1 \
\r
336 ; Restore the compiler's working storage area to page 0 \
\r
338 movlw OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE \
\r
339 movwf FSR0L,ACCESS \
\r
340 clrf FSR0H,ACCESS \
\r
342 decf FSR0L,F,ACCESS \
\r
343 movff PREINC2,INDF0 \
\r
344 tstfsz FSR0L,ACCESS \
\r
345 SMARTJUMP _rtos_R2 \
\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
351 movff PREINC2,PCLATH \
\r
352 if __ROMSIZE > 0x8000 \
\r
353 movff PREINC2,PCLATU \
\r
355 clrf PCLATU,ACCESS \
\r
357 movff PREINC2,TBLPTRL \
\r
358 movff PREINC2,TBLPTRH \
\r
359 if __ROMSIZE > 0x8000 \
\r
360 movff PREINC2,TBLPTRU \
\r
362 clrf TBLPTRU,ACCESS \
\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
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
381 movlb ucCriticalNesting>>8 \
\r
382 tstfsz ucCriticalNesting,BANKED \
\r
383 SMARTJUMP _rtos_R4 \
\r
385 movff PREINC2,BSR \
\r
386 movff PREINC2,WREG \
\r
387 movff PREINC2,STATUS \
\r
388 retfie 0 ; Return enabling interrupts \
\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
397 /*-----------------------------------------------------------*/
\r
399 #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
\r
401 /*-----------------------------------------------------------*/
\r
403 extern void vPortYield( void );
\r
404 #define portYIELD() vPortYield()
\r
406 #define portNOP() _Pragma("asm") \
\r
410 /*-----------------------------------------------------------*/
\r
412 #define portTASK_FUNCTION( xFunction, pvParameters ) \
\r
413 void pointed xFunction( void *pvParameters ) \
\r
414 _Pragma(asmfunc xFunction)
\r
416 #define portTASK_FUNCTION_PROTO portTASK_FUNCTION
\r
417 /*-----------------------------------------------------------*/
\r
423 #endif /* PORTMACRO_H */
\r