2 FreeRTOS.org V4.8.0 - Copyright (C) 2003-2008 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 ***************************************************************************
\r
29 * SAVE TIME AND MONEY! We can port FreeRTOS.org to your own hardware, *
\r
30 * and even write all or part of your application on your behalf. *
\r
31 * See http://www.OpenRTOS.com for details of the services we provide to *
\r
32 * expedite your project. *
\r
34 ***************************************************************************
\r
35 ***************************************************************************
\r
37 Please ensure to read the configuration and relevant port sections of the
\r
38 online documentation.
\r
40 http://www.FreeRTOS.org - Documentation, latest information, license and
\r
43 http://www.SafeRTOS.com - A version that is certified for use in safety
\r
46 http://www.OpenRTOS.com - Commercial support, development, porting,
\r
47 licensing and training services.
\r
53 + Introduced the configKERNEL_INTERRUPT_PRIORITY definition.
\r
56 /*-----------------------------------------------------------
\r
57 * Implementation of functions defined in portable.h for the PIC24 port.
\r
58 *----------------------------------------------------------*/
\r
60 /* Scheduler include files. */
\r
61 #include "FreeRTOS.h"
\r
64 /* Hardware specifics. */
\r
65 #define portBIT_SET 1
\r
66 #define portTIMER_PRESCALE 8
\r
67 #define portINITIAL_SR 0
\r
69 /* Defined for backward compatability with project created prior to
\r
70 FreeRTOS.org V4.3.0. */
\r
71 #ifndef configKERNEL_INTERRUPT_PRIORITY
\r
72 #define configKERNEL_INTERRUPT_PRIORITY 1
\r
75 /* The program counter is only 23 bits. */
\r
76 #define portUNUSED_PR_BITS 0x7f
\r
78 /* Records the nesting depth of calls to portENTER_CRITICAL(). */
\r
79 unsigned portBASE_TYPE uxCriticalNesting = 0xef;
\r
81 #if configKERNEL_INTERRUPT_PRIORITY != 1
\r
82 #error If configKERNEL_INTERRUPT_PRIORITY is not 1 then the #32 in the following macros needs changing to equal the portINTERRUPT_BITS value, which is ( configKERNEL_INTERRUPT_PRIORITY << 5 )
\r
85 #ifdef MPLAB_PIC24_PORT
\r
87 #define portRESTORE_CONTEXT() \
\r
88 asm volatile( "MOV _pxCurrentTCB, W0 \n" /* Restore the stack pointer for the task. */ \
\r
89 "MOV [W0], W15 \n" \
\r
90 "POP W0 \n" /* Restore the critical nesting counter for the task. */ \
\r
91 "MOV W0, _uxCriticalNesting \n" \
\r
95 "POP RCOUNT \n" /* Restore the registers from the stack. */ \
\r
107 #define portSAVE_CONTEXT() \
\r
108 asm volatile( "PUSH SR \n" /* Save the SR used by the task.... */ \
\r
109 "PUSH W0 \n" /* ....then disable interrupts. */ \
\r
112 "PUSH W1 \n" /* Save registers to the stack. */ \
\r
124 "MOV _uxCriticalNesting, W0 \n" /* Save the critical nesting counter for the task. */ \
\r
126 "MOV _pxCurrentTCB, W0 \n" /* Save the new top of stack into the TCB. */ \
\r
129 #endif /* MPLAB_PIC24_PORT */
\r
131 #ifdef MPLAB_DSPIC_PORT
\r
133 #define portRESTORE_CONTEXT() \
\r
134 asm volatile( "MOV _pxCurrentTCB, W0 \n" /* Restore the stack pointer for the task. */ \
\r
135 "MOV [W0], W15 \n" \
\r
136 "POP W0 \n" /* Restore the critical nesting counter for the task. */ \
\r
137 "MOV W0, _uxCriticalNesting \n" \
\r
142 "POP DOSTARTH \n" \
\r
143 "POP DOSTARTL \n" \
\r
152 "POP RCOUNT \n" /* Restore the registers from the stack. */ \
\r
164 #define portSAVE_CONTEXT() \
\r
165 asm volatile( "PUSH SR \n" /* Save the SR used by the task.... */ \
\r
166 "PUSH W0 \n" /* ....then disable interrupts. */ \
\r
169 "PUSH W1 \n" /* Save registers to the stack. */ \
\r
186 "PUSH DOSTARTL \n" \
\r
187 "PUSH DOSTARTH \n" \
\r
192 "MOV _uxCriticalNesting, W0 \n" /* Save the critical nesting counter for the task. */ \
\r
194 "MOV _pxCurrentTCB, W0 \n" /* Save the new top of stack into the TCB. */ \
\r
195 "MOV W15, [W0] " );
\r
197 #endif /* MPLAB_DSPIC_PORT */
\r
200 * Setup the timer used to generate the tick interrupt.
\r
202 static void prvSetupTimerInterrupt( void );
\r
205 * See header file for description.
\r
207 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
\r
209 unsigned portSHORT usCode;
\r
212 const portSTACK_TYPE xInitialStack[] =
\r
228 0xcdce, /* RCOUNT */
\r
229 0xabac, /* TBLPAG */
\r
231 /* dsPIC specific registers. */
\r
232 #ifdef MPLAB_DSPIC_PORT
\r
233 0x0202, /* ACCAL */
\r
234 0x0303, /* ACCAH */
\r
235 0x0404, /* ACCAU */
\r
236 0x0505, /* ACCBL */
\r
237 0x0606, /* ACCBH */
\r
238 0x0707, /* ACCBU */
\r
239 0x0808, /* DCOUNT */
\r
240 0x090a, /* DOSTARTL */
\r
241 0x1010, /* DOSTARTH */
\r
242 0x1110, /* DOENDL */
\r
243 0x1212, /* DOENDH */
\r
247 /* Setup the stack as if a yield had occurred.
\r
249 Save the low bytes of the program counter. */
\r
250 usCode = ( unsigned portSHORT ) pxCode;
\r
251 *pxTopOfStack = ( portSTACK_TYPE ) usCode;
\r
254 /* Save the high byte of the program counter. This will always be zero
\r
255 here as it is passed in a 16bit pointer. If the address is greater than
\r
256 16 bits then the pointer will point to a jump table. */
\r
257 *pxTopOfStack = ( portSTACK_TYPE ) 0;
\r
260 /* Status register with interrupts enabled. */
\r
261 *pxTopOfStack = portINITIAL_SR;
\r
264 /* Parameters are passed in W0. */
\r
265 *pxTopOfStack = ( portSTACK_TYPE ) pvParameters;
\r
268 for( i = 0; i < ( sizeof( xInitialStack ) / sizeof( portSTACK_TYPE ) ); i++ )
\r
270 *pxTopOfStack = xInitialStack[ i ];
\r
274 *pxTopOfStack = CORCON;
\r
276 *pxTopOfStack = PSVPAG;
\r
279 /* Finally the critical nesting depth. */
\r
280 *pxTopOfStack = 0x00;
\r
283 return pxTopOfStack;
\r
285 /*-----------------------------------------------------------*/
\r
287 portBASE_TYPE xPortStartScheduler( void )
\r
289 /* Setup a timer for the tick ISR. */
\r
290 prvSetupTimerInterrupt();
\r
292 /* Restore the context of the first task to run. */
\r
293 portRESTORE_CONTEXT();
\r
295 /* Simulate the end of the yield function. */
\r
296 asm volatile ( "return" );
\r
298 /* Should not reach here. */
\r
301 /*-----------------------------------------------------------*/
\r
303 void vPortEndScheduler( void )
\r
305 /* It is unlikely that the scheduler for the PIC port will get stopped
\r
306 once running. If required disable the tick interrupt here, then return
\r
307 to xPortStartScheduler(). */
\r
309 /*-----------------------------------------------------------*/
\r
312 * Manual context switch. This is similar to the tick context switch,
\r
313 * but does not increment the tick count. It must be identical to the
\r
314 * tick context switch in how it stores the stack of a task.
\r
316 void vPortYield( void )
\r
318 portSAVE_CONTEXT();
\r
319 vTaskSwitchContext();
\r
320 portRESTORE_CONTEXT();
\r
322 /*-----------------------------------------------------------*/
\r
325 * Setup a timer for a regular tick.
\r
327 static void prvSetupTimerInterrupt( void )
\r
329 const unsigned portLONG ulCompareMatch = ( configCPU_CLOCK_HZ / portTIMER_PRESCALE ) / configTICK_RATE_HZ;
\r
331 /* Prescale of 8. */
\r
335 PR1 = ( unsigned portSHORT ) ulCompareMatch;
\r
337 /* Setup timer 1 interrupt priority. */
\r
338 IPC0bits.T1IP = configKERNEL_INTERRUPT_PRIORITY;
\r
340 /* Clear the interrupt as a starting condition. */
\r
343 /* Enable the interrupt. */
\r
346 /* Setup the prescale value. */
\r
347 T1CONbits.TCKPS0 = 1;
\r
348 T1CONbits.TCKPS1 = 0;
\r
350 /* Start the timer. */
\r
353 /*-----------------------------------------------------------*/
\r
355 void vPortEnterCritical( void )
\r
357 portDISABLE_INTERRUPTS();
\r
358 uxCriticalNesting++;
\r
360 /*-----------------------------------------------------------*/
\r
362 void vPortExitCritical( void )
\r
364 uxCriticalNesting--;
\r
365 if( uxCriticalNesting == 0 )
\r
367 portENABLE_INTERRUPTS();
\r
370 /*-----------------------------------------------------------*/
\r
372 void __attribute__((__interrupt__, auto_psv)) _T1Interrupt( void )
\r
374 vTaskIncrementTick();
\r
376 /* Clear the timer interrupt. */
\r
379 #if configUSE_PREEMPTION == 1
\r