2006-10-09 19:40:24 +08:00
/*
2013-11-08 19:47:35 +08:00
FreeRTOS V7 .6 .0 - Copyright ( C ) 2013 Real Time Engineers Ltd .
2013-10-15 03:56:47 +08:00
All rights reserved
2012-10-16 20:17:47 +08:00
2013-07-18 02:32:57 +08:00
VISIT http : //www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
2006-10-09 19:40:24 +08:00
2009-10-13 18:54:32 +08:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2011-04-09 02:30:58 +08:00
* *
2013-07-18 02:32:57 +08:00
* FreeRTOS provides completely free yet professionally developed , *
* robust , strictly quality controlled , supported , and cross *
* platform software that has become a de facto standard . *
2011-04-09 02:30:58 +08:00
* *
2013-07-18 02:32:57 +08:00
* Help yourself get started quickly and support the FreeRTOS *
* project by purchasing a FreeRTOS tutorial book , reference *
* manual , or both from : http : //www.FreeRTOS.org/Documentation *
2011-04-09 02:30:58 +08:00
* *
2013-07-18 02:32:57 +08:00
* Thank you ! *
2011-04-09 02:30:58 +08:00
* *
2009-10-13 18:54:32 +08:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2009-10-05 17:46:11 +08:00
This file is part of the FreeRTOS distribution .
2006-10-09 19:40:24 +08:00
2009-10-13 18:54:32 +08:00
FreeRTOS is free software ; you can redistribute it and / or modify it under
2009-10-05 17:46:11 +08:00
the terms of the GNU General Public License ( version 2 ) as published by the
2013-07-18 02:32:57 +08:00
Free Software Foundation > > ! AND MODIFIED BY ! < < the FreeRTOS exception .
2013-02-20 02:36:58 +08:00
2013-07-18 02:32:57 +08:00
> > ! NOTE : The modification to the GPL is included to allow you to distribute
> > ! a combined work that includes FreeRTOS without being obliged to provide
> > ! the source code for proprietary components outside of the FreeRTOS
> > ! kernel .
2013-02-20 02:36:58 +08:00
FreeRTOS is distributed in the hope that it will be useful , but WITHOUT ANY
WARRANTY ; without even the implied warranty of MERCHANTABILITY or FITNESS
2013-07-18 02:32:57 +08:00
FOR A PARTICULAR PURPOSE . Full license text is available from the following
link : http : //www.freertos.org/a00114.html
2009-03-15 03:20:12 +08:00
2009-10-05 17:46:11 +08:00
1 tab = = 4 spaces !
2013-01-24 00:06:45 +08:00
2012-05-09 00:36:52 +08:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Having a problem ? Start by reading the FAQ " My application does *
2012-10-16 20:17:47 +08:00
* not run , what could be wrong ? " *
2012-05-09 00:36:52 +08:00
* *
* http : //www.FreeRTOS.org/FAQHelp.html *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2007-04-02 04:47:49 +08:00
2013-06-09 02:36:25 +08:00
http : //www.FreeRTOS.org - Documentation, books, training, latest versions,
2013-02-20 02:36:58 +08:00
license and Real Time Engineers Ltd . contact details .
2013-01-24 00:06:45 +08:00
2012-05-09 00:36:52 +08:00
http : //www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
2013-07-18 02:32:57 +08:00
including FreeRTOS + Trace - an indispensable productivity tool , a DOS
compatible FAT file system , and our tiny thread aware UDP / IP stack .
2013-02-20 02:36:58 +08:00
2013-06-09 02:36:25 +08:00
http : //www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
2013-07-18 02:32:57 +08:00
Integrity Systems to sell under the OpenRTOS brand . Low cost OpenRTOS
licenses offer ticketed support , indemnification and middleware .
2013-06-09 02:36:25 +08:00
http : //www.SafeRTOS.com - High Integrity Systems also provide a safety
engineered and independently SIL3 certified version for use in safety and
2013-02-20 02:36:58 +08:00
mission critical applications that require provable dependability .
2013-07-18 02:32:57 +08:00
1 tab = = 4 spaces !
2006-10-09 19:40:24 +08:00
*/
2007-06-05 17:56:16 +08:00
/*
Changes from V4 .2 .1
+ Introduced the configKERNEL_INTERRUPT_PRIORITY definition .
*/
2006-10-09 19:40:24 +08:00
/*-----------------------------------------------------------
* Implementation of functions defined in portable . h for the PIC24 port .
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Scheduler include files. */
# include "FreeRTOS.h"
# include "task.h"
/* Hardware specifics. */
# define portBIT_SET 1
# define portTIMER_PRESCALE 8
# define portINITIAL_SR 0
2013-01-24 00:06:45 +08:00
/* Defined for backward compatability with project created prior to
2007-06-05 17:56:16 +08:00
FreeRTOS . org V4 .3 .0 . */
# ifndef configKERNEL_INTERRUPT_PRIORITY
# define configKERNEL_INTERRUPT_PRIORITY 1
# endif
2013-06-09 02:36:25 +08:00
/* Use _T1Interrupt as the interrupt handler name if the application writer has
not provided their own . */
# ifndef configTICK_INTERRUPT_HANDLER
# define configTICK_INTERRUPT_HANDLER _T1Interrupt
# endif /* configTICK_INTERRUPT_HANDLER */
2006-10-09 19:40:24 +08:00
/* The program counter is only 23 bits. */
# define portUNUSED_PR_BITS 0x7f
/* Records the nesting depth of calls to portENTER_CRITICAL(). */
unsigned portBASE_TYPE uxCriticalNesting = 0xef ;
2007-06-05 17:56:16 +08:00
# if configKERNEL_INTERRUPT_PRIORITY != 1
# 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 )
# endif
2013-06-09 02:36:25 +08:00
# if defined( __PIC24E__ ) || defined ( __PIC24F__ ) || defined( __PIC24FK__ ) || defined( __PIC24H__ )
2006-10-09 19:40:24 +08:00
2013-01-24 00:06:45 +08:00
# ifdef __HAS_EDS__
2013-02-20 02:36:58 +08:00
# define portRESTORE_CONTEXT() \
asm volatile ( " MOV _pxCurrentTCB, W0 \n " /* Restore the stack pointer for the task. */ \
2013-01-24 00:06:45 +08:00
" MOV [W0], W15 \n " \
" POP W0 \n " /* Restore the critical nesting counter for the task. */ \
" MOV W0, _uxCriticalNesting \n " \
" POP DSWPAG \n " \
2013-02-20 02:36:58 +08:00
" POP DSRPAG \n " \
2013-01-24 00:06:45 +08:00
" POP CORCON \n " \
" POP TBLPAG \n " \
" POP RCOUNT \n " /* Restore the registers from the stack. */ \
" POP W14 \n " \
" POP.D W12 \n " \
" POP.D W10 \n " \
" POP.D W8 \n " \
" POP.D W6 \n " \
" POP.D W4 \n " \
" POP.D W2 \n " \
" POP.D W0 \n " \
" POP SR " ) ;
# else /* __HAS_EDS__ */
# define portRESTORE_CONTEXT() \
asm volatile ( " MOV _pxCurrentTCB, W0 \n " /* Restore the stack pointer for the task. */ \
" MOV [W0], W15 \n " \
" POP W0 \n " /* Restore the critical nesting counter for the task. */ \
" MOV W0, _uxCriticalNesting \n " \
" POP PSVPAG \n " \
" POP CORCON \n " \
" POP TBLPAG \n " \
" POP RCOUNT \n " /* Restore the registers from the stack. */ \
" POP W14 \n " \
" POP.D W12 \n " \
" POP.D W10 \n " \
" POP.D W8 \n " \
" POP.D W6 \n " \
" POP.D W4 \n " \
" POP.D W2 \n " \
" POP.D W0 \n " \
" POP SR " ) ;
# endif /* __HAS_EDS__ */
2006-10-09 19:40:24 +08:00
# endif /* MPLAB_PIC24_PORT */
2013-06-12 04:15:15 +08:00
# if defined( __dsPIC30F__ ) || defined( __dsPIC33F__ )
2006-10-09 19:40:24 +08:00
# define portRESTORE_CONTEXT() \
asm volatile ( " MOV _pxCurrentTCB, W0 \n " /* Restore the stack pointer for the task. */ \
" MOV [W0], W15 \n " \
" POP W0 \n " /* Restore the critical nesting counter for the task. */ \
" MOV W0, _uxCriticalNesting \n " \
" POP PSVPAG \n " \
" POP CORCON \n " \
" POP DOENDH \n " \
" POP DOENDL \n " \
" POP DOSTARTH \n " \
" POP DOSTARTL \n " \
" POP DCOUNT \n " \
" POP ACCBU \n " \
" POP ACCBH \n " \
" POP ACCBL \n " \
" POP ACCAU \n " \
" POP ACCAH \n " \
" POP ACCAL \n " \
" POP TBLPAG \n " \
" POP RCOUNT \n " /* Restore the registers from the stack. */ \
" POP W14 \n " \
" POP.D W12 \n " \
" POP.D W10 \n " \
" POP.D W8 \n " \
" POP.D W6 \n " \
" POP.D W4 \n " \
" POP.D W2 \n " \
" POP.D W0 \n " \
" POP SR " ) ;
# endif /* MPLAB_DSPIC_PORT */
2013-06-09 02:36:25 +08:00
# ifndef portRESTORE_CONTEXT
# error Unrecognised device selected
# endif
2006-10-09 19:40:24 +08:00
/*
* Setup the timer used to generate the tick interrupt .
*/
2013-06-09 02:36:25 +08:00
void vApplicationSetupTickTimerInterrupt ( void ) ;
2006-10-09 19:40:24 +08:00
2013-01-24 00:06:45 +08:00
/*
* See header file for description .
2006-10-09 19:40:24 +08:00
*/
portSTACK_TYPE * pxPortInitialiseStack ( portSTACK_TYPE * pxTopOfStack , pdTASK_CODE pxCode , void * pvParameters )
{
2009-10-05 17:46:11 +08:00
unsigned short usCode ;
2013-06-09 02:36:25 +08:00
unsigned portBASE_TYPE i ;
2006-10-09 19:40:24 +08:00
2013-01-24 00:06:45 +08:00
const portSTACK_TYPE xInitialStack [ ] =
2006-10-09 19:40:24 +08:00
{
0x1111 , /* W1 */
0x2222 , /* W2 */
0x3333 , /* W3 */
0x4444 , /* W4 */
0x5555 , /* W5 */
0x6666 , /* W6 */
0x7777 , /* W7 */
0x8888 , /* W8 */
0x9999 , /* W9 */
0xaaaa , /* W10 */
0xbbbb , /* W11 */
0xcccc , /* W12 */
0xdddd , /* W13 */
0xeeee , /* W14 */
0xcdce , /* RCOUNT */
0xabac , /* TBLPAG */
/* dsPIC specific registers. */
# ifdef MPLAB_DSPIC_PORT
0x0202 , /* ACCAL */
0x0303 , /* ACCAH */
0x0404 , /* ACCAU */
0x0505 , /* ACCBL */
0x0606 , /* ACCBH */
0x0707 , /* ACCBU */
0x0808 , /* DCOUNT */
0x090a , /* DOSTARTL */
0x1010 , /* DOSTARTH */
0x1110 , /* DOENDL */
0x1212 , /* DOENDH */
# endif
} ;
/* Setup the stack as if a yield had occurred.
Save the low bytes of the program counter . */
2009-10-05 17:46:11 +08:00
usCode = ( unsigned short ) pxCode ;
2006-10-09 19:40:24 +08:00
* pxTopOfStack = ( portSTACK_TYPE ) usCode ;
pxTopOfStack + + ;
/* Save the high byte of the program counter. This will always be zero
here as it is passed in a 16 bit pointer . If the address is greater than
16 bits then the pointer will point to a jump table . */
* pxTopOfStack = ( portSTACK_TYPE ) 0 ;
pxTopOfStack + + ;
/* Status register with interrupts enabled. */
* pxTopOfStack = portINITIAL_SR ;
pxTopOfStack + + ;
/* Parameters are passed in W0. */
* pxTopOfStack = ( portSTACK_TYPE ) pvParameters ;
pxTopOfStack + + ;
for ( i = 0 ; i < ( sizeof ( xInitialStack ) / sizeof ( portSTACK_TYPE ) ) ; i + + )
{
* pxTopOfStack = xInitialStack [ i ] ;
pxTopOfStack + + ;
}
* pxTopOfStack = CORCON ;
pxTopOfStack + + ;
2013-01-24 00:06:45 +08:00
# if defined(__HAS_EDS__)
* pxTopOfStack = DSRPAG ;
pxTopOfStack + + ;
* pxTopOfStack = DSWPAG ;
pxTopOfStack + + ;
# else /* __HAS_EDS__ */
* pxTopOfStack = PSVPAG ;
pxTopOfStack + + ;
# endif /* __HAS_EDS__ */
2006-10-09 19:40:24 +08:00
/* Finally the critical nesting depth. */
* pxTopOfStack = 0x00 ;
pxTopOfStack + + ;
return pxTopOfStack ;
}
/*-----------------------------------------------------------*/
portBASE_TYPE xPortStartScheduler ( void )
{
/* Setup a timer for the tick ISR. */
2013-06-09 02:36:25 +08:00
vApplicationSetupTickTimerInterrupt ( ) ;
2006-10-09 19:40:24 +08:00
/* Restore the context of the first task to run. */
portRESTORE_CONTEXT ( ) ;
/* Simulate the end of the yield function. */
asm volatile ( " return " ) ;
/* Should not reach here. */
return pdTRUE ;
}
/*-----------------------------------------------------------*/
void vPortEndScheduler ( void )
{
/* It is unlikely that the scheduler for the PIC port will get stopped
2013-01-24 00:06:45 +08:00
once running . If required disable the tick interrupt here , then return
2006-10-09 19:40:24 +08:00
to xPortStartScheduler ( ) . */
}
/*-----------------------------------------------------------*/
/*
* Setup a timer for a regular tick .
*/
2013-06-09 02:36:25 +08:00
__attribute__ ( ( weak ) ) void vApplicationSetupTickTimerInterrupt ( void )
2006-10-09 19:40:24 +08:00
{
2010-08-23 23:59:07 +08:00
const unsigned long ulCompareMatch = ( ( configCPU_CLOCK_HZ / portTIMER_PRESCALE ) / configTICK_RATE_HZ ) - 1 ;
2006-10-09 19:40:24 +08:00
/* Prescale of 8. */
T1CON = 0 ;
TMR1 = 0 ;
2009-10-05 17:46:11 +08:00
PR1 = ( unsigned short ) ulCompareMatch ;
2006-10-09 19:40:24 +08:00
/* Setup timer 1 interrupt priority. */
2007-06-05 17:56:16 +08:00
IPC0bits . T1IP = configKERNEL_INTERRUPT_PRIORITY ;
2006-10-09 19:40:24 +08:00
/* Clear the interrupt as a starting condition. */
IFS0bits . T1IF = 0 ;
/* Enable the interrupt. */
IEC0bits . T1IE = 1 ;
/* Setup the prescale value. */
T1CONbits . TCKPS0 = 1 ;
T1CONbits . TCKPS1 = 0 ;
/* Start the timer. */
T1CONbits . TON = 1 ;
}
/*-----------------------------------------------------------*/
void vPortEnterCritical ( void )
{
portDISABLE_INTERRUPTS ( ) ;
uxCriticalNesting + + ;
}
/*-----------------------------------------------------------*/
void vPortExitCritical ( void )
{
uxCriticalNesting - - ;
if ( uxCriticalNesting = = 0 )
{
portENABLE_INTERRUPTS ( ) ;
}
}
/*-----------------------------------------------------------*/
2013-06-09 02:36:25 +08:00
void __attribute__ ( ( __interrupt__ , auto_psv ) ) configTICK_INTERRUPT_HANDLER ( void )
2006-10-09 19:40:24 +08:00
{
/* Clear the timer interrupt. */
IFS0bits . T1IF = 0 ;
2013-06-07 20:16:58 +08:00
if ( xTaskIncrementTick ( ) ! = pdFALSE )
{
2006-10-09 19:40:24 +08:00
portYIELD ( ) ;
2013-06-07 20:16:58 +08:00
}
2006-10-09 19:40:24 +08:00
}
2013-06-07 20:16:58 +08:00