2 FreeRTOS V7.1.1 - Copyright (C) 2012 Real Time Engineers Ltd.
\r
5 ***************************************************************************
\r
7 * FreeRTOS tutorial books are available in pdf and paperback. *
\r
8 * Complete, revised, and edited pdf reference manuals are also *
\r
11 * Purchasing FreeRTOS documentation will not only help you, by *
\r
12 * ensuring you get running as quickly as possible and with an *
\r
13 * in-depth knowledge of how to use FreeRTOS, it will also help *
\r
14 * the FreeRTOS project to continue with its mission of providing *
\r
15 * professional grade, cross platform, de facto standard solutions *
\r
16 * for microcontrollers - completely free of charge! *
\r
18 * >>> See http://www.FreeRTOS.org/Documentation for details. <<< *
\r
20 * Thank you for using FreeRTOS, and thank you for your support! *
\r
22 ***************************************************************************
\r
25 This file is part of the FreeRTOS distribution.
\r
27 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
28 the terms of the GNU General Public License (version 2) as published by the
\r
29 Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
\r
30 >>>NOTE<<< The modification to the GPL is included to allow you to
\r
31 distribute a combined work that includes FreeRTOS without being obliged to
\r
32 provide the source code for proprietary components outside of the FreeRTOS
\r
33 kernel. FreeRTOS is distributed in the hope that it will be useful, but
\r
34 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
\r
35 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
\r
36 more details. You should have received a copy of the GNU General Public
\r
37 License and the FreeRTOS license exception along with FreeRTOS; if not it
\r
38 can be viewed here: http://www.freertos.org/a00114.html and also obtained
\r
39 by writing to Richard Barry, contact details for whom are available on the
\r
44 ***************************************************************************
\r
46 * Having a problem? Start by reading the FAQ "My application does *
\r
47 * not run, what could be wrong? *
\r
49 * http://www.FreeRTOS.org/FAQHelp.html *
\r
51 ***************************************************************************
\r
54 http://www.FreeRTOS.org - Documentation, training, latest information,
\r
55 license and contact details.
\r
57 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
58 including FreeRTOS+Trace - an indispensable productivity tool.
\r
60 Real Time Engineers ltd license FreeRTOS to High Integrity Systems, who sell
\r
61 the code with commercial support, indemnification, and middleware, under
\r
62 the OpenRTOS brand: http://www.OpenRTOS.com. High Integrity Systems also
\r
63 provide a safety engineered and independently SIL3 certified version under
\r
64 the SafeRTOS brand: http://www.SafeRTOS.com.
\r
75 #if !defined(_SERIES) || _SERIES != 18
\r
76 #error "WizC supports FreeRTOS on the Microchip PIC18-series only"
\r
79 #if !defined(QUICKCALL) || QUICKCALL != 1
\r
80 #error "QuickCall must be enabled (see ProjectOptions/Optimisations)"
\r
86 #define portCHAR char
\r
87 #define portFLOAT float
\r
88 #define portDOUBLE portFLOAT
\r
89 #define portLONG long
\r
90 #define portSHORT short
\r
91 #define portSTACK_TYPE unsigned char
\r
92 #define portBASE_TYPE char
\r
94 #if( configUSE_16_BIT_TICKS == 1 )
\r
95 typedef unsigned portSHORT portTickType;
\r
96 #define portMAX_DELAY ( portTickType ) ( 0xFFFF )
\r
98 typedef unsigned portLONG portTickType;
\r
99 #define portMAX_DELAY ( portTickType ) ( 0xFFFFFFFF )
\r
102 #define portBYTE_ALIGNMENT 1
\r
104 /*-----------------------------------------------------------*/
\r
107 * Constant used for context switch macro when we require the interrupt
\r
108 * enable state to be forced when the interrupted task is switched back in.
\r
110 #define portINTERRUPTS_FORCED (0x01)
\r
113 * Constant used for context switch macro when we require the interrupt
\r
114 * enable state to be unchanged when the interrupted task is switched back in.
\r
116 #define portINTERRUPTS_UNCHANGED (0x00)
\r
118 /* Initial interrupt enable state for newly created tasks. This value is
\r
119 * used when a task switches in for the first time.
\r
121 #define portINTERRUPTS_INITIAL_STATE (portINTERRUPTS_FORCED)
\r
124 * Macros to modify the global interrupt enable bit in INTCON.
\r
126 #define portDISABLE_INTERRUPTS() \
\r
130 } while(bGIE) // MicroChip recommends this check!
\r
132 #define portENABLE_INTERRUPTS() \
\r
138 /*-----------------------------------------------------------*/
\r
141 * Critical section macros.
\r
143 extern unsigned portCHAR ucCriticalNesting;
\r
145 #define portNO_CRITICAL_SECTION_NESTING ( ( unsigned portCHAR ) 0 )
\r
147 #define portENTER_CRITICAL() \
\r
150 portDISABLE_INTERRUPTS(); \
\r
153 * Now interrupts are disabled ucCriticalNesting \
\r
154 * can be accessed directly. Increment \
\r
155 * ucCriticalNesting to keep a count of how \
\r
156 * many times portENTER_CRITICAL() has been called. \
\r
158 ucCriticalNesting++; \
\r
161 #define portEXIT_CRITICAL() \
\r
164 if(ucCriticalNesting > portNO_CRITICAL_SECTION_NESTING) \
\r
167 * Decrement the nesting count as we are leaving a \
\r
168 * critical section. \
\r
170 ucCriticalNesting--; \
\r
174 * If the nesting level has reached zero then \
\r
175 * interrupts should be re-enabled. \
\r
177 if( ucCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
\r
179 portENABLE_INTERRUPTS(); \
\r
183 /*-----------------------------------------------------------*/
\r
186 * The minimal stacksize is calculated on the first reference of
\r
187 * portMINIMAL_STACK_SIZE. Some input to this calculation is
\r
188 * compiletime determined, other input is port-defined (see port.c)
\r
190 extern unsigned portSHORT usPortCALCULATE_MINIMAL_STACK_SIZE( void );
\r
191 extern unsigned portSHORT usCalcMinStackSize;
\r
193 #define portMINIMAL_STACK_SIZE \
\r
194 ((usCalcMinStackSize == 0) \
\r
195 ? usPortCALCULATE_MINIMAL_STACK_SIZE() \
\r
196 : usCalcMinStackSize )
\r
199 * WizC uses a downgrowing stack
\r
201 #define portSTACK_GROWTH ( -1 )
\r
203 /*-----------------------------------------------------------*/
\r
206 * Macro's that pushes all the registers that make up the context of a task onto
\r
207 * the stack, then saves the new top of stack into the TCB. TOSU and TBLPTRU
\r
208 * are only saved/restored on devices with more than 64kB (32k Words) ROM.
\r
210 * The stackpointer is helt by WizC in FSR2 and points to the first free byte.
\r
211 * WizC uses a "downgrowing" stack. There is no framepointer.
\r
213 * We keep track of the interruptstatus using ucCriticalNesting. When this
\r
214 * value equals zero, interrupts have to be enabled upon exit from the
\r
215 * portRESTORE_CONTEXT macro.
\r
217 * If this is called from an ISR then the interrupt enable bits must have been
\r
218 * set for the ISR to ever get called. Therefore we want to save
\r
219 * ucCriticalNesting with value zero. This means the interrupts will again be
\r
220 * re-enabled when the interrupted task is switched back in.
\r
222 * If this is called from a manual context switch (i.e. from a call to yield),
\r
223 * then we want to keep the current value of ucCritialNesting so it is restored
\r
224 * with its current value. This allows a yield from within a critical section.
\r
226 * The compiler uses some locations at the bottom of RAM for temporary
\r
227 * storage. The compiler may also have been instructed to optimize
\r
228 * function-parameters and local variables to global storage. The compiler
\r
229 * uses an area called LocOpt for this wizC feature.
\r
230 * The total overheadstorage has to be saved in it's entirety as part of
\r
231 * a task context. These macro's store/restore from data address 0x0000 to
\r
232 * (OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE - 1).
\r
233 * OVERHEADPAGE0, LOCOPTSIZE and MAXLOCOPTSIZE are compiler-generated
\r
234 * assembler definitions.
\r
237 #define portSAVE_CONTEXT( ucInterruptForced ) \
\r
240 portDISABLE_INTERRUPTS(); \
\r
244 ; Push the relevant SFR's onto the task's stack \
\r
246 movff STATUS,POSTDEC2 \
\r
247 movff WREG,POSTDEC2 \
\r
248 movff BSR,POSTDEC2 \
\r
249 movff PRODH,POSTDEC2 \
\r
250 movff PRODL,POSTDEC2 \
\r
251 movff FSR0H,POSTDEC2 \
\r
252 movff FSR0L,POSTDEC2 \
\r
253 movff FSR1H,POSTDEC2 \
\r
254 movff FSR1L,POSTDEC2 \
\r
255 movff TABLAT,POSTDEC2 \
\r
256 if __ROMSIZE > 0x8000 \
\r
257 movff TBLPTRU,POSTDEC2 \
\r
259 movff TBLPTRH,POSTDEC2 \
\r
260 movff TBLPTRL,POSTDEC2 \
\r
261 if __ROMSIZE > 0x8000 \
\r
262 movff PCLATU,POSTDEC2 \
\r
264 movff PCLATH,POSTDEC2 \
\r
266 ; Store the compiler-scratch-area as described above. \
\r
268 movlw OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE \
\r
269 clrf FSR0L,ACCESS \
\r
270 clrf FSR0H,ACCESS \
\r
272 movff POSTINC0,POSTDEC2 \
\r
273 decfsz WREG,W,ACCESS \
\r
274 SMARTJUMP _rtos_S1 \
\r
276 ; Save the pic call/return-stack belonging to the \
\r
277 ; current task by copying it to the task's software- \
\r
278 ; stack. We save the hardware stack pointer (which \
\r
279 ; is the number of addresses on the stack) in the \
\r
280 ; W-register first because we need it later and it \
\r
281 ; is modified in the save-loop by executing pop's. \
\r
282 ; After the loop the W-register is stored on the \
\r
285 movf STKPTR,W,ACCESS \
\r
288 if __ROMSIZE > 0x8000 \
\r
289 movff TOSU,POSTDEC2 \
\r
291 movff TOSH,POSTDEC2 \
\r
292 movff TOSL,POSTDEC2 \
\r
294 tstfsz STKPTR,ACCESS \
\r
295 SMARTJUMP _rtos_S2 \
\r
297 movwf POSTDEC2,ACCESS \
\r
299 ; Next the value for ucCriticalNesting used by the \
\r
300 ; task is stored on the stack. When \
\r
301 ; (ucInterruptForced == portINTERRUPTS_FORCED), we save \
\r
302 ; it as 0 (portNO_CRITICAL_SECTION_NESTING). \
\r
304 if ucInterruptForced == portINTERRUPTS_FORCED \
\r
305 clrf POSTDEC2,ACCESS \
\r
307 movff ucCriticalNesting,POSTDEC2 \
\r
310 ; Save the new top of the software stack in the TCB. \
\r
312 movff pxCurrentTCB,FSR0L \
\r
313 movff pxCurrentTCB+1,FSR0H \
\r
314 movff FSR2L,POSTINC0 \
\r
315 movff FSR2H,POSTINC0 \
\r
316 _Pragma("asmend") \
\r
319 /************************************************************/
\r
322 * This is the reverse of portSAVE_CONTEXT.
\r
324 #define portRESTORE_CONTEXT() \
\r
329 ; Set FSR0 to point to pxCurrentTCB->pxTopOfStack. \
\r
331 movff pxCurrentTCB,FSR0L \
\r
332 movff pxCurrentTCB+1,FSR0H \
\r
334 ; De-reference FSR0 to set the address it holds into \
\r
335 ; FSR2 (i.e. *( pxCurrentTCB->pxTopOfStack ) ). FSR2 \
\r
336 ; is used by wizC as stackpointer. \
\r
338 movff POSTINC0,FSR2L \
\r
339 movff POSTINC0,FSR2H \
\r
341 ; Next, the value for ucCriticalNesting used by the \
\r
342 ; task is retrieved from the stack. \
\r
344 movff PREINC2,ucCriticalNesting \
\r
346 ; Rebuild the pic call/return-stack. The number of \
\r
347 ; return addresses is the next item on the task stack. \
\r
348 ; Save this number in PRODL. Then fetch the addresses \
\r
349 ; and store them on the hardwarestack. \
\r
350 ; The datasheets say we can't use movff here... \
\r
352 movff PREINC2,PRODL // Use PRODL as tempregister \
\r
353 clrf STKPTR,ACCESS \
\r
356 movf PREINC2,W,ACCESS \
\r
357 movwf TOSL,ACCESS \
\r
358 movf PREINC2,W,ACCESS \
\r
359 movwf TOSH,ACCESS \
\r
360 if __ROMSIZE > 0x8000 \
\r
361 movf PREINC2,W,ACCESS \
\r
362 movwf TOSU,ACCESS \
\r
366 decfsz PRODL,F,ACCESS \
\r
367 SMARTJUMP _rtos_R1 \
\r
369 ; Restore the compiler's working storage area to page 0 \
\r
371 movlw OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE \
\r
372 movwf FSR0L,ACCESS \
\r
373 clrf FSR0H,ACCESS \
\r
375 decf FSR0L,F,ACCESS \
\r
376 movff PREINC2,INDF0 \
\r
377 tstfsz FSR0L,ACCESS \
\r
378 SMARTJUMP _rtos_R2 \
\r
380 ; Restore the sfr's forming the tasks context. \
\r
381 ; We cannot yet restore bsr, w and status because \
\r
382 ; we need these registers for a final test. \
\r
384 movff PREINC2,PCLATH \
\r
385 if __ROMSIZE > 0x8000 \
\r
386 movff PREINC2,PCLATU \
\r
388 clrf PCLATU,ACCESS \
\r
390 movff PREINC2,TBLPTRL \
\r
391 movff PREINC2,TBLPTRH \
\r
392 if __ROMSIZE > 0x8000 \
\r
393 movff PREINC2,TBLPTRU \
\r
395 clrf TBLPTRU,ACCESS \
\r
397 movff PREINC2,TABLAT \
\r
398 movff PREINC2,FSR1L \
\r
399 movff PREINC2,FSR1H \
\r
400 movff PREINC2,FSR0L \
\r
401 movff PREINC2,FSR0H \
\r
402 movff PREINC2,PRODL \
\r
403 movff PREINC2,PRODH \
\r
405 ; The return from portRESTORE_CONTEXT() depends on \
\r
406 ; the value of ucCriticalNesting. When it is zero, \
\r
407 ; interrupts need to be enabled. This is done via a \
\r
408 ; retfie instruction because we need the \
\r
409 ; interrupt-enabling and the return to the restored \
\r
410 ; task to be uninterruptable. \
\r
411 ; Because bsr, status and W are affected by the test \
\r
412 ; they are restored after the test. \
\r
414 movlb ucCriticalNesting>>8 \
\r
415 tstfsz ucCriticalNesting,BANKED \
\r
416 SMARTJUMP _rtos_R4 \
\r
418 movff PREINC2,BSR \
\r
419 movff PREINC2,WREG \
\r
420 movff PREINC2,STATUS \
\r
421 retfie 0 ; Return enabling interrupts \
\r
423 movff PREINC2,BSR \
\r
424 movff PREINC2,WREG \
\r
425 movff PREINC2,STATUS \
\r
426 return 0 ; Return without affecting interrupts \
\r
427 _Pragma("asmend") \
\r
430 /*-----------------------------------------------------------*/
\r
432 #define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ )
\r
434 /*-----------------------------------------------------------*/
\r
436 extern void vPortYield( void );
\r
437 #define portYIELD() vPortYield()
\r
439 #define portNOP() _Pragma("asm") \
\r
443 /*-----------------------------------------------------------*/
\r
445 #define portTASK_FUNCTION( xFunction, pvParameters ) \
\r
446 void pointed xFunction( void *pvParameters ) \
\r
447 _Pragma(asmfunc xFunction)
\r
449 #define portTASK_FUNCTION_PROTO portTASK_FUNCTION
\r
450 /*-----------------------------------------------------------*/
\r
456 #endif /* PORTMACRO_H */
\r