2 FreeRTOS.org V4.1.0 - Copyright (C) 2003-2006 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
30 ***************************************************************************
\r
33 /*-----------------------------------------------------------
\r
34 * Implementation of functions defined in portable.h for the PIC24 port.
\r
35 *----------------------------------------------------------*/
\r
37 /* Scheduler include files. */
\r
38 #include "FreeRTOS.h"
\r
41 /* Hardware specifics. */
\r
42 #define portBIT_SET 1
\r
43 #define portTIMER_PRESCALE 8
\r
44 #define portINITIAL_SR 0
\r
46 /* The program counter is only 23 bits. */
\r
47 #define portUNUSED_PR_BITS 0x7f
\r
49 /* Records the nesting depth of calls to portENTER_CRITICAL(). */
\r
50 unsigned portBASE_TYPE uxCriticalNesting = 0xef;
\r
52 #ifdef MPLAB_PIC24_PORT
\r
54 #define portRESTORE_CONTEXT() \
\r
55 asm volatile( "MOV _pxCurrentTCB, W0 \n" /* Restore the stack pointer for the task. */ \
\r
56 "MOV [W0], W15 \n" \
\r
57 "POP W0 \n" /* Restore the critical nesting counter for the task. */ \
\r
58 "MOV W0, _uxCriticalNesting \n" \
\r
62 "POP RCOUNT \n" /* Restore the registers from the stack. */ \
\r
74 #define portSAVE_CONTEXT() \
\r
75 asm volatile( "PUSH SR \n" /* Save the SR used by the task.... */ \
\r
76 "PUSH W0 \n" /* ....then disable interrupts. */ \
\r
79 "PUSH W1 \n" /* Save registers to the stack. */ \
\r
91 "MOV _uxCriticalNesting, W0 \n" /* Save the critical nesting counter for the task. */ \
\r
93 "MOV _pxCurrentTCB, W0 \n" /* Save the new top of stack into the TCB. */ \
\r
96 #endif /* MPLAB_PIC24_PORT */
\r
98 #ifdef MPLAB_DSPIC_PORT
\r
100 #define portRESTORE_CONTEXT() \
\r
101 asm volatile( "MOV _pxCurrentTCB, W0 \n" /* Restore the stack pointer for the task. */ \
\r
102 "MOV [W0], W15 \n" \
\r
103 "POP W0 \n" /* Restore the critical nesting counter for the task. */ \
\r
104 "MOV W0, _uxCriticalNesting \n" \
\r
109 "POP DOSTARTH \n" \
\r
110 "POP DOSTARTL \n" \
\r
119 "POP RCOUNT \n" /* Restore the registers from the stack. */ \
\r
131 #define portSAVE_CONTEXT() \
\r
132 asm volatile( "PUSH SR \n" /* Save the SR used by the task.... */ \
\r
133 "PUSH W0 \n" /* ....then disable interrupts. */ \
\r
134 "MOV #224, W0 \n" \
\r
136 "PUSH W1 \n" /* Save registers to the stack. */ \
\r
153 "PUSH DOSTARTL \n" \
\r
154 "PUSH DOSTARTH \n" \
\r
159 "MOV _uxCriticalNesting, W0 \n" /* Save the critical nesting counter for the task. */ \
\r
161 "MOV _pxCurrentTCB, W0 \n" /* Save the new top of stack into the TCB. */ \
\r
162 "MOV W15, [W0] " );
\r
164 #endif /* MPLAB_DSPIC_PORT */
\r
167 * Setup the timer used to generate the tick interrupt.
\r
169 static void prvSetupTimerInterrupt( void );
\r
172 * See header file for description.
\r
174 portSTACK_TYPE *pxPortInitialiseStack( portSTACK_TYPE *pxTopOfStack, pdTASK_CODE pxCode, void *pvParameters )
\r
176 unsigned portSHORT usCode;
\r
179 const portSTACK_TYPE xInitialStack[] =
\r
195 0xcdce, /* RCOUNT */
\r
196 0xabac, /* TBLPAG */
\r
198 /* dsPIC specific registers. */
\r
199 #ifdef MPLAB_DSPIC_PORT
\r
200 0x0202, /* ACCAL */
\r
201 0x0303, /* ACCAH */
\r
202 0x0404, /* ACCAU */
\r
203 0x0505, /* ACCBL */
\r
204 0x0606, /* ACCBH */
\r
205 0x0707, /* ACCBU */
\r
206 0x0808, /* DCOUNT */
\r
207 0x090a, /* DOSTARTL */
\r
208 0x1010, /* DOSTARTH */
\r
209 0x1110, /* DOENDL */
\r
210 0x1212, /* DOENDH */
\r
214 /* Setup the stack as if a yield had occurred.
\r
216 Save the low bytes of the program counter. */
\r
217 usCode = ( unsigned portSHORT ) pxCode;
\r
218 *pxTopOfStack = ( portSTACK_TYPE ) usCode;
\r
221 /* Save the high byte of the program counter. This will always be zero
\r
222 here as it is passed in a 16bit pointer. If the address is greater than
\r
223 16 bits then the pointer will point to a jump table. */
\r
224 *pxTopOfStack = ( portSTACK_TYPE ) 0;
\r
227 /* Status register with interrupts enabled. */
\r
228 *pxTopOfStack = portINITIAL_SR;
\r
231 /* Parameters are passed in W0. */
\r
232 *pxTopOfStack = ( portSTACK_TYPE ) pvParameters;
\r
235 for( i = 0; i < ( sizeof( xInitialStack ) / sizeof( portSTACK_TYPE ) ); i++ )
\r
237 *pxTopOfStack = xInitialStack[ i ];
\r
241 *pxTopOfStack = CORCON;
\r
243 *pxTopOfStack = PSVPAG;
\r
246 /* Finally the critical nesting depth. */
\r
247 *pxTopOfStack = 0x00;
\r
250 return pxTopOfStack;
\r
252 /*-----------------------------------------------------------*/
\r
254 portBASE_TYPE xPortStartScheduler( void )
\r
256 /* Setup a timer for the tick ISR. */
\r
257 prvSetupTimerInterrupt();
\r
259 /* Restore the context of the first task to run. */
\r
260 portRESTORE_CONTEXT();
\r
262 /* Simulate the end of the yield function. */
\r
263 asm volatile ( "return" );
\r
265 /* Should not reach here. */
\r
268 /*-----------------------------------------------------------*/
\r
270 void vPortEndScheduler( void )
\r
272 /* It is unlikely that the scheduler for the PIC port will get stopped
\r
273 once running. If required disable the tick interrupt here, then return
\r
274 to xPortStartScheduler(). */
\r
276 /*-----------------------------------------------------------*/
\r
279 * Manual context switch. This is similar to the tick context switch,
\r
280 * but does not increment the tick count. It must be identical to the
\r
281 * tick context switch in how it stores the stack of a task.
\r
283 void vPortYield( void )
\r
285 portSAVE_CONTEXT();
\r
286 vTaskSwitchContext();
\r
287 portRESTORE_CONTEXT();
\r
289 /*-----------------------------------------------------------*/
\r
292 * Setup a timer for a regular tick.
\r
294 static void prvSetupTimerInterrupt( void )
\r
296 const unsigned portLONG ulCompareMatch = ( configCPU_CLOCK_HZ / portTIMER_PRESCALE ) / configTICK_RATE_HZ;
\r
298 /* Prescale of 8. */
\r
302 PR1 = ( unsigned portSHORT ) ulCompareMatch;
\r
304 /* Setup timer 1 interrupt priority. */
\r
305 IPC0bits.T1IP = portKERNEL_INTERRUPT_PRIORITY;
\r
307 /* Clear the interrupt as a starting condition. */
\r
310 /* Enable the interrupt. */
\r
313 /* Setup the prescale value. */
\r
314 T1CONbits.TCKPS0 = 1;
\r
315 T1CONbits.TCKPS1 = 0;
\r
317 /* Start the timer. */
\r
320 /*-----------------------------------------------------------*/
\r
322 void vPortEnterCritical( void )
\r
324 portDISABLE_INTERRUPTS();
\r
325 uxCriticalNesting++;
\r
327 /*-----------------------------------------------------------*/
\r
329 void vPortExitCritical( void )
\r
331 uxCriticalNesting--;
\r
332 if( uxCriticalNesting == 0 )
\r
334 portENABLE_INTERRUPTS();
\r
337 /*-----------------------------------------------------------*/
\r
339 void __attribute__((__interrupt__)) _T1Interrupt( void )
\r
341 vTaskIncrementTick();
\r
343 /* Clear the timer interrupt. */
\r
346 #if configUSE_PREEMPTION == 1
\r