2 FreeRTOS.org V4.3.0 - Copyright (C) 2003-2007 Richard Barry.
\r
4 This file is part of the FreeRTOS.org distribution.
\r
6 FreeRTOS.org is free software; you can redistribute it and/or modify
\r
7 it under the terms of the GNU General Public License as published by
\r
8 the Free Software Foundation; either version 2 of the License, or
\r
9 (at your option) any later version.
\r
11 FreeRTOS.org is distributed in the hope that it will be useful,
\r
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 GNU General Public License for more details.
\r
16 You should have received a copy of the GNU General Public License
\r
17 along with FreeRTOS.org; if not, write to the Free Software
\r
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
20 A special exception to the GPL can be applied should you wish to distribute
\r
21 a combined work that includes FreeRTOS.org, without being obliged to provide
\r
22 the source code for any proprietary components. See the licensing section
\r
23 of http://www.FreeRTOS.org for full details of how and when the exception
\r
26 ***************************************************************************
\r
27 See http://www.FreeRTOS.org for documentation, latest information, license
\r
28 and contact details. Please ensure to read the configuration and relevant
\r
29 port sections of the online documentation.
\r
31 Also see http://www.SafeRTOS.com for an IEC 61508 compliant version along
\r
32 with commercial development and support options.
\r
33 ***************************************************************************
\r
44 #if !defined(_SERIES) || _SERIES != 18
\r
45 #error "WizC supports FreeRTOS on the Microchip PIC18-series only"
\r
48 #if !defined(QUICKCALL) || QUICKCALL != 1
\r
49 #error "QuickCall must be enabled (see ProjectOptions/Optimisations)"
\r
55 #define portCHAR char
\r
56 #define portFLOAT float
\r
57 #define portDOUBLE portFLOAT
\r
58 #define portLONG long
\r
59 #define portSHORT short
\r
60 #define portSTACK_TYPE unsigned char
\r
61 #define portBASE_TYPE char
\r
63 #if( configUSE_16_BIT_TICKS == 1 )
\r
64 typedef unsigned portSHORT portTickType;
\r
65 #define portMAX_DELAY ( portTickType ) ( 0xFFFF )
\r
67 typedef unsigned portLONG portTickType;
\r
68 #define portMAX_DELAY ( portTickType ) ( 0xFFFFFFFF )
\r
71 #define portBYTE_ALIGNMENT 1
\r
73 /*-----------------------------------------------------------*/
\r
76 * Constant used for context switch macro when we require the interrupt
\r
77 * enable state to be forced when the interrupted task is switched back in.
\r
79 #define portINTERRUPTS_FORCED (0x01)
\r
82 * Constant used for context switch macro when we require the interrupt
\r
83 * enable state to be unchanged when the interrupted task is switched back in.
\r
85 #define portINTERRUPTS_UNCHANGED (0x00)
\r
87 /* Initial interrupt enable state for newly created tasks. This value is
\r
88 * used when a task switches in for the first time.
\r
90 #define portINTERRUPTS_INITIAL_STATE (portINTERRUPTS_FORCED)
\r
93 * Macros to modify the global interrupt enable bit in INTCON.
\r
95 #define portDISABLE_INTERRUPTS() \
\r
99 } while(bGIE) // MicroChip recommends this check!
\r
101 #define portENABLE_INTERRUPTS() \
\r
107 /*-----------------------------------------------------------*/
\r
110 * Critical section macros.
\r
112 extern unsigned portCHAR ucCriticalNesting;
\r
114 #define portNO_CRITICAL_SECTION_NESTING ( ( unsigned portCHAR ) 0 )
\r
116 #define portENTER_CRITICAL() \
\r
119 portDISABLE_INTERRUPTS(); \
\r
122 * Now interrupts are disabled ucCriticalNesting \
\r
123 * can be accessed directly. Increment \
\r
124 * ucCriticalNesting to keep a count of how \
\r
125 * many times portENTER_CRITICAL() has been called. \
\r
127 ucCriticalNesting++; \
\r
130 #define portEXIT_CRITICAL() \
\r
133 if(ucCriticalNesting > portNO_CRITICAL_SECTION_NESTING) \
\r
136 * Decrement the nesting count as we are leaving a \
\r
137 * critical section. \
\r
139 ucCriticalNesting--; \
\r
143 * If the nesting level has reached zero then \
\r
144 * interrupts should be re-enabled. \
\r
146 if( ucCriticalNesting == portNO_CRITICAL_SECTION_NESTING ) \
\r
148 portENABLE_INTERRUPTS(); \
\r
152 /*-----------------------------------------------------------*/
\r
155 * The minimal stacksize is calculated on the first reference of
\r
156 * portMINIMAL_STACK_SIZE. Some input to this calculation is
\r
157 * compiletime determined, other input is port-defined (see port.c)
\r
159 extern unsigned portSHORT usPortCALCULATE_MINIMAL_STACK_SIZE( void );
\r
160 extern unsigned portSHORT usCalcMinStackSize;
\r
162 #define portMINIMAL_STACK_SIZE \
\r
163 ((usCalcMinStackSize == 0) \
\r
164 ? usPortCALCULATE_MINIMAL_STACK_SIZE() \
\r
165 : usCalcMinStackSize )
\r
168 * WizC uses a downgrowing stack
\r
170 #define portSTACK_GROWTH ( -1 )
\r
172 /*-----------------------------------------------------------*/
\r
175 * Macro's that pushes all the registers that make up the context of a task onto
\r
176 * the stack, then saves the new top of stack into the TCB. TOSU and TBLPTRU
\r
177 * are only saved/restored on devices with more than 64kB (32k Words) ROM.
\r
179 * The stackpointer is helt by WizC in FSR2 and points to the first free byte.
\r
180 * WizC uses a "downgrowing" stack. There is no framepointer.
\r
182 * We keep track of the interruptstatus using ucCriticalNesting. When this
\r
183 * value equals zero, interrupts have to be enabled upon exit from the
\r
184 * portRESTORE_CONTEXT macro.
\r
186 * If this is called from an ISR then the interrupt enable bits must have been
\r
187 * set for the ISR to ever get called. Therefore we want to save
\r
188 * ucCriticalNesting with value zero. This means the interrupts will again be
\r
189 * re-enabled when the interrupted task is switched back in.
\r
191 * If this is called from a manual context switch (i.e. from a call to yield),
\r
192 * then we want to keep the current value of ucCritialNesting so it is restored
\r
193 * with its current value. This allows a yield from within a critical section.
\r
195 * The compiler uses some locations at the bottom of RAM for temporary
\r
196 * storage. The compiler may also have been instructed to optimize
\r
197 * function-parameters and local variables to global storage. The compiler
\r
198 * uses an area called LocOpt for this wizC feature.
\r
199 * The total overheadstorage has to be saved in it's entirety as part of
\r
200 * a task context. These macro's store/restore from data address 0x0000 to
\r
201 * (OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE - 1).
\r
202 * OVERHEADPAGE0, LOCOPTSIZE and MAXLOCOPTSIZE are compiler-generated
\r
203 * assembler definitions.
\r
206 #define portSAVE_CONTEXT( ucInterruptForced ) \
\r
209 portDISABLE_INTERRUPTS(); \
\r
213 ; Push the relevant SFR's onto the task's stack \
\r
215 movff STATUS,POSTDEC2 \
\r
216 movff WREG,POSTDEC2 \
\r
217 movff BSR,POSTDEC2 \
\r
218 movff PRODH,POSTDEC2 \
\r
219 movff PRODL,POSTDEC2 \
\r
220 movff FSR0H,POSTDEC2 \
\r
221 movff FSR0L,POSTDEC2 \
\r
222 movff FSR1H,POSTDEC2 \
\r
223 movff FSR1L,POSTDEC2 \
\r
224 movff TABLAT,POSTDEC2 \
\r
225 if __ROMSIZE > 0x8000 \
\r
226 movff TBLPTRU,POSTDEC2 \
\r
228 movff TBLPTRH,POSTDEC2 \
\r
229 movff TBLPTRL,POSTDEC2 \
\r
230 if __ROMSIZE > 0x8000 \
\r
231 movff PCLATU,POSTDEC2 \
\r
233 movff PCLATH,POSTDEC2 \
\r
235 ; Store the compiler-scratch-area as described above. \
\r
237 movlw OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE \
\r
238 clrf FSR0L,ACCESS \
\r
239 clrf FSR0H,ACCESS \
\r
241 movff POSTINC0,POSTDEC2 \
\r
242 decfsz WREG,W,ACCESS \
\r
243 SMARTJUMP _rtos_S1 \
\r
245 ; Save the pic call/return-stack belonging to the \
\r
246 ; current task by copying it to the task's software- \
\r
247 ; stack. We save the hardware stack pointer (which \
\r
248 ; is the number of addresses on the stack) in the \
\r
249 ; W-register first because we need it later and it \
\r
250 ; is modified in the save-loop by executing pop's. \
\r
251 ; After the loop the W-register is stored on the \
\r
254 movf STKPTR,W,ACCESS \
\r
257 if __ROMSIZE > 0x8000 \
\r
258 movff TOSU,POSTDEC2 \
\r
260 movff TOSH,POSTDEC2 \
\r
261 movff TOSL,POSTDEC2 \
\r
263 tstfsz STKPTR,ACCESS \
\r
264 SMARTJUMP _rtos_S2 \
\r
266 movwf POSTDEC2,ACCESS \
\r
268 ; Next the value for ucCriticalNesting used by the \
\r
269 ; task is stored on the stack. When \
\r
270 ; (ucInterruptForced == portINTERRUPTS_FORCED), we save \
\r
271 ; it as 0 (portNO_CRITICAL_SECTION_NESTING). \
\r
273 if ucInterruptForced == portINTERRUPTS_FORCED \
\r
274 clrf POSTDEC2,ACCESS \
\r
276 movff ucCriticalNesting,POSTDEC2 \
\r
279 ; Save the new top of the software stack in the TCB. \
\r
281 movff pxCurrentTCB,FSR0L \
\r
282 movff pxCurrentTCB+1,FSR0H \
\r
283 movff FSR2L,POSTINC0 \
\r
284 movff FSR2H,POSTINC0 \
\r
285 _Pragma("asmend") \
\r
288 /************************************************************/
\r
291 * This is the reverse of portSAVE_CONTEXT.
\r
293 #define portRESTORE_CONTEXT() \
\r
298 ; Set FSR0 to point to pxCurrentTCB->pxTopOfStack. \
\r
300 movff pxCurrentTCB,FSR0L \
\r
301 movff pxCurrentTCB+1,FSR0H \
\r
303 ; De-reference FSR0 to set the address it holds into \
\r
304 ; FSR2 (i.e. *( pxCurrentTCB->pxTopOfStack ) ). FSR2 \
\r
305 ; is used by wizC as stackpointer. \
\r
307 movff POSTINC0,FSR2L \
\r
308 movff POSTINC0,FSR2H \
\r
310 ; Next, the value for ucCriticalNesting used by the \
\r
311 ; task is retrieved from the stack. \
\r
313 movff PREINC2,ucCriticalNesting \
\r
315 ; Rebuild the pic call/return-stack. The number of \
\r
316 ; return addresses is the next item on the task stack. \
\r
317 ; Save this number in PRODL. Then fetch the addresses \
\r
318 ; and store them on the hardwarestack. \
\r
319 ; The datasheets say we can't use movff here... \
\r
321 movff PREINC2,PRODL // Use PRODL as tempregister \
\r
322 clrf STKPTR,ACCESS \
\r
325 movf PREINC2,W,ACCESS \
\r
326 movwf TOSL,ACCESS \
\r
327 movf PREINC2,W,ACCESS \
\r
328 movwf TOSH,ACCESS \
\r
329 if __ROMSIZE > 0x8000 \
\r
330 movf PREINC2,W,ACCESS \
\r
331 movwf TOSU,ACCESS \
\r
335 decfsz PRODL,F,ACCESS \
\r
336 SMARTJUMP _rtos_R1 \
\r
338 ; Restore the compiler's working storage area to page 0 \
\r
340 movlw OVERHEADPAGE0-LOCOPTSIZE+MAXLOCOPTSIZE \
\r
341 movwf FSR0L,ACCESS \
\r
342 clrf FSR0H,ACCESS \
\r
344 decf FSR0L,F,ACCESS \
\r
345 movff PREINC2,INDF0 \
\r
346 tstfsz FSR0L,ACCESS \
\r
347 SMARTJUMP _rtos_R2 \
\r
349 ; Restore the sfr's forming the tasks context. \
\r
350 ; We cannot yet restore bsr, w and status because \
\r
351 ; we need these registers for a final test. \
\r
353 movff PREINC2,PCLATH \
\r
354 if __ROMSIZE > 0x8000 \
\r
355 movff PREINC2,PCLATU \
\r
357 clrf PCLATU,ACCESS \
\r
359 movff PREINC2,TBLPTRL \
\r
360 movff PREINC2,TBLPTRH \
\r
361 if __ROMSIZE > 0x8000 \
\r
362 movff PREINC2,TBLPTRU \
\r
364 clrf TBLPTRU,ACCESS \
\r
366 movff PREINC2,TABLAT \
\r
367 movff PREINC2,FSR1L \
\r
368 movff PREINC2,FSR1H \
\r
369 movff PREINC2,FSR0L \
\r
370 movff PREINC2,FSR0H \
\r
371 movff PREINC2,PRODL \
\r
372 movff PREINC2,PRODH \
\r
374 ; The return from portRESTORE_CONTEXT() depends on \
\r
375 ; the value of ucCriticalNesting. When it is zero, \
\r
376 ; interrupts need to be enabled. This is done via a \
\r
377 ; retfie instruction because we need the \
\r
378 ; interrupt-enabling and the return to the restored \
\r
379 ; task to be uninterruptable. \
\r
380 ; Because bsr, status and W are affected by the test \
\r
381 ; they are restored after the test. \
\r
383 movlb ucCriticalNesting>>8 \
\r
384 tstfsz ucCriticalNesting,BANKED \
\r
385 SMARTJUMP _rtos_R4 \
\r
387 movff PREINC2,BSR \
\r
388 movff PREINC2,WREG \
\r
389 movff PREINC2,STATUS \
\r
390 retfie 0 ; Return enabling interrupts \
\r
392 movff PREINC2,BSR \
\r
393 movff PREINC2,WREG \
\r
394 movff PREINC2,STATUS \
\r
395 return 0 ; Return without affecting interrupts \
\r
396 _Pragma("asmend") \
\r
399 /*-----------------------------------------------------------*/
\r
401 #define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ )
\r
403 /*-----------------------------------------------------------*/
\r
405 extern void vPortYield( void );
\r
406 #define portYIELD() vPortYield()
\r
408 #define portNOP() _Pragma("asm") \
\r
412 /*-----------------------------------------------------------*/
\r
414 #define portTASK_FUNCTION( xFunction, pvParameters ) \
\r
415 void pointed xFunction( void *pvParameters ) \
\r
416 _Pragma(asmfunc xFunction)
\r
418 #define portTASK_FUNCTION_PROTO portTASK_FUNCTION
\r
419 /*-----------------------------------------------------------*/
\r
425 #endif /* PORTMACRO_H */
\r