2 FreeRTOS V8.1.1 - Copyright (C) 2014 Real Time Engineers Ltd.
\r
5 VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
\r
7 ***************************************************************************
\r
9 * FreeRTOS provides completely free yet professionally developed, *
\r
10 * robust, strictly quality controlled, supported, and cross *
\r
11 * platform software that has become a de facto standard. *
\r
13 * Help yourself get started quickly and support the FreeRTOS *
\r
14 * project by purchasing a FreeRTOS tutorial book, reference *
\r
15 * manual, or both from: http://www.FreeRTOS.org/Documentation *
\r
19 ***************************************************************************
\r
21 This file is part of the FreeRTOS distribution.
\r
23 FreeRTOS is free software; you can redistribute it and/or modify it under
\r
24 the terms of the GNU General Public License (version 2) as published by the
\r
25 Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
\r
27 >>! NOTE: The modification to the GPL is included to allow you to !<<
\r
28 >>! distribute a combined work that includes FreeRTOS without being !<<
\r
29 >>! obliged to provide the source code for proprietary components !<<
\r
30 >>! outside of the FreeRTOS kernel. !<<
\r
32 FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
\r
33 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
\r
34 FOR A PARTICULAR PURPOSE. Full license text is available from the following
\r
35 link: http://www.freertos.org/a00114.html
\r
39 ***************************************************************************
\r
41 * Having a problem? Start by reading the FAQ "My application does *
\r
42 * not run, what could be wrong?" *
\r
44 * http://www.FreeRTOS.org/FAQHelp.html *
\r
46 ***************************************************************************
\r
48 http://www.FreeRTOS.org - Documentation, books, training, latest versions,
\r
49 license and Real Time Engineers Ltd. contact details.
\r
51 http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
\r
52 including FreeRTOS+Trace - an indispensable productivity tool, a DOS
\r
53 compatible FAT file system, and our tiny thread aware UDP/IP stack.
\r
55 http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
\r
56 Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS
\r
57 licenses offer ticketed support, indemnification and middleware.
\r
59 http://www.SafeRTOS.com - High Integrity Systems also provide a safety
\r
60 engineered and independently SIL3 certified version for use in safety and
\r
61 mission critical applications that require provable dependability.
\r
74 #if !defined(_SERIES) || _SERIES != 18
\r
75 #error "WizC supports FreeRTOS on the Microchip PIC18-series only"
\r
78 #if !defined(QUICKCALL) || QUICKCALL != 1
\r
79 #error "QuickCall must be enabled (see ProjectOptions/Optimisations)"
\r
85 #define portCHAR char
\r
86 #define portFLOAT float
\r
87 #define portDOUBLE portFLOAT
\r
88 #define portLONG long
\r
89 #define portSHORT short
\r
90 #define portSTACK_TYPE uint8_t
\r
91 #define portBASE_TYPE char
\r
93 typedef portSTACK_TYPE StackType_t;
\r
94 typedef signed char BaseType_t;
\r
95 typedef unsigned char UBaseType_t;
\r
98 #if( configUSE_16_BIT_TICKS == 1 )
\r
99 typedef uint16_t TickType_t;
\r
100 #define portMAX_DELAY ( TickType_t ) ( 0xFFFF )
\r
102 typedef uint32_t TickType_t;
\r
103 #define portMAX_DELAY ( TickType_t ) ( 0xFFFFFFFF )
\r
106 #define portBYTE_ALIGNMENT 1
\r
108 /*-----------------------------------------------------------*/
\r
111 * Constant used for context switch macro when we require the interrupt
\r
112 * enable state to be forced when the interrupted task is switched back in.
\r
114 #define portINTERRUPTS_FORCED (0x01)
\r
117 * Constant used for context switch macro when we require the interrupt
\r
118 * enable state to be unchanged when the interrupted task is switched back in.
\r
120 #define portINTERRUPTS_UNCHANGED (0x00)
\r
122 /* Initial interrupt enable state for newly created tasks. This value is
\r
123 * used when a task switches in for the first time.
\r
125 #define portINTERRUPTS_INITIAL_STATE (portINTERRUPTS_FORCED)
\r
128 * Macros to modify the global interrupt enable bit in INTCON.
\r
130 #define portDISABLE_INTERRUPTS() \
\r
134 } while(bGIE) // MicroChip recommends this check!
\r
136 #define portENABLE_INTERRUPTS() \
\r
142 /*-----------------------------------------------------------*/
\r
145 * Critical section macros.
\r
147 extern uint8_t ucCriticalNesting;
\r
149 #define portNO_CRITICAL_SECTION_NESTING ( ( uint8_t ) 0 )
\r
151 #define portENTER_CRITICAL() \
\r
154 portDISABLE_INTERRUPTS(); \
\r
157 * Now interrupts are disabled ucCriticalNesting \
\r
158 * can be accessed directly. Increment \
\r
159 * ucCriticalNesting to keep a count of how \
\r
160 * many times portENTER_CRITICAL() has been called. \
\r
162 ucCriticalNesting++; \
\r
165 #define portEXIT_CRITICAL() \
\r
168 if(ucCriticalNesting > portNO_CRITICAL_SECTION_NESTING) \
\r
171 * Decrement the nesting count as we are leaving a \
\r
172 * critical section. \
\r
174 ucCriticalNesting--; \
\r
178 * If the nesting level has reached zero then \
\r
179 * interrupts should be re-enabled. \
\r
181 if( ucCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
\r
183 portENABLE_INTERRUPTS(); \
\r
187 /*-----------------------------------------------------------*/
\r
190 * The minimal stacksize is calculated on the first reference of
\r
191 * portMINIMAL_STACK_SIZE. Some input to this calculation is
\r
192 * compiletime determined, other input is port-defined (see port.c)
\r
194 extern uint16_t usPortCALCULATE_MINIMAL_STACK_SIZE( void );
\r
195 extern uint16_t usCalcMinStackSize;
\r
197 #define portMINIMAL_STACK_SIZE \
\r
198 ((usCalcMinStackSize == 0) \
\r
199 ? usPortCALCULATE_MINIMAL_STACK_SIZE() \
\r
200 : usCalcMinStackSize )
\r
203 * WizC uses a downgrowing stack
\r
205 #define portSTACK_GROWTH ( -1 )
\r
207 /*-----------------------------------------------------------*/
\r
210 * Macro's that pushes all the registers that make up the context of a task onto
\r
211 * the stack, then saves the new top of stack into the TCB. TOSU and TBLPTRU
\r
212 * are only saved/restored on devices with more than 64kB (32k Words) ROM.
\r
214 * The stackpointer is helt by WizC in FSR2 and points to the first free byte.
\r
215 * WizC uses a "downgrowing" stack. There is no framepointer.
\r
217 * We keep track of the interruptstatus using ucCriticalNesting. When this
\r
218 * value equals zero, interrupts have to be enabled upon exit from the
\r
219 * portRESTORE_CONTEXT macro.
\r
221 * If this is called from an ISR then the interrupt enable bits must have been
\r
222 * set for the ISR to ever get called. Therefore we want to save
\r
223 * ucCriticalNesting with value zero. This means the interrupts will again be
\r
224 * re-enabled when the interrupted task is switched back in.
\r
226 * If this is called from a manual context switch (i.e. from a call to yield),
\r
227 * then we want to keep the current value of ucCritialNesting so it is restored
\r
228 * with its current value. This allows a yield from within a critical section.
\r
230 * The compiler uses some locations at the bottom of RAM for temporary
\r
231 * storage. The compiler may also have been instructed to optimize
\r
232 * function-parameters and local variables to global storage. The compiler
\r
233 * uses an area called LocOpt for this wizC feature.
\r
234 * The total overheadstorage has to be saved in it's entirety as part of
\r
235 * a task context. These macro's store/restore from data address 0x0000 to
\r
236 * (OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE - 1).
\r
237 * OVERHEADPAGE0, LOCOPTSIZE and MAXLOCOPTSIZE are compiler-generated
\r
238 * assembler definitions.
\r
241 #define portSAVE_CONTEXT( ucInterruptForced ) \
\r
244 portDISABLE_INTERRUPTS(); \
\r
248 ; Push the relevant SFR's onto the task's stack \
\r
250 movff STATUS,POSTDEC2 \
\r
251 movff WREG,POSTDEC2 \
\r
252 movff BSR,POSTDEC2 \
\r
253 movff PRODH,POSTDEC2 \
\r
254 movff PRODL,POSTDEC2 \
\r
255 movff FSR0H,POSTDEC2 \
\r
256 movff FSR0L,POSTDEC2 \
\r
257 movff FSR1H,POSTDEC2 \
\r
258 movff FSR1L,POSTDEC2 \
\r
259 movff TABLAT,POSTDEC2 \
\r
260 if __ROMSIZE > 0x8000 \
\r
261 movff TBLPTRU,POSTDEC2 \
\r
263 movff TBLPTRH,POSTDEC2 \
\r
264 movff TBLPTRL,POSTDEC2 \
\r
265 if __ROMSIZE > 0x8000 \
\r
266 movff PCLATU,POSTDEC2 \
\r
268 movff PCLATH,POSTDEC2 \
\r
270 ; Store the compiler-scratch-area as described above. \
\r
272 movlw OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE \
\r
273 clrf FSR0L,ACCESS \
\r
274 clrf FSR0H,ACCESS \
\r
276 movff POSTINC0,POSTDEC2 \
\r
277 decfsz WREG,W,ACCESS \
\r
278 SMARTJUMP _rtos_S1 \
\r
280 ; Save the pic call/return-stack belonging to the \
\r
281 ; current task by copying it to the task's software- \
\r
282 ; stack. We save the hardware stack pointer (which \
\r
283 ; is the number of addresses on the stack) in the \
\r
284 ; W-register first because we need it later and it \
\r
285 ; is modified in the save-loop by executing pop's. \
\r
286 ; After the loop the W-register is stored on the \
\r
289 movf STKPTR,W,ACCESS \
\r
292 if __ROMSIZE > 0x8000 \
\r
293 movff TOSU,POSTDEC2 \
\r
295 movff TOSH,POSTDEC2 \
\r
296 movff TOSL,POSTDEC2 \
\r
298 tstfsz STKPTR,ACCESS \
\r
299 SMARTJUMP _rtos_S2 \
\r
301 movwf POSTDEC2,ACCESS \
\r
303 ; Next the value for ucCriticalNesting used by the \
\r
304 ; task is stored on the stack. When \
\r
305 ; (ucInterruptForced == portINTERRUPTS_FORCED), we save \
\r
306 ; it as 0 (portNO_CRITICAL_SECTION_NESTING). \
\r
308 if ucInterruptForced == portINTERRUPTS_FORCED \
\r
309 clrf POSTDEC2,ACCESS \
\r
311 movff ucCriticalNesting,POSTDEC2 \
\r
314 ; Save the new top of the software stack in the TCB. \
\r
316 movff pxCurrentTCB,FSR0L \
\r
317 movff pxCurrentTCB+1,FSR0H \
\r
318 movff FSR2L,POSTINC0 \
\r
319 movff FSR2H,POSTINC0 \
\r
320 _Pragma("asmend") \
\r
323 /************************************************************/
\r
326 * This is the reverse of portSAVE_CONTEXT.
\r
328 #define portRESTORE_CONTEXT() \
\r
333 ; Set FSR0 to point to pxCurrentTCB->pxTopOfStack. \
\r
335 movff pxCurrentTCB,FSR0L \
\r
336 movff pxCurrentTCB+1,FSR0H \
\r
338 ; De-reference FSR0 to set the address it holds into \
\r
339 ; FSR2 (i.e. *( pxCurrentTCB->pxTopOfStack ) ). FSR2 \
\r
340 ; is used by wizC as stackpointer. \
\r
342 movff POSTINC0,FSR2L \
\r
343 movff POSTINC0,FSR2H \
\r
345 ; Next, the value for ucCriticalNesting used by the \
\r
346 ; task is retrieved from the stack. \
\r
348 movff PREINC2,ucCriticalNesting \
\r
350 ; Rebuild the pic call/return-stack. The number of \
\r
351 ; return addresses is the next item on the task stack. \
\r
352 ; Save this number in PRODL. Then fetch the addresses \
\r
353 ; and store them on the hardwarestack. \
\r
354 ; The datasheets say we can't use movff here... \
\r
356 movff PREINC2,PRODL // Use PRODL as tempregister \
\r
357 clrf STKPTR,ACCESS \
\r
360 movf PREINC2,W,ACCESS \
\r
361 movwf TOSL,ACCESS \
\r
362 movf PREINC2,W,ACCESS \
\r
363 movwf TOSH,ACCESS \
\r
364 if __ROMSIZE > 0x8000 \
\r
365 movf PREINC2,W,ACCESS \
\r
366 movwf TOSU,ACCESS \
\r
370 decfsz PRODL,F,ACCESS \
\r
371 SMARTJUMP _rtos_R1 \
\r
373 ; Restore the compiler's working storage area to page 0 \
\r
375 movlw OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE \
\r
376 movwf FSR0L,ACCESS \
\r
377 clrf FSR0H,ACCESS \
\r
379 decf FSR0L,F,ACCESS \
\r
380 movff PREINC2,INDF0 \
\r
381 tstfsz FSR0L,ACCESS \
\r
382 SMARTJUMP _rtos_R2 \
\r
384 ; Restore the sfr's forming the tasks context. \
\r
385 ; We cannot yet restore bsr, w and status because \
\r
386 ; we need these registers for a final test. \
\r
388 movff PREINC2,PCLATH \
\r
389 if __ROMSIZE > 0x8000 \
\r
390 movff PREINC2,PCLATU \
\r
392 clrf PCLATU,ACCESS \
\r
394 movff PREINC2,TBLPTRL \
\r
395 movff PREINC2,TBLPTRH \
\r
396 if __ROMSIZE > 0x8000 \
\r
397 movff PREINC2,TBLPTRU \
\r
399 clrf TBLPTRU,ACCESS \
\r
401 movff PREINC2,TABLAT \
\r
402 movff PREINC2,FSR1L \
\r
403 movff PREINC2,FSR1H \
\r
404 movff PREINC2,FSR0L \
\r
405 movff PREINC2,FSR0H \
\r
406 movff PREINC2,PRODL \
\r
407 movff PREINC2,PRODH \
\r
409 ; The return from portRESTORE_CONTEXT() depends on \
\r
410 ; the value of ucCriticalNesting. When it is zero, \
\r
411 ; interrupts need to be enabled. This is done via a \
\r
412 ; retfie instruction because we need the \
\r
413 ; interrupt-enabling and the return to the restored \
\r
414 ; task to be uninterruptable. \
\r
415 ; Because bsr, status and W are affected by the test \
\r
416 ; they are restored after the test. \
\r
418 movlb ucCriticalNesting>>8 \
\r
419 tstfsz ucCriticalNesting,BANKED \
\r
420 SMARTJUMP _rtos_R4 \
\r
422 movff PREINC2,BSR \
\r
423 movff PREINC2,WREG \
\r
424 movff PREINC2,STATUS \
\r
425 retfie 0 ; Return enabling interrupts \
\r
427 movff PREINC2,BSR \
\r
428 movff PREINC2,WREG \
\r
429 movff PREINC2,STATUS \
\r
430 return 0 ; Return without affecting interrupts \
\r
431 _Pragma("asmend") \
\r
434 /*-----------------------------------------------------------*/
\r
436 #define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
\r
438 /*-----------------------------------------------------------*/
\r
440 extern void vPortYield( void );
\r
441 #define portYIELD() vPortYield()
\r
443 #define portNOP() _Pragma("asm") \
\r
447 /*-----------------------------------------------------------*/
\r
449 #define portTASK_FUNCTION( xFunction, pvParameters ) \
\r
450 void pointed xFunction( void *pvParameters ) \
\r
451 _Pragma(asmfunc xFunction)
\r
453 #define portTASK_FUNCTION_PROTO portTASK_FUNCTION
\r
454 /*-----------------------------------------------------------*/
\r
460 #endif /* PORTMACRO_H */
\r