diff --git a/portable/MPLAB/PIC18F/port.c b/portable/MPLAB/PIC18F/port.c index 471a6955e42..a26d97116cf 100644 --- a/portable/MPLAB/PIC18F/port.c +++ b/portable/MPLAB/PIC18F/port.c @@ -27,33 +27,33 @@ */ /* - * Changes between V1.2.4 and V1.2.5 - * - + Introduced portGLOBAL_INTERRUPT_FLAG definition to test the global - + interrupt flag setting. Using the two bits defined within - + portINITAL_INTERRUPT_STATE was causing the w register to get clobbered - + before the test was performed. - + - + Changes from V1.2.5 - + - + Set the interrupt vector address to 0x08. Previously it was at the - + incorrect address for compatibility mode of 0x18. - + - + Changes from V2.1.1 - + - + PCLATU and PCLATH are now saved as part of the context. This allows - + function pointers to be used within tasks. Thanks to Javier Espeche - + for the enhancement. - + - + Changes from V2.3.1 - + - + TABLAT is now saved as part of the task context. - + - + Changes from V3.2.0 - + - + TBLPTRU is now initialised to zero as the MPLAB compiler expects this - + value and does not write to the register. - */ +Changes between V1.2.4 and V1.2.5 + + + Introduced portGLOBAL_INTERRUPT_FLAG definition to test the global + interrupt flag setting. Using the two bits defined within + portINITAL_INTERRUPT_STATE was causing the w register to get clobbered + before the test was performed. + +Changes from V1.2.5 + + + Set the interrupt vector address to 0x08. Previously it was at the + incorrect address for compatibility mode of 0x18. + +Changes from V2.1.1 + + + PCLATU and PCLATH are now saved as part of the context. This allows + function pointers to be used within tasks. Thanks to Javier Espeche + for the enhancement. + +Changes from V2.3.1 + + + TABLAT is now saved as part of the task context. + +Changes from V3.2.0 + + + TBLPTRU is now initialised to zero as the MPLAB compiler expects this + value and does not write to the register. +*/ /* Scheduler include files. */ #include "FreeRTOS.h" @@ -63,37 +63,37 @@ #include "timers.h" /*----------------------------------------------------------- -* Implementation of functions defined in portable.h for the PIC port. -*----------------------------------------------------------*/ + * Implementation of functions defined in portable.h for the PIC port. + *----------------------------------------------------------*/ /* Hardware setup for tick. */ -#define portTIMER_FOSC_SCALE ( ( uint32_t ) 4 ) +#define portTIMER_FOSC_SCALE ( ( uint32_t ) 4 ) /* Initial interrupt enable state for newly created tasks. This value is - * copied into INTCON when a task switches in for the first time. */ +copied into INTCON when a task switches in for the first time. */ #define portINITAL_INTERRUPT_STATE 0xc0 /* Just the bit within INTCON for the global interrupt flag. */ #define portGLOBAL_INTERRUPT_FLAG 0x80 /* Constant used for context switch macro when we require the interrupt - * enable state to be unchanged when the interrupted task is switched back in. */ +enable state to be unchanged when the interrupted task is switched back in. */ #define portINTERRUPTS_UNCHANGED 0x00 /* Some memory areas get saved as part of the task context. These memory - * area's get used by the compiler for temporary storage, especially when - * performing mathematical operations, or when using 32bit data types. This - * constant defines the size of memory area which must be saved. */ +area's get used by the compiler for temporary storage, especially when +performing mathematical operations, or when using 32bit data types. This +constant defines the size of memory area which must be saved. */ #define portCOMPILER_MANAGED_MEMORY_SIZE ( ( uint8_t ) 0x13 ) /* We require the address of the pxCurrentTCB variable, but don't want to know - * any details of its type. */ +any details of its type. */ typedef void TCB_t; extern volatile TCB_t * volatile pxCurrentTCB; /* IO port constants. */ -#define portBIT_SET ( ( uint8_t ) 1 ) -#define portBIT_CLEAR ( ( uint8_t ) 0 ) +#define portBIT_SET ( ( uint8_t ) 1 ) +#define portBIT_CLEAR ( ( uint8_t ) 0 ) /* * The serial port ISR's are defined in serial.c, but are called from portable @@ -136,7 +136,7 @@ static void prvLowInterrupt( void ); * * The compiler uses some locations at the bottom of the memory for temporary * storage during math and other computations. This is especially true if - * 32bit data types are used (as they are by the scheduler). The .tmpdata + * 32bit data types are utilized (as they are by the scheduler). The .tmpdata * and MATH_DATA sections have to be stored in there entirety as part of a task * context. This macro stores from data address 0x00 to * portCOMPILER_MANAGED_MEMORY_SIZE. This is sufficient for the demo @@ -144,214 +144,212 @@ static void prvLowInterrupt( void ); * this is sufficient for your needs. It is not clear whether this size is * fixed for all compilations or has the potential to be program specific. */ -#define portSAVE_CONTEXT( ucForcedInterruptFlags ) \ - { \ - _asm \ +#define portSAVE_CONTEXT( ucForcedInterruptFlags ) \ +{ \ + _asm \ /* Save the status and WREG registers first, as these will get modified \ - * by the operations below. */ \ - MOVFF WREG, PREINC1 \ - MOVFF STATUS, PREINC1 \ - /* Save the INTCON register with the appropriate bits forced if \ - * necessary - as described above. */ \ - MOVFF INTCON, WREG \ - IORLW ucForcedInterruptFlags \ - MOVFF WREG, PREINC1 \ - _endasm \ - \ - portDISABLE_INTERRUPTS(); \ - \ - _asm \ - /* Store the necessary registers to the stack. */ \ - MOVFF BSR, PREINC1 \ - MOVFF FSR2L, PREINC1 \ - MOVFF FSR2H, PREINC1 \ - MOVFF FSR0L, PREINC1 \ - MOVFF FSR0H, PREINC1 \ - MOVFF TABLAT, PREINC1 \ - MOVFF TBLPTRU, PREINC1 \ - MOVFF TBLPTRH, PREINC1 \ - MOVFF TBLPTRL, PREINC1 \ - MOVFF PRODH, PREINC1 \ - MOVFF PRODL, PREINC1 \ - MOVFF PCLATU, PREINC1 \ - MOVFF PCLATH, PREINC1 \ - /* Store the .tempdata and MATH_DATA areas as described above. */ \ - CLRF FSR0L, 0 \ - CLRF FSR0H, 0 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF POSTINC0, PREINC1 \ - MOVFF INDF0, PREINC1 \ - MOVFF FSR0L, PREINC1 \ - MOVFF FSR0H, PREINC1 \ - /* Store the hardware stack pointer in a temp register before we \ - * modify it. */ \ - MOVFF STKPTR, FSR0L \ - _endasm \ - \ - /* Store each address from the hardware stack. */ \ - while( STKPTR > ( uint8_t ) 0 ) \ - { \ - _asm \ - MOVFF TOSL, PREINC1 \ - MOVFF TOSH, PREINC1 \ - MOVFF TOSU, PREINC1 \ - POP \ - _endasm \ - } \ - \ - _asm \ - /* Store the number of addresses on the hardware stack (from the \ - * temporary register). */ \ - MOVFF FSR0L, PREINC1 \ - MOVF PREINC1, 1, 0 \ - _endasm \ - \ - /* Save the new top of the software stack in the TCB. */ \ - _asm \ - MOVFF pxCurrentTCB, FSR0L \ - MOVFF pxCurrentTCB + 1, FSR0H \ - MOVFF FSR1L, POSTINC0 \ - MOVFF FSR1H, POSTINC0 \ - _endasm \ - } + by the operations below. */ \ + MOVFF WREG, PREINC1 \ + MOVFF STATUS, PREINC1 \ + /* Save the INTCON register with the appropriate bits forced if \ + necessary - as described above. */ \ + MOVFF INTCON, WREG \ + IORLW ucForcedInterruptFlags \ + MOVFF WREG, PREINC1 \ + _endasm \ + \ + portDISABLE_INTERRUPTS(); \ + \ + _asm \ + /* Store the necessary registers to the stack. */ \ + MOVFF BSR, PREINC1 \ + MOVFF FSR2L, PREINC1 \ + MOVFF FSR2H, PREINC1 \ + MOVFF FSR0L, PREINC1 \ + MOVFF FSR0H, PREINC1 \ + MOVFF TABLAT, PREINC1 \ + MOVFF TBLPTRU, PREINC1 \ + MOVFF TBLPTRH, PREINC1 \ + MOVFF TBLPTRL, PREINC1 \ + MOVFF PRODH, PREINC1 \ + MOVFF PRODL, PREINC1 \ + MOVFF PCLATU, PREINC1 \ + MOVFF PCLATH, PREINC1 \ + /* Store the .tempdata and MATH_DATA areas as described above. */ \ + CLRF FSR0L, 0 \ + CLRF FSR0H, 0 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF POSTINC0, PREINC1 \ + MOVFF INDF0, PREINC1 \ + MOVFF FSR0L, PREINC1 \ + MOVFF FSR0H, PREINC1 \ + /* Store the hardware stack pointer in a temp register before we \ + modify it. */ \ + MOVFF STKPTR, FSR0L \ + _endasm \ + \ + /* Store each address from the hardware stack. */ \ + while( STKPTR > ( uint8_t ) 0 ) \ + { \ + _asm \ + MOVFF TOSL, PREINC1 \ + MOVFF TOSH, PREINC1 \ + MOVFF TOSU, PREINC1 \ + POP \ + _endasm \ + } \ + \ + _asm \ + /* Store the number of addresses on the hardware stack (from the \ + temporary register). */ \ + MOVFF FSR0L, PREINC1 \ + MOVF PREINC1, 1, 0 \ + _endasm \ + \ + /* Save the new top of the software stack in the TCB. */ \ + _asm \ + MOVFF pxCurrentTCB, FSR0L \ + MOVFF pxCurrentTCB + 1, FSR0H \ + MOVFF FSR1L, POSTINC0 \ + MOVFF FSR1H, POSTINC0 \ + _endasm \ +} /*-----------------------------------------------------------*/ /* * This is the reverse of portSAVE_CONTEXT. See portSAVE_CONTEXT for more * details. */ -#define portRESTORE_CONTEXT() \ - { \ - _asm \ - /* Set FSR0 to point to pxCurrentTCB->pxTopOfStack. */ \ - MOVFF pxCurrentTCB, FSR0L \ - MOVFF pxCurrentTCB + 1, FSR0H \ - \ - /* De-reference FSR0 to set the address it holds into FSR1. \ - * (i.e. *( pxCurrentTCB->pxTopOfStack ) ). */ \ - MOVFF POSTINC0, FSR1L \ - MOVFF POSTINC0, FSR1H \ - \ - /* How many return addresses are there on the hardware stack? Discard \ - * the first byte as we are pointing to the next free space. */ \ - MOVFF POSTDEC1, FSR0L \ - MOVFF POSTDEC1, FSR0L \ - _endasm \ - \ - /* Fill the hardware stack from our software stack. */ \ - STKPTR = 0; \ - \ - while( STKPTR < FSR0L ) \ - { \ - _asm \ - PUSH \ - MOVF POSTDEC1, 0, 0 \ - MOVWF TOSU, 0 \ - MOVF POSTDEC1, 0, 0 \ - MOVWF TOSH, 0 \ - MOVF POSTDEC1, 0, 0 \ - MOVWF TOSL, 0 \ - _endasm \ - } \ - \ - _asm \ - /* Restore the .tmpdata and MATH_DATA memory. */ \ - MOVFF POSTDEC1, FSR0H \ - MOVFF POSTDEC1, FSR0L \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, POSTDEC0 \ - MOVFF POSTDEC1, INDF0 \ - /* Restore the other registers forming the tasks context. */ \ - MOVFF POSTDEC1, PCLATH \ - MOVFF POSTDEC1, PCLATU \ - MOVFF POSTDEC1, PRODL \ - MOVFF POSTDEC1, PRODH \ - MOVFF POSTDEC1, TBLPTRL \ - MOVFF POSTDEC1, TBLPTRH \ - MOVFF POSTDEC1, TBLPTRU \ - MOVFF POSTDEC1, TABLAT \ - MOVFF POSTDEC1, FSR0H \ - MOVFF POSTDEC1, FSR0L \ - MOVFF POSTDEC1, FSR2H \ - MOVFF POSTDEC1, FSR2L \ - MOVFF POSTDEC1, BSR \ - /* The next byte is the INTCON register. Read this into WREG as some \ - * manipulation is required. */ \ - MOVFF POSTDEC1, WREG \ - _endasm \ - \ - /* From the INTCON register, only the interrupt enable bits form part \ - * of the tasks context. It is perfectly legitimate for another task to \ - * have modified any other bits. We therefore only restore the top two bits. \ - */ \ - if( WREG &portGLOBAL_INTERRUPT_FLAG ) \ - { \ - _asm \ - MOVFF POSTDEC1, STATUS \ - MOVFF POSTDEC1, WREG \ - /* Return enabling interrupts. */ \ - RETFIE 0 \ - _endasm \ - } \ - else \ - { \ - _asm \ - MOVFF POSTDEC1, STATUS \ - MOVFF POSTDEC1, WREG \ - /* Return without effecting interrupts. The context may have \ - * been saved from a critical region. */ \ - RETURN 0 \ - _endasm \ - } \ - } +#define portRESTORE_CONTEXT() \ +{ \ + _asm \ + /* Set FSR0 to point to pxCurrentTCB->pxTopOfStack. */ \ + MOVFF pxCurrentTCB, FSR0L \ + MOVFF pxCurrentTCB + 1, FSR0H \ + \ + /* De-reference FSR0 to set the address it holds into FSR1. \ + (i.e. *( pxCurrentTCB->pxTopOfStack ) ). */ \ + MOVFF POSTINC0, FSR1L \ + MOVFF POSTINC0, FSR1H \ + \ + /* How many return addresses are there on the hardware stack? Discard \ + the first byte as we are pointing to the next free space. */ \ + MOVFF POSTDEC1, FSR0L \ + MOVFF POSTDEC1, FSR0L \ + _endasm \ + \ + /* Fill the hardware stack from our software stack. */ \ + STKPTR = 0; \ + \ + while( STKPTR < FSR0L ) \ + { \ + _asm \ + PUSH \ + MOVF POSTDEC1, 0, 0 \ + MOVWF TOSU, 0 \ + MOVF POSTDEC1, 0, 0 \ + MOVWF TOSH, 0 \ + MOVF POSTDEC1, 0, 0 \ + MOVWF TOSL, 0 \ + _endasm \ + } \ + \ + _asm \ + /* Restore the .tmpdata and MATH_DATA memory. */ \ + MOVFF POSTDEC1, FSR0H \ + MOVFF POSTDEC1, FSR0L \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, POSTDEC0 \ + MOVFF POSTDEC1, INDF0 \ + /* Restore the other registers forming the tasks context. */ \ + MOVFF POSTDEC1, PCLATH \ + MOVFF POSTDEC1, PCLATU \ + MOVFF POSTDEC1, PRODL \ + MOVFF POSTDEC1, PRODH \ + MOVFF POSTDEC1, TBLPTRL \ + MOVFF POSTDEC1, TBLPTRH \ + MOVFF POSTDEC1, TBLPTRU \ + MOVFF POSTDEC1, TABLAT \ + MOVFF POSTDEC1, FSR0H \ + MOVFF POSTDEC1, FSR0L \ + MOVFF POSTDEC1, FSR2H \ + MOVFF POSTDEC1, FSR2L \ + MOVFF POSTDEC1, BSR \ + /* The next byte is the INTCON register. Read this into WREG as some \ + manipulation is required. */ \ + MOVFF POSTDEC1, WREG \ + _endasm \ + \ + /* From the INTCON register, only the interrupt enable bits form part \ + of the tasks context. It is perfectly legitimate for another task to \ + have modified any other bits. We therefore only restore the top two bits. \ + */ \ + if( WREG & portGLOBAL_INTERRUPT_FLAG ) \ + { \ + _asm \ + MOVFF POSTDEC1, STATUS \ + MOVFF POSTDEC1, WREG \ + /* Return enabling interrupts. */ \ + RETFIE 0 \ + _endasm \ + } \ + else \ + { \ + _asm \ + MOVFF POSTDEC1, STATUS \ + MOVFF POSTDEC1, WREG \ + /* Return without effecting interrupts. The context may have \ + been saved from a critical region. */ \ + RETURN 0 \ + _endasm \ + } \ +} /*-----------------------------------------------------------*/ /* * See header file for description. */ -StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, - TaskFunction_t pxCode, - void * pvParameters ) +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) { - uint32_t ulAddress; - uint8_t ucBlock; +uint32_t ulAddress; +uint8_t ucBlock; /* Place a few bytes of known values on the bottom of the stack. - * This is just useful for debugging. */ + This is just useful for debugging. */ *pxTopOfStack = 0x11; pxTopOfStack++; @@ -362,10 +360,10 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, /* Simulate how the stack would look after a call to vPortYield() generated - * by the compiler. - * - * First store the function parameters. This is where the task will expect to - * find them when it starts running. */ + by the compiler. + + First store the function parameters. This is where the task will expect to + find them when it starts running. */ ulAddress = ( uint32_t ) pvParameters; *pxTopOfStack = ( StackType_t ) ( ulAddress & ( uint32_t ) 0x00ff ); pxTopOfStack++; @@ -375,9 +373,9 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, pxTopOfStack++; /* Next we just leave a space. When a context is saved the stack pointer - * is incremented before it is used so as not to corrupt whatever the stack - * pointer is actually pointing to. This is especially necessary during - * function epilogue code generated by the compiler. */ + is incremented before it is used so as not to corrupt whatever the stack + pointer is actually pointing to. This is especially necessary during + function epilogue code generated by the compiler. */ *pxTopOfStack = 0x44; pxTopOfStack++; @@ -447,7 +445,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, pxTopOfStack++; /* The only function return address so far is the address of the - * task. */ + task. */ ulAddress = ( uint32_t ) pxCode; /* TOS low. */ @@ -465,7 +463,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, pxTopOfStack++; /* Store the number of return addresses on the hardware stack - so far only - * the address of the task entry point. */ + the address of the task entry point. */ *pxTopOfStack = ( StackType_t ) 1; pxTopOfStack++; @@ -492,8 +490,8 @@ BaseType_t xPortStartScheduler( void ) void vPortEndScheduler( void ) { /* It is unlikely that the scheduler for the PIC port will get stopped - * once running. If required disable the tick interrupt here, then return - * to xPortStartScheduler(). */ + once running. If required disable the tick interrupt here, then return + to xPortStartScheduler(). */ } /*-----------------------------------------------------------*/ @@ -505,7 +503,7 @@ void vPortEndScheduler( void ) void vPortYield( void ) { /* This can get called with interrupts either enabled or disabled. We - * will save the INTCON register with the interrupt enable bits unmodified. */ + will save the INTCON register with the interrupt enable bits unmodified. */ portSAVE_CONTEXT( portINTERRUPTS_UNCHANGED ); /* Switch to the highest priority task that is ready to run. */ @@ -526,7 +524,7 @@ static void prvLowInterrupt( void ) if( PIR1bits.CCP1IF ) { _asm - goto prvTickISR + goto prvTickISR _endasm } @@ -534,7 +532,7 @@ static void prvLowInterrupt( void ) if( PIR1bits.RCIF ) { _asm - goto vSerialRxISR + goto vSerialRxISR _endasm } @@ -544,7 +542,7 @@ static void prvLowInterrupt( void ) if( PIE1bits.TXIE ) { _asm - goto vSerialTxISR + goto vSerialTxISR _endasm } } @@ -562,7 +560,7 @@ static void prvLowInterrupt( void ) static void prvTickISR( void ) { /* Interrupts must have been enabled for the ISR to fire, so we have to - * save the context with interrupts enabled. */ + save the context with interrupts enabled. */ portSAVE_CONTEXT( portGLOBAL_INTERRUPT_FLAG ); PIR1bits.CCP1IF = 0; @@ -582,16 +580,16 @@ static void prvTickISR( void ) */ static void prvSetupTimerInterrupt( void ) { - const uint32_t ulConstCompareValue = ( ( configCPU_CLOCK_HZ / portTIMER_FOSC_SCALE ) / configTICK_RATE_HZ ); - uint32_t ulCompareValue; - uint8_t ucByte; +const uint32_t ulConstCompareValue = ( ( configCPU_CLOCK_HZ / portTIMER_FOSC_SCALE ) / configTICK_RATE_HZ ); +uint32_t ulCompareValue; +uint8_t ucByte; /* Interrupts are disabled when this function is called. - * - * Setup CCP1 to provide the tick interrupt using a compare match on timer - * 1. - * - * Clear the time count then setup timer. */ + + Setup CCP1 to provide the tick interrupt using a compare match on timer + 1. + + Clear the time count then setup timer. */ TMR1H = ( uint8_t ) 0x00; TMR1L = ( uint8_t ) 0x00; @@ -608,10 +606,10 @@ static void prvSetupTimerInterrupt( void ) PIE1bits.CCP1IE = portBIT_SET; /*< Interrupt enable. */ /* We are only going to use the global interrupt bit, so set the peripheral - * bit to true. */ + bit to true. */ INTCONbits.GIEL = portBIT_SET; /* Provided library function for setting up the timer that will produce the - * tick. */ + tick. */ OpenTimer1( T1_16BIT_RW & T1_SOURCE_INT & T1_PS_1_1 & T1_CCP1_T3_CCP2 ); } diff --git a/portable/MPLAB/PIC18F/portmacro.h b/portable/MPLAB/PIC18F/portmacro.h index 11f21cfc9e5..80e83ed9efa 100644 --- a/portable/MPLAB/PIC18F/portmacro.h +++ b/portable/MPLAB/PIC18F/portmacro.h @@ -40,23 +40,23 @@ */ /* Type definitions. */ -#define portCHAR char -#define portFLOAT float -#define portDOUBLE double -#define portLONG long -#define portSHORT int -#define portSTACK_TYPE uint8_t -#define portBASE_TYPE char +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT int +#define portSTACK_TYPE uint8_t +#define portBASE_TYPE char -typedef portSTACK_TYPE StackType_t; -typedef signed char BaseType_t; -typedef unsigned char UBaseType_t; +typedef portSTACK_TYPE StackType_t; +typedef signed char BaseType_t; +typedef unsigned char UBaseType_t; -#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff -#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; +#if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -64,10 +64,10 @@ typedef unsigned char UBaseType_t; /*-----------------------------------------------------------*/ /* Hardware specifics. */ -#define portBYTE_ALIGNMENT 1 -#define portGLOBAL_INT_ENABLE_BIT 0x80 -#define portSTACK_GROWTH 1 -#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 1 +#define portGLOBAL_INT_ENABLE_BIT 0x80 +#define portSTACK_GROWTH 1 +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) /*-----------------------------------------------------------*/ /* Critical section management. */ @@ -75,32 +75,30 @@ typedef unsigned char UBaseType_t; #define portENABLE_INTERRUPTS() INTCONbits.GIEH = 1; /* Push the INTCON register onto the stack, then disable interrupts. */ -#define portENTER_CRITICAL() \ - POSTINC1 = INTCON; \ - INTCONbits.GIEH = 0; +#define portENTER_CRITICAL() POSTINC1 = INTCON; \ + INTCONbits.GIEH = 0; /* Retrieve the INTCON register from the stack, and enable interrupts - * if they were saved as being enabled. Don't modify any other bits - * within the INTCON register as these may have legitimately have been - * modified within the critical region. */ -#define portEXIT_CRITICAL() \ - _asm \ - MOVF POSTDEC1, 1, 0 \ - _endasm \ - if( INDF1 & portGLOBAL_INT_ENABLE_BIT ) \ - { \ - portENABLE_INTERRUPTS(); \ - } +if they were saved as being enabled. Don't modify any other bits +within the INTCON register as these may have legitimately have been +modified within the critical region. */ +#define portEXIT_CRITICAL() _asm \ + MOVF POSTDEC1, 1, 0 \ + _endasm \ + if( INDF1 & portGLOBAL_INT_ENABLE_BIT ) \ + { \ + portENABLE_INTERRUPTS(); \ + } /*-----------------------------------------------------------*/ /* Task utilities. */ extern void vPortYield( void ); -#define portYIELD() vPortYield() +#define portYIELD() vPortYield() /*-----------------------------------------------------------*/ /* Task function macros as described on the FreeRTOS.org WEB site. */ -#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) -#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) /*-----------------------------------------------------------*/ /* Required by the kernel aware debugger. */ @@ -109,9 +107,8 @@ extern void vPortYield( void ); #endif -#define portNOP() \ - _asm \ - NOP \ - _endasm +#define portNOP() _asm \ + NOP \ + _endasm #endif /* PORTMACRO_H */ diff --git a/portable/MPLAB/PIC24_dsPIC/port.c b/portable/MPLAB/PIC24_dsPIC/port.c index dfbce112882..6f23fe8a2f4 100644 --- a/portable/MPLAB/PIC24_dsPIC/port.c +++ b/portable/MPLAB/PIC24_dsPIC/port.c @@ -27,38 +27,38 @@ */ /* - * Changes from V4.2.1 - * - + Introduced the configKERNEL_INTERRUPT_PRIORITY definition. - */ + Changes from V4.2.1 + + + Introduced the configKERNEL_INTERRUPT_PRIORITY definition. +*/ /*----------------------------------------------------------- -* Implementation of functions defined in portable.h for the PIC24 port. -*----------------------------------------------------------*/ + * 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 +#define portBIT_SET 1 +#define portTIMER_PRESCALE 8 +#define portINITIAL_SR 0 /* Defined for backward compatability with project created prior to - * FreeRTOS.org V4.3.0. */ +FreeRTOS.org V4.3.0. */ #ifndef configKERNEL_INTERRUPT_PRIORITY - #define configKERNEL_INTERRUPT_PRIORITY 1 + #define configKERNEL_INTERRUPT_PRIORITY 1 #endif /* Use _T1Interrupt as the interrupt handler name if the application writer has - * not provided their own. */ +not provided their own. */ #ifndef configTICK_INTERRUPT_HANDLER - #define configTICK_INTERRUPT_HANDLER _T1Interrupt + #define configTICK_INTERRUPT_HANDLER _T1Interrupt #endif /* configTICK_INTERRUPT_HANDLER */ /* The program counter is only 23 bits. */ -#define portUNUSED_PR_BITS 0x7f +#define portUNUSED_PR_BITS 0x7f /* Records the nesting depth of calls to portENTER_CRITICAL(). */ UBaseType_t uxCriticalNesting = 0xef; @@ -67,89 +67,89 @@ UBaseType_t uxCriticalNesting = 0xef; #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 -#if defined( __PIC24E__ ) || defined( __PIC24F__ ) || defined( __PIC24FK__ ) || defined( __PIC24H__ ) +#if defined( __PIC24E__ ) || defined ( __PIC24F__ ) || defined( __PIC24FK__ ) || defined( __PIC24H__ ) #ifdef __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 DSWPAG \n" \ - "POP DSRPAG \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 " ); + #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 DSWPAG \n" \ + "POP DSRPAG \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 " ); #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__ */ + #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__ */ #endif /* defined( __PIC24E__ ) || defined ( __PIC24F__ ) || defined( __PIC24FK__ ) || defined( __PIC24H__ ) */ #if defined( __dsPIC30F__ ) || defined( __dsPIC33F__ ) - #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 " ); + #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 /* defined( __dsPIC30F__ ) || defined( __dsPIC33F__ ) */ #ifndef portRESTORE_CONTEXT #error Unrecognised device selected -/* Note: dsPIC parts with EDS are not supported as there is no easy way to - * recover the hardware stacked copies for DOCOUNT, DOHIGH, DOLOW. */ + /* Note: dsPIC parts with EDS are not supported as there is no easy way to + recover the hardware stacked copies for DOCOUNT, DOHIGH, DOLOW. */ #endif /* @@ -160,58 +160,56 @@ void vApplicationSetupTickTimerInterrupt( void ); /* * See header file for description. */ -StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, - TaskFunction_t pxCode, - void * pvParameters ) +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) { - uint16_t usCode; - UBaseType_t i; +uint16_t usCode; +UBaseType_t i; - const StackType_t xInitialStack[] = - { - 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. */ - #if defined( __dsPIC30F__ ) || defined( __dsPIC33F__ ) - 0x0202, /* ACCAL */ - 0x0303, /* ACCAH */ - 0x0404, /* ACCAU */ - 0x0505, /* ACCBL */ - 0x0606, /* ACCBH */ - 0x0707, /* ACCBU */ - 0x0808, /* DCOUNT */ - 0x090a, /* DOSTARTL */ - 0x1010, /* DOSTARTH */ - 0x1110, /* DOENDL */ - 0x1212, /* DOENDH */ - #endif /* if defined( __dsPIC30F__ ) || defined( __dsPIC33F__ ) */ - }; +const StackType_t xInitialStack[] = +{ + 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. */ + #if defined( __dsPIC30F__ ) || defined( __dsPIC33F__ ) + 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. */ + + Save the low bytes of the program counter. */ usCode = ( uint16_t ) pxCode; *pxTopOfStack = ( StackType_t ) usCode; pxTopOfStack++; /* Save the high byte of the program counter. This will always be zero - * here as it is passed in a 16bit pointer. If the address is greater than - * 16 bits then the pointer will point to a jump table. */ + here as it is passed in a 16bit pointer. If the address is greater than + 16 bits then the pointer will point to a jump table. */ *pxTopOfStack = ( StackType_t ) 0; pxTopOfStack++; @@ -232,7 +230,7 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, *pxTopOfStack = CORCON; pxTopOfStack++; - #if defined( __HAS_EDS__ ) + #if defined(__HAS_EDS__) *pxTopOfStack = DSRPAG; pxTopOfStack++; *pxTopOfStack = DSWPAG; @@ -269,7 +267,7 @@ BaseType_t xPortStartScheduler( void ) void vPortEndScheduler( void ) { /* Not implemented in ports where there is nothing to return to. - * Artificially force an assert. */ + Artificially force an assert. */ configASSERT( uxCriticalNesting == 1000UL ); } /*-----------------------------------------------------------*/ @@ -277,9 +275,9 @@ void vPortEndScheduler( void ) /* * Setup a timer for a regular tick. */ -__attribute__( ( weak ) ) void vApplicationSetupTickTimerInterrupt( void ) +__attribute__(( weak )) void vApplicationSetupTickTimerInterrupt( void ) { - const uint32_t ulCompareMatch = ( ( configCPU_CLOCK_HZ / portTIMER_PRESCALE ) / configTICK_RATE_HZ ) - 1; +const uint32_t ulCompareMatch = ( ( configCPU_CLOCK_HZ / portTIMER_PRESCALE ) / configTICK_RATE_HZ ) - 1; /* Prescale of 8. */ T1CON = 0; @@ -316,7 +314,6 @@ void vPortExitCritical( void ) { configASSERT( uxCriticalNesting ); uxCriticalNesting--; - if( uxCriticalNesting == 0 ) { portENABLE_INTERRUPTS(); @@ -324,7 +321,7 @@ void vPortExitCritical( void ) } /*-----------------------------------------------------------*/ -void __attribute__( ( __interrupt__, auto_psv ) ) configTICK_INTERRUPT_HANDLER( void ) +void __attribute__((__interrupt__, auto_psv)) configTICK_INTERRUPT_HANDLER( void ) { /* Clear the timer interrupt. */ IFS0bits.T1IF = 0; diff --git a/portable/MPLAB/PIC24_dsPIC/portmacro.h b/portable/MPLAB/PIC24_dsPIC/portmacro.h index 7590d7c7458..f01ee9c9b43 100644 --- a/portable/MPLAB/PIC24_dsPIC/portmacro.h +++ b/portable/MPLAB/PIC24_dsPIC/portmacro.h @@ -46,63 +46,61 @@ */ /* Type definitions. */ -#define portCHAR char -#define portFLOAT float -#define portDOUBLE double -#define portLONG long -#define portSHORT short -#define portSTACK_TYPE uint16_t -#define portBASE_TYPE short -#define portPOINTER_SIZE_TYPE size_t -#define SIZE_MAX ( ( size_t ) -1 ) - -typedef portSTACK_TYPE StackType_t; -typedef short BaseType_t; -typedef unsigned short UBaseType_t; - -#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff - +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint16_t +#define portBASE_TYPE short +#define portPOINTER_SIZE_TYPE size_t +#define SIZE_MAX ( ( size_t ) -1 ) + +typedef portSTACK_TYPE StackType_t; +typedef short BaseType_t; +typedef unsigned short UBaseType_t; + +#if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff /* 16-bit tick type on a 16-bit architecture, so reads of the tick count do * not need to be guarded with a critical section. */ - #define portTICK_TYPE_IS_ATOMIC 1 -#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL + #define portTICK_TYPE_IS_ATOMIC 1 +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. #endif /*-----------------------------------------------------------*/ /* Hardware specifics. */ -#define portBYTE_ALIGNMENT 2 -#define portSTACK_GROWTH 1 -#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 2 +#define portSTACK_GROWTH 1 +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) /*-----------------------------------------------------------*/ /* Critical section management. */ #define portDISABLE_INTERRUPTS() SET_CPU_IPL( configKERNEL_INTERRUPT_PRIORITY ); __asm volatile ( "NOP" ) #define portENABLE_INTERRUPTS() SET_CPU_IPL( 0 ) -/* Note that exiting a critical section will set the IPL bits to 0, no - * matter what their value was prior to entering the critical section. */ +/* Note that exiting a critical sectino will set the IPL bits to 0, no matter +what their value was prior to entering the critical section. */ extern void vPortEnterCritical( void ); extern void vPortExitCritical( void ); -#define portENTER_CRITICAL() vPortEnterCritical() -#define portEXIT_CRITICAL() vPortExitCritical() +#define portENTER_CRITICAL() vPortEnterCritical() +#define portEXIT_CRITICAL() vPortExitCritical() /*-----------------------------------------------------------*/ /* Task utilities. */ extern void vPortYield( void ); -#define portYIELD() \ - asm volatile ( "CALL _vPortYield \n" \ - "NOP " ); +#define portYIELD() asm volatile ( "CALL _vPortYield \n" \ + "NOP " ); /*-----------------------------------------------------------*/ /* Task function macros as described on the FreeRTOS.org WEB site. */ -#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) -#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) /*-----------------------------------------------------------*/ /* Required by the kernel aware debugger. */ @@ -110,7 +108,7 @@ extern void vPortYield( void ); #define portREMOVE_STATIC_QUALIFIER #endif -#define portNOP() asm volatile ( "NOP" ) +#define portNOP() asm volatile ( "NOP" ) /* *INDENT-OFF* */ #ifdef __cplusplus diff --git a/portable/MPLAB/PIC32MEC14xx/ISR_Support.h b/portable/MPLAB/PIC32MEC14xx/ISR_Support.h index eda3e13e718..d2fa5bb4dba 100644 --- a/portable/MPLAB/PIC32MEC14xx/ISR_Support.h +++ b/portable/MPLAB/PIC32MEC14xx/ISR_Support.h @@ -28,187 +28,187 @@ #include "FreeRTOSConfig.h" -#define portCONTEXT_SIZE 132 -#define portEPC_STACK_LOCATION 124 -#define portSTATUS_STACK_LOCATION 128 +#define portCONTEXT_SIZE 132 +#define portEPC_STACK_LOCATION 124 +#define portSTATUS_STACK_LOCATION 128 #ifdef __LANGUAGE_ASSEMBLY__ /******************************************************************/ - .macro portSAVE_CONTEXT +.macro portSAVE_CONTEXT -/* Make room for the context. First save the current status so it can be - * manipulated, and the cause and EPC registers so their original values are - * captured. */ - mfc0 k0, _CP0_CAUSE - addiu sp, sp, -portCONTEXT_SIZE - mfc0 k1, _CP0_STATUS + /* Make room for the context. First save the current status so it can be + manipulated, and the cause and EPC registers so their original values are + captured. */ + mfc0 k0, _CP0_CAUSE + addiu sp, sp, -portCONTEXT_SIZE + mfc0 k1, _CP0_STATUS -/* Also save s6 and s5 so they can be used. Any nesting interrupts should - * maintain the values of these registers across the ISR. */ - sw s6, 44 ( sp ) - sw s5, 40 ( sp ) - sw k1, portSTATUS_STACK_LOCATION( sp ) + /* Also save s6 and s5 so they can be used. Any nesting interrupts should + maintain the values of these registers across the ISR. */ + sw s6, 44(sp) + sw s5, 40(sp) + sw k1, portSTATUS_STACK_LOCATION(sp) -/* Prepare to enable interrupts above the current priority. - * k0 = k0 >> 10. Moves RIPL[17:10] to [7:0] */ - srl k0, k0, 0xa + /* Prepare to enable interrupts above the current priority. + k0 = k0 >> 10. Moves RIPL[17:10] to [7:0] */ + srl k0, k0, 0xa -/* Insert bit field. 7 bits k0[6:0] to k1[16:10] */ - ins k1, k0, 10, 7 + /* Insert bit field. 7 bits k0[6:0] to k1[16:10] */ + ins k1, k0, 10, 7 -/* Sets CP0.Status.IPL = CP0.Cause.RIPL - * Copy the MSB of the IPL, but it would be an error if it was set anyway. */ - srl k0, k0, 0x7 + /* Sets CP0.Status.IPL = CP0.Cause.RIPL + Copy the MSB of the IPL, but it would be an error if it was set anyway. */ + srl k0, k0, 0x7 -/* MSB of IPL is bit[18] of CP0.Status */ - ins k1, k0, 18, 1 + /* MSB of IPL is bit[18] of CP0.Status */ + ins k1, k0, 18, 1 -/* CP0.Status[5:1] = 0 b[5]=Rsvd, b[4]=UM, - * b[3]=Rsvd, b[2]=ERL, b[1]=EXL - * Setting EXL=0 allows higher priority interrupts - * to preempt this handler */ - ins k1, zero, 1, 4 + /* CP0.Status[5:1] = 0 b[5]=Rsvd, b[4]=UM, + b[3]=Rsvd, b[2]=ERL, b[1]=EXL + Setting EXL=0 allows higher priority interrupts + to preempt this handler */ + ins k1, zero, 1, 4 -/* s5 is used as the frame pointer. */ - add s5, zero, sp + /* s5 is used as the frame pointer. */ + add s5, zero, sp -/* Check the nesting count value. */ - la k0, uxInterruptNesting - lw s6, ( k0 ) + /* Check the nesting count value. */ + la k0, uxInterruptNesting + lw s6, (k0) -/* If the nesting count is 0 then swap to the the system stack, otherwise - * the system stack is already being used. */ - bne s6, zero, 1f + /* If the nesting count is 0 then swap to the the system stack, otherwise + the system stack is already being used. */ + bne s6, zero, 1f nop -/* Swap to the system stack. */ - la sp, xISRStackTop - lw sp, ( sp ) - -/* Increment and save the nesting count. */ - 1 : addiu s6, s6, 1 - sw s6, 0 ( k0 ) - -/* s6 holds the EPC value, this is saved after interrupts are re-enabled. */ - mfc0 s6, _CP0_EPC - -/* Re-enable interrupts. */ - mtc0 k1, _CP0_STATUS - -/* Save the context into the space just created. s6 is saved again - * here as it now contains the EPC value. No other s registers need be - * saved. */ - sw ra, 120 ( s5 ) /* Return address (RA=R31) */ - sw s8, 116 ( s5 ) /* Frame Pointer (FP=R30) */ - sw t9, 112 ( s5 ) - sw t8, 108 ( s5 ) - sw t7, 104 ( s5 ) - sw t6, 100 ( s5 ) - sw t5, 96 ( s5 ) - sw t4, 92 ( s5 ) - sw t3, 88 ( s5 ) - sw t2, 84 ( s5 ) - sw t1, 80 ( s5 ) - sw t0, 76 ( s5 ) - sw a3, 72 ( s5 ) - sw a2, 68 ( s5 ) - sw a1, 64 ( s5 ) - sw a0, 60 ( s5 ) - sw v1, 56 ( s5 ) - sw v0, 52 ( s5 ) - sw s6, portEPC_STACK_LOCATION( s5 ) - sw $1, 16 ( s5 ) - -/* MEC14xx does not have DSP, removed 7 words */ - mfhi s6 - sw s6, 12 ( s5 ) - mflo s6 - sw s6, 8 ( s5 ) - -/* Update the task stack pointer value if nesting is zero. */ - la s6, uxInterruptNesting - lw s6, ( s6 ) - addiu s6, s6, -1 - bne s6, zero, 1f + /* Swap to the system stack. */ + la sp, xISRStackTop + lw sp, (sp) + + /* Increment and save the nesting count. */ +1: addiu s6, s6, 1 + sw s6, 0(k0) + + /* s6 holds the EPC value, this is saved after interrupts are re-enabled. */ + mfc0 s6, _CP0_EPC + + /* Re-enable interrupts. */ + mtc0 k1, _CP0_STATUS + + /* Save the context into the space just created. s6 is saved again + here as it now contains the EPC value. No other s registers need be + saved. */ + sw ra, 120(s5) /* Return address (RA=R31) */ + sw s8, 116(s5) /* Frame Pointer (FP=R30) */ + sw t9, 112(s5) + sw t8, 108(s5) + sw t7, 104(s5) + sw t6, 100(s5) + sw t5, 96(s5) + sw t4, 92(s5) + sw t3, 88(s5) + sw t2, 84(s5) + sw t1, 80(s5) + sw t0, 76(s5) + sw a3, 72(s5) + sw a2, 68(s5) + sw a1, 64(s5) + sw a0, 60(s5) + sw v1, 56(s5) + sw v0, 52(s5) + sw s6, portEPC_STACK_LOCATION(s5) + sw $1, 16(s5) + + /* MEC14xx does not have DSP, removed 7 words */ + mfhi s6 + sw s6, 12(s5) + mflo s6 + sw s6, 8(s5) + + /* Update the task stack pointer value if nesting is zero. */ + la s6, uxInterruptNesting + lw s6, (s6) + addiu s6, s6, -1 + bne s6, zero, 1f nop -/* Save the stack pointer. */ - la s6, uxSavedTaskStackPointer - sw s5, ( s6 ) - 1 : + /* Save the stack pointer. */ + la s6, uxSavedTaskStackPointer + sw s5, (s6) +1: .endm /******************************************************************/ - .macro portRESTORE_CONTEXT - -/* Restore the stack pointer from the TCB. This is only done if the - * nesting count is 1. */ - la s6, uxInterruptNesting - lw s6, ( s6 ) - addiu s6, s6, -1 - bne s6, zero, 1f +.macro portRESTORE_CONTEXT + + /* Restore the stack pointer from the TCB. This is only done if the + nesting count is 1. */ + la s6, uxInterruptNesting + lw s6, (s6) + addiu s6, s6, -1 + bne s6, zero, 1f nop - la s6, uxSavedTaskStackPointer - lw s5, ( s6 ) - -/* Restore the context. - * MCHP MEC14xx does not include DSP */ - 1 : - lw s6, 8 ( s5 ) - mtlo s6 - lw s6, 12 ( s5 ) - mthi s6 - lw $1, 16 ( s5 ) - -/* s6 is loaded as it was used as a scratch register and therefore saved - * as part of the interrupt context. */ - lw s6, 44 ( s5 ) - lw v0, 52 ( s5 ) - lw v1, 56 ( s5 ) - lw a0, 60 ( s5 ) - lw a1, 64 ( s5 ) - lw a2, 68 ( s5 ) - lw a3, 72 ( s5 ) - lw t0, 76 ( s5 ) - lw t1, 80 ( s5 ) - lw t2, 84 ( s5 ) - lw t3, 88 ( s5 ) - lw t4, 92 ( s5 ) - lw t5, 96 ( s5 ) - lw t6, 100 ( s5 ) - lw t7, 104 ( s5 ) - lw t8, 108 ( s5 ) - lw t9, 112 ( s5 ) - lw s8, 116 ( s5 ) - lw ra, 120 ( s5 ) - -/* Protect access to the k registers, and others. */ + la s6, uxSavedTaskStackPointer + lw s5, (s6) + + /* Restore the context. + MCHP MEC14xx does not include DSP */ +1: + lw s6, 8(s5) + mtlo s6 + lw s6, 12(s5) + mthi s6 + lw $1, 16(s5) + + /* s6 is loaded as it was used as a scratch register and therefore saved + as part of the interrupt context. */ + lw s6, 44(s5) + lw v0, 52(s5) + lw v1, 56(s5) + lw a0, 60(s5) + lw a1, 64(s5) + lw a2, 68(s5) + lw a3, 72(s5) + lw t0, 76(s5) + lw t1, 80(s5) + lw t2, 84(s5) + lw t3, 88(s5) + lw t4, 92(s5) + lw t5, 96(s5) + lw t6, 100(s5) + lw t7, 104(s5) + lw t8, 108(s5) + lw t9, 112(s5) + lw s8, 116(s5) + lw ra, 120(s5) + + /* Protect access to the k registers, and others. */ di ehb -/* Decrement the nesting count. */ - la k0, uxInterruptNesting - lw k1, ( k0 ) - addiu k1, k1, -1 - sw k1, 0 ( k0 ) + /* Decrement the nesting count. */ + la k0, uxInterruptNesting + lw k1, (k0) + addiu k1, k1, -1 + sw k1, 0(k0) - lw k0, portSTATUS_STACK_LOCATION( s5 ) - lw k1, portEPC_STACK_LOCATION( s5 ) + lw k0, portSTATUS_STACK_LOCATION(s5) + lw k1, portEPC_STACK_LOCATION(s5) -/* Leave the stack in its original state. First load sp from s5, then - * restore s5 from the stack. */ - add sp, zero, s5 - lw s5, 40 ( sp ) - addiu sp, sp, portCONTEXT_SIZE + /* Leave the stack in its original state. First load sp from s5, then + restore s5 from the stack. */ + add sp, zero, s5 + lw s5, 40(sp) + addiu sp, sp, portCONTEXT_SIZE - mtc0 k0, _CP0_STATUS - mtc0 k1, _CP0_EPC + mtc0 k0, _CP0_STATUS + mtc0 k1, _CP0_EPC ehb eret nop - .endm + .endm #endif /* #ifdef __LANGUAGE_ASSEMBLY__ */ diff --git a/portable/MPLAB/PIC32MEC14xx/port.c b/portable/MPLAB/PIC32MEC14xx/port.c index 5eb6e567bdb..ebe9bdb7c0f 100644 --- a/portable/MPLAB/PIC32MEC14xx/port.c +++ b/portable/MPLAB/PIC32MEC14xx/port.c @@ -27,8 +27,8 @@ */ /*----------------------------------------------------------- -* Implementation of functions defined in portable.h for the PIC32MEC14xx port. -*----------------------------------------------------------*/ + * Implementation of functions defined in portable.h for the PIC32MEC14xx port. + *----------------------------------------------------------*/ /* Scheduler include files. */ #include "FreeRTOS.h" @@ -38,57 +38,57 @@ #include #include -#if !defined( __MEC__ ) +#if !defined(__MEC__) #error This port is designed to work with XC32 on MEC14xx. Please update your C compiler version or settings. #endif -#if ( ( configMAX_SYSCALL_INTERRUPT_PRIORITY >= 0x7 ) || ( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 ) ) +#if( ( configMAX_SYSCALL_INTERRUPT_PRIORITY >= 0x7 ) || ( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 ) ) #error configMAX_SYSCALL_INTERRUPT_PRIORITY must be less than 7 and greater than 0 #endif /* Bits within various registers. */ -#define portIE_BIT ( 0x00000001 ) -#define portEXL_BIT ( 0x00000002 ) +#define portIE_BIT ( 0x00000001 ) +#define portEXL_BIT ( 0x00000002 ) /* The EXL bit is set to ensure interrupts do not occur while the context of - * the first task is being restored. MEC14xx does not have DSP HW. */ -#define portINITIAL_SR ( portIE_BIT | portEXL_BIT ) +the first task is being restored. MEC14xx does not have DSP HW. */ +#define portINITIAL_SR ( portIE_BIT | portEXL_BIT ) /* MEC14xx RTOS Timer MMCR's. */ -#define portMMCR_RTMR_PRELOAD *( ( volatile uint32_t * ) ( 0xA0007404ul ) ) -#define portMMCR_RTMR_CONTROL *( ( volatile uint32_t * ) ( 0xA0007408ul ) ) +#define portMMCR_RTMR_PRELOAD *((volatile uint32_t *)(0xA0007404ul)) +#define portMMCR_RTMR_CONTROL *((volatile uint32_t *)(0xA0007408ul)) /* MEC14xx JTVIC external interrupt controller is mapped to M14K closely-coupled - * peripheral space. */ -#define portGIRQ23_RTOS_TIMER_BITPOS ( 4 ) -#define portGIRQ23_RTOS_TIMER_MASK ( 1ul << ( portGIRQ23_RTOS_TIMER_BITPOS ) ) -#define portMMCR_JTVIC_GIRQ23_SRC *( ( volatile uint32_t * ) ( 0xBFFFC0F0ul ) ) -#define portMMCR_JTVIC_GIRQ23_SETEN *( ( volatile uint32_t * ) ( 0xBFFFC0F4ul ) ) -#define portMMCR_JTVIC_GIRQ23_PRIA *( ( volatile uint32_t * ) ( 0xBFFFC3F0ul ) ) +peripheral space. */ +#define portGIRQ23_RTOS_TIMER_BITPOS ( 4 ) +#define portGIRQ23_RTOS_TIMER_MASK ( 1ul << ( portGIRQ23_RTOS_TIMER_BITPOS ) ) +#define portMMCR_JTVIC_GIRQ23_SRC *((volatile uint32_t *)(0xBFFFC0F0ul)) +#define portMMCR_JTVIC_GIRQ23_SETEN *((volatile uint32_t *)(0xBFFFC0F4ul)) +#define portMMCR_JTVIC_GIRQ23_PRIA *((volatile uint32_t *)(0xBFFFC3F0ul)) /* MIPS Software Interrupts are routed through JTVIC GIRQ24 */ -#define portGIRQ24_M14K_SOFTIRQ0_BITPOS ( 1 ) -#define portGIRQ24_M14K_SOFTIRQ0_MASK ( 1ul << ( portGIRQ24_M14K_SOFTIRQ0_BITPOS ) ) -#define portMMCR_JTVIC_GIRQ24_SRC *( ( volatile uint32_t * ) ( 0xBFFFC100ul ) ) -#define portMMCR_JTVIC_GIRQ24_SETEN *( ( volatile uint32_t * ) ( 0xBFFFC104ul ) ) -#define portMMCR_JTVIC_GIRQ24_PRIA *( ( volatile uint32_t * ) ( 0xBFFFC400ul ) ) +#define portGIRQ24_M14K_SOFTIRQ0_BITPOS ( 1 ) +#define portGIRQ24_M14K_SOFTIRQ0_MASK ( 1ul << ( portGIRQ24_M14K_SOFTIRQ0_BITPOS ) ) +#define portMMCR_JTVIC_GIRQ24_SRC *((volatile uint32_t *)(0xBFFFC100ul)) +#define portMMCR_JTVIC_GIRQ24_SETEN *((volatile uint32_t *)(0xBFFFC104ul)) +#define portMMCR_JTVIC_GIRQ24_PRIA *((volatile uint32_t *)(0xBFFFC400ul)) /* - * By default port.c generates its tick interrupt from the RTOS timer. The user - * can override this behaviour by: - * 1: Providing their own implementation of vApplicationSetupTickTimerInterrupt(), - * which is the function that configures the timer. The function is defined - * as a weak symbol in this file so if the same function name is used in the - * application code then the version in the application code will be linked - * into the application in preference to the version defined in this file. - * 2: Provide a vector implementation in port_asm.S that overrides the default - * behaviour for the specified interrupt vector. - * 3: Specify the correct bit to clear the interrupt during the timer interrupt - * handler. - */ +By default port.c generates its tick interrupt from the RTOS timer. The user +can override this behaviour by: + 1: Providing their own implementation of vApplicationSetupTickTimerInterrupt(), + which is the function that configures the timer. The function is defined + as a weak symbol in this file so if the same function name is used in the + application code then the version in the application code will be linked + into the application in preference to the version defined in this file. + 2: Provide a vector implementation in port_asm.S that overrides the default + behaviour for the specified interrupt vector. + 3: Specify the correct bit to clear the interrupt during the timer interrupt + handler. +*/ #ifndef configTICK_INTERRUPT_VECTOR - #define configTICK_INTERRUPT_VECTOR girq23_b4 - #define configCLEAR_TICK_TIMER_INTERRUPT() portMMCR_JTVIC_GIRQ23_SRC = portGIRQ23_RTOS_TIMER_MASK + #define configTICK_INTERRUPT_VECTOR girq23_b4 + #define configCLEAR_TICK_TIMER_INTERRUPT() portMMCR_JTVIC_GIRQ23_SRC = portGIRQ23_RTOS_TIMER_MASK #else #ifndef configCLEAR_TICK_TIMER_INTERRUPT #error If configTICK_INTERRUPT_VECTOR is defined in application code then configCLEAR_TICK_TIMER_INTERRUPT must also be defined in application code. @@ -96,36 +96,34 @@ #endif /* Let the user override the pre-loading of the initial RA with the address of - * prvTaskExitError() in case it messes up unwinding of the stack in the debugger - - * in which case configTASK_RETURN_ADDRESS can be defined as 0 (NULL). */ +prvTaskExitError() in case it messes up unwinding of the stack in the debugger - +in which case configTASK_RETURN_ADDRESS can be defined as 0 (NULL). */ #ifdef configTASK_RETURN_ADDRESS - #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #else - #define portTASK_RETURN_ADDRESS prvTaskExitError + #define portTASK_RETURN_ADDRESS prvTaskExitError #endif /* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task - * stack checking. A problem in the ISR stack will trigger an assert, not call the - * stack overflow hook function (because the stack overflow hook is specific to a - * task stack, not the ISR stack). */ -#if ( configCHECK_FOR_STACK_OVERFLOW > 2 ) - -/* Don't use 0xa5 as the stack fill bytes as that is used by the kernel for - * the task stacks, and so will legitimately appear in many positions within - * the ISR stack. */ - #define portISR_STACK_FILL_BYTE 0xee - - static const uint8_t ucExpectedStackBytes[] = - { - portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ - portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ - portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ - portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ - portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE - }; \ - - #define portCHECK_ISR_STACK() configASSERT( ( memcmp( ( void * ) xISRStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) == 0 ) ) -#else /* if ( configCHECK_FOR_STACK_OVERFLOW > 2 ) */ +stack checking. A problem in the ISR stack will trigger an assert, not call the +stack overflow hook function (because the stack overflow hook is specific to a +task stack, not the ISR stack). */ +#if( configCHECK_FOR_STACK_OVERFLOW > 2 ) + + /* Don't use 0xa5 as the stack fill bytes as that is used by the kernel for + the task stacks, and so will legitimately appear in many positions within + the ISR stack. */ + #define portISR_STACK_FILL_BYTE 0xee + + static const uint8_t ucExpectedStackBytes[] = { + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE }; \ + + #define portCHECK_ISR_STACK() configASSERT( ( memcmp( ( void * ) xISRStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) == 0 ) ) +#else /* Define the function away. */ #define portCHECK_ISR_STACK() #endif /* configCHECK_FOR_STACK_OVERFLOW > 2 */ @@ -141,7 +139,7 @@ static void prvTaskExitError( void ); /*-----------------------------------------------------------*/ /* Records the interrupt nesting depth. This is initialised to one as it is - * decremented to 0 when the first task starts. */ +decremented to 0 when the first task starts. */ volatile UBaseType_t uxInterruptNesting = 0x01; /* Stores the task stack pointer when a switch is made to use the system stack. */ @@ -151,7 +149,7 @@ UBaseType_t uxSavedTaskStackPointer = 0; StackType_t xISRStack[ configISR_STACK_SIZE ] = { 0 }; /* The top of stack value ensures there is enough space to store 6 registers on - * the callers stack, as some functions seem to want to do this. */ +the callers stack, as some functions seem to want to do this. */ const StackType_t * const xISRStackTop = &( xISRStack[ configISR_STACK_SIZE - 7 ] ); /*-----------------------------------------------------------*/ @@ -159,32 +157,30 @@ const StackType_t * const xISRStackTop = &( xISRStack[ configISR_STACK_SIZE - 7 /* * See header file for description. */ -StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, - TaskFunction_t pxCode, - void * pvParameters ) +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) { /* Ensure byte alignment is maintained when leaving this function. */ pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0xDEADBEEF; + *pxTopOfStack = (StackType_t) 0xDEADBEEF; pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x12345678; /* Word to which the stack pointer will be left pointing after context restore. */ + *pxTopOfStack = (StackType_t) 0x12345678; /* Word to which the stack pointer will be left pointing after context restore. */ pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) ulPortGetCP0Cause(); + *pxTopOfStack = (StackType_t) ulPortGetCP0Cause(); pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) portINITIAL_SR; /* CP0_STATUS */ + *pxTopOfStack = (StackType_t) portINITIAL_SR; /* CP0_STATUS */ pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxCode; /* CP0_EPC */ + *pxTopOfStack = (StackType_t) pxCode; /* CP0_EPC */ pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* ra */ + *pxTopOfStack = (StackType_t) portTASK_RETURN_ADDRESS; /* ra */ pxTopOfStack -= 15; - *pxTopOfStack = ( StackType_t ) pvParameters; /* Parameters to pass in. */ + *pxTopOfStack = (StackType_t) pvParameters; /* Parameters to pass in. */ pxTopOfStack -= 15; return pxTopOfStack; @@ -193,10 +189,9 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, static __inline uint32_t prvDisableInterrupt( void ) { - uint32_t prev_state; - - __asm volatile ( "di %0; ehb" : "=r" ( prev_state )::"memory" ); +uint32_t prev_state; + __asm volatile( "di %0; ehb" : "=r" ( prev_state ) :: "memory" ); return prev_state; } /*-----------------------------------------------------------*/ @@ -204,17 +199,14 @@ static __inline uint32_t prvDisableInterrupt( void ) static void prvTaskExitError( void ) { /* A function that implements a task must not exit or attempt to return to - * its caller as there is nothing to return to. If a task wants to exit it - * should instead call vTaskDelete( NULL ). - * - * Artificially force an assert() to be triggered if configASSERT() is - * defined, then stop here so application writers can catch the error. */ + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ configASSERT( uxSavedTaskStackPointer == 0UL ); portDISABLE_INTERRUPTS(); - - for( ; ; ) - { - } + for( ;; ); } /*-----------------------------------------------------------*/ @@ -226,10 +218,10 @@ static void prvTaskExitError( void ) * ensure the RTOS provided tick interrupt handler is installed on the correct * vector number. */ -__attribute__( ( weak ) ) void vApplicationSetupTickTimerInterrupt( void ) +__attribute__(( weak )) void vApplicationSetupTickTimerInterrupt( void ) { /* MEC14xx RTOS Timer whose input clock is 32KHz. */ - const uint32_t ulPreload = ( 32768ul / ( configTICK_RATE_HZ ) ); +const uint32_t ulPreload = ( 32768ul / ( configTICK_RATE_HZ ) ); configASSERT( ulPreload != 0UL ); @@ -248,18 +240,18 @@ __attribute__( ( weak ) ) void vApplicationSetupTickTimerInterrupt( void ) } /*-----------------------------------------------------------*/ -void vPortEndScheduler( void ) +void vPortEndScheduler(void) { /* Not implemented in ports where there is nothing to return to. - * Artificially force an assert. */ + Artificially force an assert. */ configASSERT( uxInterruptNesting == 1000UL ); } /*-----------------------------------------------------------*/ BaseType_t xPortStartScheduler( void ) { - extern void vPortStartFirstTask( void ); - extern void * pxCurrentTCB; +extern void vPortStartFirstTask( void ); +extern void *pxCurrentTCB; #if ( configCHECK_FOR_STACK_OVERFLOW > 2 ) { @@ -269,29 +261,29 @@ BaseType_t xPortStartScheduler( void ) #endif /* configCHECK_FOR_STACK_OVERFLOW > 2 */ /* Clear the software interrupt flag. */ - portMMCR_JTVIC_GIRQ24_SRC = ( portGIRQ24_M14K_SOFTIRQ0_MASK ); + portMMCR_JTVIC_GIRQ24_SRC = (portGIRQ24_M14K_SOFTIRQ0_MASK); /* Set software timer priority. Each GIRQn has one nibble containing its - * priority */ - portMMCR_JTVIC_GIRQ24_PRIA &= ~( 0xF0ul ); + priority */ + portMMCR_JTVIC_GIRQ24_PRIA &= ~(0xF0ul); portMMCR_JTVIC_GIRQ24_PRIA |= ( portIPL_TO_CODE( configKERNEL_INTERRUPT_PRIORITY ) << 4 ); /* Enable software interrupt. */ portMMCR_JTVIC_GIRQ24_SETEN = ( portGIRQ24_M14K_SOFTIRQ0_MASK ); /* Setup the timer to generate the tick. Interrupts will have been disabled - * by the time we get here. */ + by the time we get here. */ vApplicationSetupTickTimerInterrupt(); /* Start the highest priority task that has been created so far. Its stack - * location is loaded into uxSavedTaskStackPointer. */ + location is loaded into uxSavedTaskStackPointer. */ uxSavedTaskStackPointer = *( UBaseType_t * ) pxCurrentTCB; vPortStartFirstTask(); /* Should never get here as the tasks will now be executing! Call the task - * exit error function to prevent compiler warnings about a static function - * not being called in the case that the application writer overrides this - * functionality by defining configTASK_RETURN_ADDRESS. */ + exit error function to prevent compiler warnings about a static function + not being called in the case that the application writer overrides this + functionality by defining configTASK_RETURN_ADDRESS. */ prvTaskExitError(); return pdFALSE; @@ -300,8 +292,8 @@ BaseType_t xPortStartScheduler( void ) void vPortIncrementTick( void ) { - UBaseType_t uxSavedStatus; - uint32_t ulCause; +UBaseType_t uxSavedStatus; +uint32_t ulCause; uxSavedStatus = uxPortSetInterruptMaskFromISR(); { @@ -325,17 +317,17 @@ void vPortIncrementTick( void ) UBaseType_t uxPortSetInterruptMaskFromISR( void ) { - UBaseType_t uxSavedStatusRegister; +UBaseType_t uxSavedStatusRegister; prvDisableInterrupt(); uxSavedStatusRegister = ulPortGetCP0Status() | 0x01; /* This clears the IPL bits, then sets them to - * configMAX_SYSCALL_INTERRUPT_PRIORITY. This function should not be called - * from an interrupt that has a priority above - * configMAX_SYSCALL_INTERRUPT_PRIORITY so, when used correctly, the action - * can only result in the IPL being unchanged or raised, and therefore never - * lowered. */ + configMAX_SYSCALL_INTERRUPT_PRIORITY. This function should not be called + from an interrupt that has a priority above + configMAX_SYSCALL_INTERRUPT_PRIORITY so, when used correctly, the action + can only result in the IPL being unchanged or raised, and therefore never + lowered. */ vPortSetCP0Status( ( ( uxSavedStatusRegister & ( ~portALL_IPL_BITS ) ) ) | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ); return uxSavedStatusRegister; diff --git a/portable/MPLAB/PIC32MEC14xx/portmacro.h b/portable/MPLAB/PIC32MEC14xx/portmacro.h index 2b1fb9fa69b..d4d4f50dc9d 100644 --- a/portable/MPLAB/PIC32MEC14xx/portmacro.h +++ b/portable/MPLAB/PIC32MEC14xx/portmacro.h @@ -46,23 +46,23 @@ */ /* Type definitions. */ -#define portCHAR char -#define portFLOAT float -#define portDOUBLE double -#define portLONG long -#define portSHORT short -#define portSTACK_TYPE uint32_t -#define portBASE_TYPE long - -typedef portSTACK_TYPE StackType_t; -typedef long BaseType_t; -typedef unsigned long UBaseType_t; - -#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff -#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff +#elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) + typedef uint32_t TickType_t; #define portMAX_DELAY ( TickType_t ) 0xffffffffUL #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. @@ -70,16 +70,15 @@ typedef unsigned long UBaseType_t; /*-----------------------------------------------------------*/ /* Hardware specifics. */ -#define portBYTE_ALIGNMENT 8 -#define portSTACK_GROWTH -1 -#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portSTACK_GROWTH -1 +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) /*-----------------------------------------------------------*/ /* Critical section management. */ #define portIPL_SHIFT ( 10UL ) - /* Don't straddle the CEE bit. Interrupts calling FreeRTOS functions should - * never have higher IPL bits set anyway. */ +never have higher IPL bits set anyway. */ #define portALL_IPL_BITS ( 0x7FUL << portIPL_SHIFT ) #define portSW0_BIT ( 0x01 << 8 ) @@ -91,38 +90,38 @@ typedef unsigned long UBaseType_t; static inline uint32_t ulPortGetCP0Status( void ) { - uint32_t rv; +uint32_t rv; - __asm volatile ( - "\n\t" - "mfc0 %0,$12,0 \n\t" - : "=r" ( rv )::); + __asm volatile( + "\n\t" + "mfc0 %0,$12,0 \n\t" + : "=r" ( rv ) :: ); return rv; } /*-----------------------------------------------------------*/ -static inline void vPortSetCP0Status( uint32_t new_status ) +static inline void vPortSetCP0Status( uint32_t new_status) { ( void ) new_status; - __asm__ __volatile__ ( - "\n\t" - "mtc0 %0,$12,0 \n\t" - "ehb \n\t" - : - : "r" ( new_status ) : ); + __asm__ __volatile__( + "\n\t" + "mtc0 %0,$12,0 \n\t" + "ehb \n\t" + : + :"r" ( new_status ) : ); } /*-----------------------------------------------------------*/ static inline uint32_t ulPortGetCP0Cause( void ) { - uint32_t rv; +uint32_t rv; - __asm volatile ( - "\n\t" - "mfc0 %0,$13,0 \n\t" - : "=r" ( rv )::); + __asm volatile( + "\n\t" + "mfc0 %0,$13,0 \n\t" + : "=r" ( rv ) :: ); return rv; } @@ -132,86 +131,86 @@ static inline void vPortSetCP0Cause( uint32_t new_cause ) { ( void ) new_cause; - __asm__ __volatile__ ( - "\n\t" - "mtc0 %0,$13,0 \n\t" - "ehb \n\t" - : - : "r" ( new_cause ) : ); + __asm__ __volatile__( + "\n\t" + "mtc0 %0,$13,0 \n\t" + "ehb \n\t" + : + :"r" ( new_cause ) : ); } /*-----------------------------------------------------------*/ /* This clears the IPL bits, then sets them to - * configMAX_SYSCALL_INTERRUPT_PRIORITY. An extra check is performed if - * configASSERT() is defined to ensure an assertion handler does not inadvertently - * attempt to lower the IPL when the call to assert was triggered because the IPL - * value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY when an ISR - * safe FreeRTOS API function was executed. ISR safe FreeRTOS API functions are - * those that end in FromISR. FreeRTOS maintains a separate interrupt API to - * ensure API function and interrupt entry is as fast and as simple as possible. */ +configMAX_SYSCALL_INTERRUPT_PRIORITY. An extra check is performed if +configASSERT() is defined to ensure an assertion handler does not inadvertently +attempt to lower the IPL when the call to assert was triggered because the IPL +value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY when an ISR +safe FreeRTOS API function was executed. ISR safe FreeRTOS API functions are +those that end in FromISR. FreeRTOS maintains a separate interrupt API to +ensure API function and interrupt entry is as fast and as simple as possible. */ #ifdef configASSERT - #define portDISABLE_INTERRUPTS() \ - { \ - uint32_t ulStatus; \ - /* Mask interrupts at and below the kernel interrupt priority. */ \ - ulStatus = ulPortGetCP0Status(); \ - /* Is the current IPL below configMAX_SYSCALL_INTERRUPT_PRIORITY? */ \ - if( ( ( ulStatus & portALL_IPL_BITS ) >> portIPL_SHIFT ) < configMAX_SYSCALL_INTERRUPT_PRIORITY ) \ - { \ - ulStatus &= ~portALL_IPL_BITS; \ - vPortSetCP0Status( ( ulStatus | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ) ); \ - } \ + #define portDISABLE_INTERRUPTS() \ + { \ + uint32_t ulStatus; \ + /* Mask interrupts at and below the kernel interrupt priority. */ \ + ulStatus = ulPortGetCP0Status(); \ + /* Is the current IPL below configMAX_SYSCALL_INTERRUPT_PRIORITY? */ \ + if( ( ( ulStatus & portALL_IPL_BITS ) >> portIPL_SHIFT ) < configMAX_SYSCALL_INTERRUPT_PRIORITY ) \ + { \ + ulStatus &= ~portALL_IPL_BITS; \ + vPortSetCP0Status( ( ulStatus | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ) ); \ + } \ } #else /* configASSERT */ - #define portDISABLE_INTERRUPTS() \ - { \ - uint32_t ulStatus; \ - /* Mask interrupts at and below the kernel interrupt priority. */ \ - ulStatus = ulPortGetCP0Status(); \ - ulStatus &= ~portALL_IPL_BITS; \ - vPortSetCP0Status( ( ulStatus | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ) ); \ + #define portDISABLE_INTERRUPTS() \ + { \ + uint32_t ulStatus; \ + /* Mask interrupts at and below the kernel interrupt priority. */ \ + ulStatus = ulPortGetCP0Status(); \ + ulStatus &= ~portALL_IPL_BITS; \ + vPortSetCP0Status( ( ulStatus | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ) ); \ } #endif /* configASSERT */ -#define portENABLE_INTERRUPTS() \ - { \ - uint32_t ulStatus; \ - /* Unmask all interrupts. */ \ - ulStatus = ulPortGetCP0Status(); \ - ulStatus &= ~portALL_IPL_BITS; \ - vPortSetCP0Status( ulStatus ); \ - } +#define portENABLE_INTERRUPTS() \ +{ \ +uint32_t ulStatus; \ + /* Unmask all interrupts. */ \ + ulStatus = ulPortGetCP0Status(); \ + ulStatus &= ~portALL_IPL_BITS; \ + vPortSetCP0Status( ulStatus ); \ +} extern void vTaskEnterCritical( void ); extern void vTaskExitCritical( void ); -#define portCRITICAL_NESTING_IN_TCB 1 -#define portENTER_CRITICAL() vTaskEnterCritical() -#define portEXIT_CRITICAL() vTaskExitCritical() +#define portCRITICAL_NESTING_IN_TCB 1 +#define portENTER_CRITICAL() vTaskEnterCritical() +#define portEXIT_CRITICAL() vTaskExitCritical() extern UBaseType_t uxPortSetInterruptMaskFromISR(); extern void vPortClearInterruptMaskFromISR( UBaseType_t ); -#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMaskFromISR() -#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) vPortClearInterruptMaskFromISR( uxSavedStatusRegister ) +#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMaskFromISR() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) vPortClearInterruptMaskFromISR( uxSavedStatusRegister ) #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION - #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #endif #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 -/* Check the configuration. */ - #if ( configMAX_PRIORITIES > 32 ) + /* Check the configuration. */ + #if( configMAX_PRIORITIES > 32 ) #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. #endif -/* Store/clear the ready priorities in a bit map. */ - #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) - #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) -/*-----------------------------------------------------------*/ + /*-----------------------------------------------------------*/ - #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - _clz( ( uxReadyPriorities ) ) ) + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - _clz( ( uxReadyPriorities ) ) ) #endif /* taskRECORD_READY_PRIORITY */ @@ -219,25 +218,25 @@ extern void vPortClearInterruptMaskFromISR( UBaseType_t ); /* Task utilities. */ -#define portYIELD() \ - { \ - uint32_t ulCause; \ - /* Trigger software interrupt. */ \ - ulCause = ulPortGetCP0Cause(); \ - ulCause |= portSW0_BIT; \ - vPortSetCP0Cause( ulCause ); \ - } +#define portYIELD() \ +{ \ +uint32_t ulCause; \ + /* Trigger software interrupt. */ \ + ulCause = ulPortGetCP0Cause(); \ + ulCause |= portSW0_BIT; \ + vPortSetCP0Cause( ulCause ); \ +} extern volatile UBaseType_t uxInterruptNesting; -#define portASSERT_IF_IN_ISR() configASSERT( uxInterruptNesting == 0 ) +#define portASSERT_IF_IN_ISR() configASSERT( uxInterruptNesting == 0 ) -#define portNOP() __asm volatile ( "nop" ) +#define portNOP() __asm volatile ( "nop" ) /*-----------------------------------------------------------*/ /* Task function macros as described on the FreeRTOS.org WEB site. */ -#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) __attribute__( ( noreturn ) ) -#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__((noreturn)) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) /*-----------------------------------------------------------*/ #define portEND_SWITCHING_ISR( xSwitchRequired ) \ diff --git a/portable/MPLAB/PIC32MX/ISR_Support.h b/portable/MPLAB/PIC32MX/ISR_Support.h index 38c8d6a35f1..d594c7cc707 100644 --- a/portable/MPLAB/PIC32MX/ISR_Support.h +++ b/portable/MPLAB/PIC32MX/ISR_Support.h @@ -28,165 +28,164 @@ #include "FreeRTOSConfig.h" -#define portCONTEXT_SIZE 132 -#define portEPC_STACK_LOCATION 124 -#define portSTATUS_STACK_LOCATION 128 +#define portCONTEXT_SIZE 132 +#define portEPC_STACK_LOCATION 124 +#define portSTATUS_STACK_LOCATION 128 /******************************************************************/ -.macro portSAVE_CONTEXT - -/* Make room for the context. First save the current status so it can be - * manipulated, and the cause and EPC registers so their original values are - * captured. */ -mfc0 k0, _CP0_CAUSE -addiu sp, sp, -portCONTEXT_SIZE -mfc0 k1, _CP0_STATUS - -/* Also save s6 and s5 so they can be used. Any nesting interrupts should - * maintain the values of these registers across the ISR. */ -sw s6, 44 ( sp ) -sw s5, 40 ( sp ) -sw k1, portSTATUS_STACK_LOCATION( sp ) - -/* Prepare to enable interrupts above the current priority. */ -srl k0, k0, 0xa -ins k1, k0, 10, 6 -ins k1, zero, 1, 4 - -/* s5 is used as the frame pointer. */ -add s5, zero, sp - -/* Check the nesting count value. */ -la k0, uxInterruptNesting -lw s6, ( k0 ) - -/* If the nesting count is 0 then swap to the the system stack, otherwise - * the system stack is already being used. */ -bne s6, zero, 1f -nop - -/* Swap to the system stack. */ -la sp, xISRStackTop -lw sp, ( sp ) - -/* Increment and save the nesting count. */ -1 : addiu s6, s6, 1 -sw s6, 0 ( k0 ) - -/* s6 holds the EPC value, this is saved after interrupts are re-enabled. */ -mfc0 s6, _CP0_EPC - -/* Re-enable interrupts. */ -mtc0 k1, _CP0_STATUS - -/* Save the context into the space just created. s6 is saved again - * here as it now contains the EPC value. No other s registers need be - * saved. */ -sw ra, 120 ( s5 ) -sw s8, 116 ( s5 ) -sw t9, 112 ( s5 ) -sw t8, 108 ( s5 ) -sw t7, 104 ( s5 ) -sw t6, 100 ( s5 ) -sw t5, 96 ( s5 ) -sw t4, 92 ( s5 ) -sw t3, 88 ( s5 ) -sw t2, 84 ( s5 ) -sw t1, 80 ( s5 ) -sw t0, 76 ( s5 ) -sw a3, 72 ( s5 ) -sw a2, 68 ( s5 ) -sw a1, 64 ( s5 ) -sw a0, 60 ( s5 ) -sw v1, 56 ( s5 ) -sw v0, 52 ( s5 ) -sw s6, portEPC_STACK_LOCATION( s5 ) -sw $1, 16 ( s5 ) - -/* s6 is used as a scratch register. */ -mfhi s6 -sw s6, 12 ( s5 ) -mflo s6 -sw s6, 8 ( s5 ) - -/* Update the task stack pointer value if nesting is zero. */ -la s6, uxInterruptNesting -lw s6, ( s6 ) -addiu s6, s6, -1 -bne s6, zero, 1f -nop - -/* Save the stack pointer. */ -la s6, uxSavedTaskStackPointer -sw s5, ( s6 ) -1 : -.endm +.macro portSAVE_CONTEXT + + /* Make room for the context. First save the current status so it can be + manipulated, and the cause and EPC registers so their original values are + captured. */ + mfc0 k0, _CP0_CAUSE + addiu sp, sp, -portCONTEXT_SIZE + mfc0 k1, _CP0_STATUS + + /* Also save s6 and s5 so they can be used. Any nesting interrupts should + maintain the values of these registers across the ISR. */ + sw s6, 44(sp) + sw s5, 40(sp) + sw k1, portSTATUS_STACK_LOCATION(sp) + + /* Prepare to enable interrupts above the current priority. */ + srl k0, k0, 0xa + ins k1, k0, 10, 6 + ins k1, zero, 1, 4 + + /* s5 is used as the frame pointer. */ + add s5, zero, sp + + /* Check the nesting count value. */ + la k0, uxInterruptNesting + lw s6, (k0) + + /* If the nesting count is 0 then swap to the the system stack, otherwise + the system stack is already being used. */ + bne s6, zero, 1f + nop + + /* Swap to the system stack. */ + la sp, xISRStackTop + lw sp, (sp) + + /* Increment and save the nesting count. */ +1: addiu s6, s6, 1 + sw s6, 0(k0) + + /* s6 holds the EPC value, this is saved after interrupts are re-enabled. */ + mfc0 s6, _CP0_EPC + + /* Re-enable interrupts. */ + mtc0 k1, _CP0_STATUS + + /* Save the context into the space just created. s6 is saved again + here as it now contains the EPC value. No other s registers need be + saved. */ + sw ra, 120(s5) + sw s8, 116(s5) + sw t9, 112(s5) + sw t8, 108(s5) + sw t7, 104(s5) + sw t6, 100(s5) + sw t5, 96(s5) + sw t4, 92(s5) + sw t3, 88(s5) + sw t2, 84(s5) + sw t1, 80(s5) + sw t0, 76(s5) + sw a3, 72(s5) + sw a2, 68(s5) + sw a1, 64(s5) + sw a0, 60(s5) + sw v1, 56(s5) + sw v0, 52(s5) + sw s6, portEPC_STACK_LOCATION(s5) + sw $1, 16(s5) + + /* s6 is used as a scratch register. */ + mfhi s6 + sw s6, 12(s5) + mflo s6 + sw s6, 8(s5) + + /* Update the task stack pointer value if nesting is zero. */ + la s6, uxInterruptNesting + lw s6, (s6) + addiu s6, s6, -1 + bne s6, zero, 1f + nop + + /* Save the stack pointer. */ + la s6, uxSavedTaskStackPointer + sw s5, (s6) +1: + .endm /******************************************************************/ - .macro portRESTORE_CONTEXT - -/* Restore the stack pointer from the TCB. This is only done if the - * nesting count is 1. */ -la s6, uxInterruptNesting -lw s6, ( s6 ) -addiu s6, s6, -1 -bne s6, zero, 1f -nop -la s6, uxSavedTaskStackPointer -lw s5, ( s6 ) - -/* Restore the context. */ -1 : lw s6, 8 ( s5 ) -mtlo s6 -lw s6, 12 ( s5 ) -mthi s6 -lw $1, 16 ( s5 ) - -/* s6 is loaded as it was used as a scratch register and therefore saved - * as part of the interrupt context. */ -lw s6, 44 ( s5 ) -lw v0, 52 ( s5 ) -lw v1, 56 ( s5 ) -lw a0, 60 ( s5 ) -lw a1, 64 ( s5 ) -lw a2, 68 ( s5 ) -lw a3, 72 ( s5 ) -lw t0, 76 ( s5 ) -lw t1, 80 ( s5 ) -lw t2, 84 ( s5 ) -lw t3, 88 ( s5 ) -lw t4, 92 ( s5 ) -lw t5, 96 ( s5 ) -lw t6, 100 ( s5 ) -lw t7, 104 ( s5 ) -lw t8, 108 ( s5 ) -lw t9, 112 ( s5 ) -lw s8, 116 ( s5 ) -lw ra, 120 ( s5 ) - -/* Protect access to the k registers, and others. */ -di -ehb - -/* Decrement the nesting count. */ -la k0, uxInterruptNesting -lw k1, ( k0 ) -addiu k1, k1, -1 -sw k1, 0 ( k0 ) - -lw k0, portSTATUS_STACK_LOCATION( s5 ) -lw k1, portEPC_STACK_LOCATION( s5 ) - -/* Leave the stack in its original state. First load sp from s5, then - * restore s5 from the stack. */ -add sp, zero, s5 -lw s5, 40 ( sp ) -addiu sp, sp, portCONTEXT_SIZE - -mtc0 k0, _CP0_STATUS -mtc0 k1, _CP0_EPC -ehb -eret -nop - - .endm +.macro portRESTORE_CONTEXT + + /* Restore the stack pointer from the TCB. This is only done if the + nesting count is 1. */ + la s6, uxInterruptNesting + lw s6, (s6) + addiu s6, s6, -1 + bne s6, zero, 1f + nop + la s6, uxSavedTaskStackPointer + lw s5, (s6) + + /* Restore the context. */ +1: lw s6, 8(s5) + mtlo s6 + lw s6, 12(s5) + mthi s6 + lw $1, 16(s5) + /* s6 is loaded as it was used as a scratch register and therefore saved + as part of the interrupt context. */ + lw s6, 44(s5) + lw v0, 52(s5) + lw v1, 56(s5) + lw a0, 60(s5) + lw a1, 64(s5) + lw a2, 68(s5) + lw a3, 72(s5) + lw t0, 76(s5) + lw t1, 80(s5) + lw t2, 84(s5) + lw t3, 88(s5) + lw t4, 92(s5) + lw t5, 96(s5) + lw t6, 100(s5) + lw t7, 104(s5) + lw t8, 108(s5) + lw t9, 112(s5) + lw s8, 116(s5) + lw ra, 120(s5) + + /* Protect access to the k registers, and others. */ + di + ehb + + /* Decrement the nesting count. */ + la k0, uxInterruptNesting + lw k1, (k0) + addiu k1, k1, -1 + sw k1, 0(k0) + + lw k0, portSTATUS_STACK_LOCATION(s5) + lw k1, portEPC_STACK_LOCATION(s5) + + /* Leave the stack in its original state. First load sp from s5, then + restore s5 from the stack. */ + add sp, zero, s5 + lw s5, 40(sp) + addiu sp, sp, portCONTEXT_SIZE + + mtc0 k0, _CP0_STATUS + mtc0 k1, _CP0_EPC + ehb + eret + nop + + .endm diff --git a/portable/MPLAB/PIC32MX/port.c b/portable/MPLAB/PIC32MX/port.c index 6c71f725760..9f914076362 100644 --- a/portable/MPLAB/PIC32MX/port.c +++ b/portable/MPLAB/PIC32MX/port.c @@ -27,8 +27,8 @@ */ /*----------------------------------------------------------- -* Implementation of functions defined in portable.h for the PIC32MX port. -*----------------------------------------------------------*/ + * Implementation of functions defined in portable.h for the PIC32MX port. + *----------------------------------------------------------*/ #ifndef __XC #error This port is designed to work with XC32. Please update your C compiler version. @@ -39,41 +39,41 @@ #include "task.h" /* Hardware specifics. */ -#define portTIMER_PRESCALE 8 -#define portPRESCALE_BITS 1 +#define portTIMER_PRESCALE 8 +#define portPRESCALE_BITS 1 /* Bits within various registers. */ -#define portIE_BIT ( 0x00000001 ) -#define portEXL_BIT ( 0x00000002 ) +#define portIE_BIT ( 0x00000001 ) +#define portEXL_BIT ( 0x00000002 ) /* Bits within the CAUSE register. */ -#define portCORE_SW_0 ( 0x00000100 ) -#define portCORE_SW_1 ( 0x00000200 ) +#define portCORE_SW_0 ( 0x00000100 ) +#define portCORE_SW_1 ( 0x00000200 ) /* The EXL bit is set to ensure interrupts do not occur while the context of - * the first task is being restored. */ -#define portINITIAL_SR ( portIE_BIT | portEXL_BIT ) +the first task is being restored. */ +#define portINITIAL_SR ( portIE_BIT | portEXL_BIT ) /* - * By default port.c generates its tick interrupt from TIMER1. The user can - * override this behaviour by: - * 1: Providing their own implementation of vApplicationSetupTickTimerInterrupt(), - * which is the function that configures the timer. The function is defined - * as a weak symbol in this file so if the same function name is used in the - * application code then the version in the application code will be linked - * into the application in preference to the version defined in this file. - * 2: Define configTICK_INTERRUPT_VECTOR to the vector number of the timer used - * to generate the tick interrupt. For example, when timer 1 is used then - * configTICK_INTERRUPT_VECTOR is set to _TIMER_1_VECTOR. - * configTICK_INTERRUPT_VECTOR should be defined in FreeRTOSConfig.h. - * 3: Define configCLEAR_TICK_TIMER_INTERRUPT() to clear the interrupt in the - * timer used to generate the tick interrupt. For example, when timer 1 is - * used configCLEAR_TICK_TIMER_INTERRUPT() is defined to - * IFS0CLR = _IFS0_T1IF_MASK. - */ +By default port.c generates its tick interrupt from TIMER1. The user can +override this behaviour by: + 1: Providing their own implementation of vApplicationSetupTickTimerInterrupt(), + which is the function that configures the timer. The function is defined + as a weak symbol in this file so if the same function name is used in the + application code then the version in the application code will be linked + into the application in preference to the version defined in this file. + 2: Define configTICK_INTERRUPT_VECTOR to the vector number of the timer used + to generate the tick interrupt. For example, when timer 1 is used then + configTICK_INTERRUPT_VECTOR is set to _TIMER_1_VECTOR. + configTICK_INTERRUPT_VECTOR should be defined in FreeRTOSConfig.h. + 3: Define configCLEAR_TICK_TIMER_INTERRUPT() to clear the interrupt in the + timer used to generate the tick interrupt. For example, when timer 1 is + used configCLEAR_TICK_TIMER_INTERRUPT() is defined to + IFS0CLR = _IFS0_T1IF_MASK. +*/ #ifndef configTICK_INTERRUPT_VECTOR - #define configTICK_INTERRUPT_VECTOR _TIMER_1_VECTOR - #define configCLEAR_TICK_TIMER_INTERRUPT() IFS0CLR = _IFS0_T1IF_MASK + #define configTICK_INTERRUPT_VECTOR _TIMER_1_VECTOR + #define configCLEAR_TICK_TIMER_INTERRUPT() IFS0CLR = _IFS0_T1IF_MASK #else #ifndef configCLEAR_TICK_TIMER_INTERRUPT #error If configTICK_INTERRUPT_VECTOR is defined in application code then configCLEAR_TICK_TIMER_INTERRUPT must also be defined in application code. @@ -81,36 +81,34 @@ #endif /* Let the user override the pre-loading of the initial RA with the address of - * prvTaskExitError() in case it messes up unwinding of the stack in the - * debugger - in which case configTASK_RETURN_ADDRESS can be defined as 0 (NULL). */ +prvTaskExitError() in case it messes up unwinding of the stack in the +debugger - in which case configTASK_RETURN_ADDRESS can be defined as 0 (NULL). */ #ifdef configTASK_RETURN_ADDRESS - #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #else - #define portTASK_RETURN_ADDRESS prvTaskExitError + #define portTASK_RETURN_ADDRESS prvTaskExitError #endif /* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task - * stack checking. A problem in the ISR stack will trigger an assert, not call the - * stack overflow hook function (because the stack overflow hook is specific to a - * task stack, not the ISR stack). */ -#if ( configCHECK_FOR_STACK_OVERFLOW > 2 ) - -/* Don't use 0xa5 as the stack fill bytes as that is used by the kernel for - * the task stacks, and so will legitimately appear in many positions within - * the ISR stack. */ - #define portISR_STACK_FILL_BYTE 0xee - - static const uint8_t ucExpectedStackBytes[] = - { - portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ - portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ - portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ - portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ - portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE - }; \ - - #define portCHECK_ISR_STACK() configASSERT( ( memcmp( ( void * ) xISRStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) == 0 ) ) -#else /* if ( configCHECK_FOR_STACK_OVERFLOW > 2 ) */ +stack checking. A problem in the ISR stack will trigger an assert, not call the +stack overflow hook function (because the stack overflow hook is specific to a +task stack, not the ISR stack). */ +#if( configCHECK_FOR_STACK_OVERFLOW > 2 ) + + /* Don't use 0xa5 as the stack fill bytes as that is used by the kernel for + the task stacks, and so will legitimately appear in many positions within + the ISR stack. */ + #define portISR_STACK_FILL_BYTE 0xee + + static const uint8_t ucExpectedStackBytes[] = { + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE }; \ + + #define portCHECK_ISR_STACK() configASSERT( ( memcmp( ( void * ) xISRStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) == 0 ) ) +#else /* Define the function away. */ #define portCHECK_ISR_STACK() #endif /* configCHECK_FOR_STACK_OVERFLOW > 2 */ @@ -124,7 +122,7 @@ * following line of code has no effect. The interrupt priority is set by the * call to ConfigIntTimer1() in vApplicationSetupTickTimerInterrupt(). */ -extern void __attribute__( ( interrupt( IPL1AUTO ), vector( configTICK_INTERRUPT_VECTOR ) ) ) vPortTickInterruptHandler( void ); +extern void __attribute__( (interrupt(IPL1AUTO), vector( configTICK_INTERRUPT_VECTOR ))) vPortTickInterruptHandler( void ); /* * The software interrupt handler that performs the yield. Note that, because @@ -132,7 +130,7 @@ extern void __attribute__( ( interrupt( IPL1AUTO ), vector( configTICK_INTERRUPT * code has no effect. The interrupt priority is set by the call to * mConfigIntCoreSW0() in xPortStartScheduler(). */ -void __attribute__( ( interrupt( IPL1AUTO ), vector( _CORE_SOFTWARE_0_VECTOR ) ) ) vPortYieldISR( void ); +void __attribute__( (interrupt(IPL1AUTO), vector(_CORE_SOFTWARE_0_VECTOR))) vPortYieldISR( void ); /* * Used to catch tasks that attempt to return from their implementing function. @@ -142,17 +140,17 @@ static void prvTaskExitError( void ); /*-----------------------------------------------------------*/ /* Records the interrupt nesting depth. This is initialised to one as it is - * decremented to 0 when the first task starts. */ +decremented to 0 when the first task starts. */ volatile UBaseType_t uxInterruptNesting = 0x01; /* Stores the task stack pointer when a switch is made to use the system stack. */ UBaseType_t uxSavedTaskStackPointer = 0; /* The stack used by interrupt service routines that cause a context switch. */ -__attribute__( ( aligned( 8 ) ) ) StackType_t xISRStack[ configISR_STACK_SIZE ] = { 0 }; +__attribute__ ((aligned(8))) StackType_t xISRStack[ configISR_STACK_SIZE ] = { 0 }; /* The top of stack value ensures there is enough space to store 6 registers on - * the callers stack, as some functions seem to want to do this. */ +the callers stack, as some functions seem to want to do this. */ const StackType_t * const xISRStackTop = &( xISRStack[ ( configISR_STACK_SIZE & ~portBYTE_ALIGNMENT_MASK ) - 8 ] ); /*-----------------------------------------------------------*/ @@ -160,34 +158,32 @@ const StackType_t * const xISRStackTop = &( xISRStack[ ( configISR_STACK_SIZE & /* * See header file for description. */ -StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, - TaskFunction_t pxCode, - void * pvParameters ) +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) { /* Ensure 8 byte alignment is maintained when the context is popped from * stack. The size of the context is 33 words (132 bytes). */ pxTopOfStack--; pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0xDEADBEEF; + *pxTopOfStack = (StackType_t) 0xDEADBEEF; pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x12345678; /* Word to which the stack pointer will be left pointing after context restore. */ + *pxTopOfStack = (StackType_t) 0x12345678; /* Word to which the stack pointer will be left pointing after context restore. */ pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) _CP0_GET_CAUSE(); + *pxTopOfStack = (StackType_t) _CP0_GET_CAUSE(); pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) portINITIAL_SR; /* CP0_STATUS */ + *pxTopOfStack = (StackType_t) portINITIAL_SR;/* CP0_STATUS */ pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxCode; /* CP0_EPC */ + *pxTopOfStack = (StackType_t) pxCode; /* CP0_EPC */ pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* ra */ + *pxTopOfStack = (StackType_t) portTASK_RETURN_ADDRESS; /* ra */ pxTopOfStack -= 15; - *pxTopOfStack = ( StackType_t ) pvParameters; /* Parameters to pass in. */ + *pxTopOfStack = (StackType_t) pvParameters; /* Parameters to pass in. */ pxTopOfStack -= 15; return pxTopOfStack; @@ -197,17 +193,14 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, static void prvTaskExitError( void ) { /* A function that implements a task must not exit or attempt to return to - * its caller as there is nothing to return to. If a task wants to exit it - * should instead call vTaskDelete( NULL ). - * - * Artificially force an assert() to be triggered if configASSERT() is - * defined, then stop here so application writers can catch the error. */ + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ configASSERT( uxSavedTaskStackPointer == 0UL ); portDISABLE_INTERRUPTS(); - - for( ; ; ) - { - } + for( ;; ); } /*-----------------------------------------------------------*/ @@ -220,9 +213,9 @@ static void prvTaskExitError( void ) * vector number. When Timer 1 is used the vector number is defined as * _TIMER_1_VECTOR. */ -__attribute__( ( weak ) ) void vApplicationSetupTickTimerInterrupt( void ) +__attribute__(( weak )) void vApplicationSetupTickTimerInterrupt( void ) { - const uint32_t ulCompareMatch = ( ( configPERIPHERAL_CLOCK_HZ / portTIMER_PRESCALE ) / configTICK_RATE_HZ ) - 1; +const uint32_t ulCompareMatch = ( (configPERIPHERAL_CLOCK_HZ / portTIMER_PRESCALE) / configTICK_RATE_HZ ) - 1; T1CON = 0x0000; T1CONbits.TCKPS = portPRESCALE_BITS; @@ -240,18 +233,18 @@ __attribute__( ( weak ) ) void vApplicationSetupTickTimerInterrupt( void ) } /*-----------------------------------------------------------*/ -void vPortEndScheduler( void ) +void vPortEndScheduler(void) { /* Not implemented in ports where there is nothing to return to. - * Artificially force an assert. */ + Artificially force an assert. */ configASSERT( uxInterruptNesting == 1000UL ); } /*-----------------------------------------------------------*/ BaseType_t xPortStartScheduler( void ) { - extern void vPortStartFirstTask( void ); - extern void * pxCurrentTCB; +extern void vPortStartFirstTask( void ); +extern void *pxCurrentTCB; #if ( configCHECK_FOR_STACK_OVERFLOW > 2 ) { @@ -272,18 +265,18 @@ BaseType_t xPortStartScheduler( void ) IEC0SET = 1 << _IEC0_CS0IE_POSITION; /* Setup the timer to generate the tick. Interrupts will have been - * disabled by the time we get here. */ + disabled by the time we get here. */ vApplicationSetupTickTimerInterrupt(); /* Kick off the highest priority task that has been created so far. - * Its stack location is loaded into uxSavedTaskStackPointer. */ + Its stack location is loaded into uxSavedTaskStackPointer. */ uxSavedTaskStackPointer = *( UBaseType_t * ) pxCurrentTCB; vPortStartFirstTask(); /* Should never get here as the tasks will now be executing! Call the task - * exit error function to prevent compiler warnings about a static function - * not being called in the case that the application writer overrides this - * functionality by defining configTASK_RETURN_ADDRESS. */ + exit error function to prevent compiler warnings about a static function + not being called in the case that the application writer overrides this + functionality by defining configTASK_RETURN_ADDRESS. */ prvTaskExitError(); return pdFALSE; @@ -292,7 +285,7 @@ BaseType_t xPortStartScheduler( void ) void vPortIncrementTick( void ) { - UBaseType_t uxSavedStatus; +UBaseType_t uxSavedStatus; uxSavedStatus = uxPortSetInterruptMaskFromISR(); { @@ -314,17 +307,16 @@ void vPortIncrementTick( void ) UBaseType_t uxPortSetInterruptMaskFromISR( void ) { - UBaseType_t uxSavedStatusRegister; +UBaseType_t uxSavedStatusRegister; __builtin_disable_interrupts(); uxSavedStatusRegister = _CP0_GET_STATUS() | 0x01; - /* This clears the IPL bits, then sets them to - * configMAX_SYSCALL_INTERRUPT_PRIORITY. This function should not be called - * from an interrupt that has a priority above - * configMAX_SYSCALL_INTERRUPT_PRIORITY so, when used correctly, the action - * can only result in the IPL being unchanged or raised, and therefore never - * lowered. */ + configMAX_SYSCALL_INTERRUPT_PRIORITY. This function should not be called + from an interrupt that has a priority above + configMAX_SYSCALL_INTERRUPT_PRIORITY so, when used correctly, the action + can only result in the IPL being unchanged or raised, and therefore never + lowered. */ _CP0_SET_STATUS( ( ( uxSavedStatusRegister & ( ~portALL_IPL_BITS ) ) ) | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ); return uxSavedStatusRegister; diff --git a/portable/MPLAB/PIC32MX/portmacro.h b/portable/MPLAB/PIC32MX/portmacro.h index 89777d80b68..b481165e686 100644 --- a/portable/MPLAB/PIC32MX/portmacro.h +++ b/portable/MPLAB/PIC32MX/portmacro.h @@ -49,119 +49,119 @@ */ /* Type definitions. */ -#define portCHAR char -#define portFLOAT float -#define portDOUBLE double -#define portLONG long -#define portSHORT short -#define portSTACK_TYPE uint32_t -#define portBASE_TYPE long - -typedef portSTACK_TYPE StackType_t; -typedef long BaseType_t; -typedef unsigned long UBaseType_t; - -#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ - #define portTICK_TYPE_IS_ATOMIC 1 + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + not need to be guarded with a critical section. */ + #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. #endif /*-----------------------------------------------------------*/ /* Hardware specifics. */ -#define portBYTE_ALIGNMENT 8 -#define portSTACK_GROWTH -1 -#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portSTACK_GROWTH -1 +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) /*-----------------------------------------------------------*/ /* Critical section management. */ -#define portIPL_SHIFT ( 10UL ) -#define portALL_IPL_BITS ( 0x3fUL << portIPL_SHIFT ) -#define portSW0_BIT ( 0x01 << 8 ) +#define portIPL_SHIFT ( 10UL ) +#define portALL_IPL_BITS ( 0x3fUL << portIPL_SHIFT ) +#define portSW0_BIT ( 0x01 << 8 ) /* This clears the IPL bits, then sets them to - * configMAX_SYSCALL_INTERRUPT_PRIORITY. An extra check is performed if - * configASSERT() is defined to ensure an assertion handler does not inadvertently - * attempt to lower the IPL when the call to assert was triggered because the IPL - * value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY when an ISR - * safe FreeRTOS API function was executed. ISR safe FreeRTOS API functions are - * those that end in FromISR. FreeRTOS maintains a separate interrupt API to - * ensure API function and interrupt entry is as fast and as simple as possible. */ +configMAX_SYSCALL_INTERRUPT_PRIORITY. An extra check is performed if +configASSERT() is defined to ensure an assertion handler does not inadvertently +attempt to lower the IPL when the call to assert was triggered because the IPL +value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY when an ISR +safe FreeRTOS API function was executed. ISR safe FreeRTOS API functions are +those that end in FromISR. FreeRTOS maintains a separate interrupt API to +ensure API function and interrupt entry is as fast and as simple as possible. */ #ifdef configASSERT - #define portDISABLE_INTERRUPTS() \ - { \ - uint32_t ulStatus; \ - \ - /* Mask interrupts at and below the kernel interrupt priority. */ \ - ulStatus = _CP0_GET_STATUS(); \ - \ - /* Is the current IPL below configMAX_SYSCALL_INTERRUPT_PRIORITY? */ \ + #define portDISABLE_INTERRUPTS() \ + { \ + uint32_t ulStatus; \ + \ + /* Mask interrupts at and below the kernel interrupt priority. */ \ + ulStatus = _CP0_GET_STATUS(); \ + \ + /* Is the current IPL below configMAX_SYSCALL_INTERRUPT_PRIORITY? */ \ if( ( ( ulStatus & portALL_IPL_BITS ) >> portIPL_SHIFT ) < configMAX_SYSCALL_INTERRUPT_PRIORITY ) \ - { \ - ulStatus &= ~portALL_IPL_BITS; \ - _CP0_SET_STATUS( ( ulStatus | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ) ); \ - } \ + { \ + ulStatus &= ~portALL_IPL_BITS; \ + _CP0_SET_STATUS( ( ulStatus | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ) ); \ + } \ } #else /* configASSERT */ - #define portDISABLE_INTERRUPTS() \ - { \ - uint32_t ulStatus; \ - \ - /* Mask interrupts at and below the kernel interrupt priority. */ \ - ulStatus = _CP0_GET_STATUS(); \ - ulStatus &= ~portALL_IPL_BITS; \ + #define portDISABLE_INTERRUPTS() \ + { \ + uint32_t ulStatus; \ + \ + /* Mask interrupts at and below the kernel interrupt priority. */ \ + ulStatus = _CP0_GET_STATUS(); \ + ulStatus &= ~portALL_IPL_BITS; \ _CP0_SET_STATUS( ( ulStatus | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ) ); \ } #endif /* configASSERT */ -#define portENABLE_INTERRUPTS() \ - { \ - uint32_t ulStatus; \ - \ - /* Unmask all interrupts. */ \ - ulStatus = _CP0_GET_STATUS(); \ - ulStatus &= ~portALL_IPL_BITS; \ - _CP0_SET_STATUS( ulStatus ); \ - } +#define portENABLE_INTERRUPTS() \ +{ \ +uint32_t ulStatus; \ + \ + /* Unmask all interrupts. */ \ + ulStatus = _CP0_GET_STATUS(); \ + ulStatus &= ~portALL_IPL_BITS; \ + _CP0_SET_STATUS( ulStatus ); \ +} extern void vTaskEnterCritical( void ); extern void vTaskExitCritical( void ); -#define portCRITICAL_NESTING_IN_TCB 1 -#define portENTER_CRITICAL() vTaskEnterCritical() -#define portEXIT_CRITICAL() vTaskExitCritical() +#define portCRITICAL_NESTING_IN_TCB 1 +#define portENTER_CRITICAL() vTaskEnterCritical() +#define portEXIT_CRITICAL() vTaskExitCritical() extern UBaseType_t uxPortSetInterruptMaskFromISR(); extern void vPortClearInterruptMaskFromISR( UBaseType_t ); -#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMaskFromISR() -#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) vPortClearInterruptMaskFromISR( uxSavedStatusRegister ) +#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMaskFromISR() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) vPortClearInterruptMaskFromISR( uxSavedStatusRegister ) #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION - #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #endif #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 -/* Check the configuration. */ - #if ( configMAX_PRIORITIES > 32 ) + /* Check the configuration. */ + #if( configMAX_PRIORITIES > 32 ) #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. #endif -/* Store/clear the ready priorities in a bit map. */ - #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) - #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) -/*-----------------------------------------------------------*/ + /*-----------------------------------------------------------*/ - #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - _clz( ( uxReadyPriorities ) ) ) + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - _clz( ( uxReadyPriorities ) ) ) #endif /* taskRECORD_READY_PRIORITY */ @@ -169,26 +169,26 @@ extern void vPortClearInterruptMaskFromISR( UBaseType_t ); /* Task utilities. */ -#define portYIELD() \ - { \ - uint32_t ulCause; \ - \ - /* Trigger software interrupt. */ \ - ulCause = _CP0_GET_CAUSE(); \ - ulCause |= portSW0_BIT; \ - _CP0_SET_CAUSE( ulCause ); \ - } +#define portYIELD() \ +{ \ +uint32_t ulCause; \ + \ + /* Trigger software interrupt. */ \ + ulCause = _CP0_GET_CAUSE(); \ + ulCause |= portSW0_BIT; \ + _CP0_SET_CAUSE( ulCause ); \ +} extern volatile UBaseType_t uxInterruptNesting; -#define portASSERT_IF_IN_ISR() configASSERT( uxInterruptNesting == 0 ) +#define portASSERT_IF_IN_ISR() configASSERT( uxInterruptNesting == 0 ) -#define portNOP() __asm volatile ( "nop" ) +#define portNOP() __asm volatile ( "nop" ) /*-----------------------------------------------------------*/ /* Task function macros as described on the FreeRTOS.org WEB site. */ -#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) __attribute__( ( noreturn ) ) -#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__((noreturn)) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) /*-----------------------------------------------------------*/ #define portEND_SWITCHING_ISR( xSwitchRequired ) \ diff --git a/portable/MPLAB/PIC32MZ/ISR_Support.h b/portable/MPLAB/PIC32MZ/ISR_Support.h index 459ee2e3f42..a9ddee0f4f5 100644 --- a/portable/MPLAB/PIC32MZ/ISR_Support.h +++ b/portable/MPLAB/PIC32MZ/ISR_Support.h @@ -28,406 +28,405 @@ #include "FreeRTOSConfig.h" -#define portCONTEXT_SIZE 160 -#define portEPC_STACK_LOCATION 152 -#define portSTATUS_STACK_LOCATION 156 -#define portFPCSR_STACK_LOCATION 0 -#define portTASK_HAS_FPU_STACK_LOCATION 0 -#define portFPU_CONTEXT_SIZE 264 +#define portCONTEXT_SIZE 160 +#define portEPC_STACK_LOCATION 152 +#define portSTATUS_STACK_LOCATION 156 +#define portFPCSR_STACK_LOCATION 0 +#define portTASK_HAS_FPU_STACK_LOCATION 0 +#define portFPU_CONTEXT_SIZE 264 /******************************************************************/ -.macro portSAVE_FPU_REGS offset, base - -/* Macro to assist with saving just the FPU registers to the - * specified address and base offset, - * offset is a constant, base is the base pointer register */ - -sdc1 $f31, \ offset + 248 ( \ base ) -sdc1 $f30, \ offset + 240 ( \ base ) -sdc1 $f29, \ offset + 232 ( \ base ) -sdc1 $f28, \ offset + 224 ( \ base ) -sdc1 $f27, \ offset + 216 ( \ base ) -sdc1 $f26, \ offset + 208 ( \ base ) -sdc1 $f25, \ offset + 200 ( \ base ) -sdc1 $f24, \ offset + 192 ( \ base ) -sdc1 $f23, \ offset + 184 ( \ base ) -sdc1 $f22, \ offset + 176 ( \ base ) -sdc1 $f21, \ offset + 168 ( \ base ) -sdc1 $f20, \ offset + 160 ( \ base ) -sdc1 $f19, \ offset + 152 ( \ base ) -sdc1 $f18, \ offset + 144 ( \ base ) -sdc1 $f17, \ offset + 136 ( \ base ) -sdc1 $f16, \ offset + 128 ( \ base ) -sdc1 $f15, \ offset + 120 ( \ base ) -sdc1 $f14, \ offset + 112 ( \ base ) -sdc1 $f13, \ offset + 104 ( \ base ) -sdc1 $f12, \ offset + 96 ( \ base ) -sdc1 $f11, \ offset + 88 ( \ base ) -sdc1 $f10, \ offset + 80 ( \ base ) -sdc1 $f9, \ offset + 72 ( \ base ) -sdc1 $f8, \ offset + 64 ( \ base ) -sdc1 $f7, \ offset + 56 ( \ base ) -sdc1 $f6, \ offset + 48 ( \ base ) -sdc1 $f5, \ offset + 40 ( \ base ) -sdc1 $f4, \ offset + 32 ( \ base ) -sdc1 $f3, \ offset + 24 ( \ base ) -sdc1 $f2, \ offset + 16 ( \ base ) -sdc1 $f1, \ offset + 8 ( \ base ) -sdc1 $f0, \ offset + 0 ( \ base ) - - .endm +.macro portSAVE_FPU_REGS offset, base + /* Macro to assist with saving just the FPU registers to the + * specified address and base offset, + * offset is a constant, base is the base pointer register */ + + sdc1 $f31, \offset + 248(\base) + sdc1 $f30, \offset + 240(\base) + sdc1 $f29, \offset + 232(\base) + sdc1 $f28, \offset + 224(\base) + sdc1 $f27, \offset + 216(\base) + sdc1 $f26, \offset + 208(\base) + sdc1 $f25, \offset + 200(\base) + sdc1 $f24, \offset + 192(\base) + sdc1 $f23, \offset + 184(\base) + sdc1 $f22, \offset + 176(\base) + sdc1 $f21, \offset + 168(\base) + sdc1 $f20, \offset + 160(\base) + sdc1 $f19, \offset + 152(\base) + sdc1 $f18, \offset + 144(\base) + sdc1 $f17, \offset + 136(\base) + sdc1 $f16, \offset + 128(\base) + sdc1 $f15, \offset + 120(\base) + sdc1 $f14, \offset + 112(\base) + sdc1 $f13, \offset + 104(\base) + sdc1 $f12, \offset + 96(\base) + sdc1 $f11, \offset + 88(\base) + sdc1 $f10, \offset + 80(\base) + sdc1 $f9, \offset + 72(\base) + sdc1 $f8, \offset + 64(\base) + sdc1 $f7, \offset + 56(\base) + sdc1 $f6, \offset + 48(\base) + sdc1 $f5, \offset + 40(\base) + sdc1 $f4, \offset + 32(\base) + sdc1 $f3, \offset + 24(\base) + sdc1 $f2, \offset + 16(\base) + sdc1 $f1, \offset + 8(\base) + sdc1 $f0, \offset + 0(\base) + + .endm /******************************************************************/ - .macro portLOAD_FPU_REGS offset, base - -/* Macro to assist with loading just the FPU registers from the - * specified address and base offset, offset is a constant, - * base is the base pointer register */ - -ldc1 $f0, \ offset + 0 ( \ base ) -ldc1 $f1, \ offset + 8 ( \ base ) -ldc1 $f2, \ offset + 16 ( \ base ) -ldc1 $f3, \ offset + 24 ( \ base ) -ldc1 $f4, \ offset + 32 ( \ base ) -ldc1 $f5, \ offset + 40 ( \ base ) -ldc1 $f6, \ offset + 48 ( \ base ) -ldc1 $f7, \ offset + 56 ( \ base ) -ldc1 $f8, \ offset + 64 ( \ base ) -ldc1 $f9, \ offset + 72 ( \ base ) -ldc1 $f10, \ offset + 80 ( \ base ) -ldc1 $f11, \ offset + 88 ( \ base ) -ldc1 $f12, \ offset + 96 ( \ base ) -ldc1 $f13, \ offset + 104 ( \ base ) -ldc1 $f14, \ offset + 112 ( \ base ) -ldc1 $f15, \ offset + 120 ( \ base ) -ldc1 $f16, \ offset + 128 ( \ base ) -ldc1 $f17, \ offset + 136 ( \ base ) -ldc1 $f18, \ offset + 144 ( \ base ) -ldc1 $f19, \ offset + 152 ( \ base ) -ldc1 $f20, \ offset + 160 ( \ base ) -ldc1 $f21, \ offset + 168 ( \ base ) -ldc1 $f22, \ offset + 176 ( \ base ) -ldc1 $f23, \ offset + 184 ( \ base ) -ldc1 $f24, \ offset + 192 ( \ base ) -ldc1 $f25, \ offset + 200 ( \ base ) -ldc1 $f26, \ offset + 208 ( \ base ) -ldc1 $f27, \ offset + 216 ( \ base ) -ldc1 $f28, \ offset + 224 ( \ base ) -ldc1 $f29, \ offset + 232 ( \ base ) -ldc1 $f30, \ offset + 240 ( \ base ) -ldc1 $f31, \ offset + 248 ( \ base ) - - .endm +.macro portLOAD_FPU_REGS offset, base + /* Macro to assist with loading just the FPU registers from the + * specified address and base offset, offset is a constant, + * base is the base pointer register */ + + ldc1 $f0, \offset + 0(\base) + ldc1 $f1, \offset + 8(\base) + ldc1 $f2, \offset + 16(\base) + ldc1 $f3, \offset + 24(\base) + ldc1 $f4, \offset + 32(\base) + ldc1 $f5, \offset + 40(\base) + ldc1 $f6, \offset + 48(\base) + ldc1 $f7, \offset + 56(\base) + ldc1 $f8, \offset + 64(\base) + ldc1 $f9, \offset + 72(\base) + ldc1 $f10, \offset + 80(\base) + ldc1 $f11, \offset + 88(\base) + ldc1 $f12, \offset + 96(\base) + ldc1 $f13, \offset + 104(\base) + ldc1 $f14, \offset + 112(\base) + ldc1 $f15, \offset + 120(\base) + ldc1 $f16, \offset + 128(\base) + ldc1 $f17, \offset + 136(\base) + ldc1 $f18, \offset + 144(\base) + ldc1 $f19, \offset + 152(\base) + ldc1 $f20, \offset + 160(\base) + ldc1 $f21, \offset + 168(\base) + ldc1 $f22, \offset + 176(\base) + ldc1 $f23, \offset + 184(\base) + ldc1 $f24, \offset + 192(\base) + ldc1 $f25, \offset + 200(\base) + ldc1 $f26, \offset + 208(\base) + ldc1 $f27, \offset + 216(\base) + ldc1 $f28, \offset + 224(\base) + ldc1 $f29, \offset + 232(\base) + ldc1 $f30, \offset + 240(\base) + ldc1 $f31, \offset + 248(\base) + + .endm /******************************************************************/ - .macro portSAVE_CONTEXT - -/* Make room for the context. First save the current status so it can be - * manipulated, and the cause and EPC registers so their original values are - * captured. */ -mfc0 k0, _CP0_CAUSE -addiu sp, sp, -portCONTEXT_SIZE - -#if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) - -/* Test if we are already using the system stack. Only tasks may use the - * FPU so if we are already in a nested interrupt then the FPU context does - * not require saving. */ - la k1, uxInterruptNesting - lw k1, 0 ( k1 ) - bne k1, zero, 2f +.macro portSAVE_CONTEXT + + /* Make room for the context. First save the current status so it can be + manipulated, and the cause and EPC registers so their original values are + captured. */ + mfc0 k0, _CP0_CAUSE + addiu sp, sp, -portCONTEXT_SIZE + + #if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) + /* Test if we are already using the system stack. Only tasks may use the + FPU so if we are already in a nested interrupt then the FPU context does + not require saving. */ + la k1, uxInterruptNesting + lw k1, 0(k1) + bne k1, zero, 2f + nop + + /* Test if the current task needs the FPU context saving. */ + la k1, ulTaskHasFPUContext + lw k1, 0(k1) + beq k1, zero, 1f + nop + + /* Adjust the stack to account for the additional FPU context.*/ + addiu sp, sp, -portFPU_CONTEXT_SIZE + + 1: + /* Save the ulTaskHasFPUContext flag. */ + sw k1, portTASK_HAS_FPU_STACK_LOCATION(sp) + + 2: + #endif + + mfc0 k1, _CP0_STATUS + + /* Also save s7, s6 and s5 so they can be used. Any nesting interrupts + should maintain the values of these registers across the ISR. */ + sw s7, 48(sp) + sw s6, 44(sp) + sw s5, 40(sp) + sw k1, portSTATUS_STACK_LOCATION(sp) + + /* Prepare to enable interrupts above the current priority. */ + srl k0, k0, 0xa + ins k1, k0, 10, 7 + srl k0, k0, 0x7 /* This copies the MSB of the IPL, but it would be an error if it was set anyway. */ + ins k1, k0, 18, 1 + ins k1, zero, 1, 4 + + /* s5 is used as the frame pointer. */ + add s5, zero, sp + + /* Check the nesting count value. */ + la k0, uxInterruptNesting + lw s6, (k0) + + /* If the nesting count is 0 then swap to the the system stack, otherwise + the system stack is already being used. */ + bne s6, zero, 1f nop -/* Test if the current task needs the FPU context saving. */ - la k1, ulTaskHasFPUContext - lw k1, 0 ( k1 ) - beq k1, zero, 1f + /* Swap to the system stack. */ + la sp, xISRStackTop + lw sp, (sp) + + /* Increment and save the nesting count. */ +1: addiu s6, s6, 1 + sw s6, 0(k0) + + /* s6 holds the EPC value, this is saved after interrupts are re-enabled. */ + mfc0 s6, _CP0_EPC + + /* Re-enable interrupts. */ + mtc0 k1, _CP0_STATUS + + /* Save the context into the space just created. s6 is saved again + here as it now contains the EPC value. No other s registers need be + saved. */ + sw ra, 120(s5) + sw s8, 116(s5) + sw t9, 112(s5) + sw t8, 108(s5) + sw t7, 104(s5) + sw t6, 100(s5) + sw t5, 96(s5) + sw t4, 92(s5) + sw t3, 88(s5) + sw t2, 84(s5) + sw t1, 80(s5) + sw t0, 76(s5) + sw a3, 72(s5) + sw a2, 68(s5) + sw a1, 64(s5) + sw a0, 60(s5) + sw v1, 56(s5) + sw v0, 52(s5) + sw s6, portEPC_STACK_LOCATION(s5) + sw $1, 16(s5) + + /* Save the AC0, AC1, AC2, AC3 registers from the DSP. s6 is used as a + scratch register. */ + mfhi s6, $ac1 + sw s6, 128(s5) + mflo s6, $ac1 + sw s6, 124(s5) + + mfhi s6, $ac2 + sw s6, 136(s5) + mflo s6, $ac2 + sw s6, 132(s5) + + mfhi s6, $ac3 + sw s6, 144(s5) + mflo s6, $ac3 + sw s6, 140(s5) + + /* Save the DSP Control register */ + rddsp s6 + sw s6, 148(s5) + + /* ac0 is done separately to match the MX port. */ + mfhi s6, $ac0 + sw s6, 12(s5) + mflo s6, $ac0 + sw s6, 8(s5) + + /* Save the FPU context if the nesting count was zero. */ + #if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) + la s6, uxInterruptNesting + lw s6, 0(s6) + addiu s6, s6, -1 + bne s6, zero, 1f + nop + + /* Test if the current task needs the FPU context saving. */ + lw s6, portTASK_HAS_FPU_STACK_LOCATION(s5) + beq s6, zero, 1f + nop + + /* Save the FPU registers. */ + portSAVE_FPU_REGS ( portCONTEXT_SIZE + 8 ), s5 + + /* Save the FPU status register */ + cfc1 s6, $f31 + sw s6, (portCONTEXT_SIZE + portFPCSR_STACK_LOCATION)(s5) + + 1: + #endif + + /* Update the task stack pointer value if nesting is zero. */ + la s6, uxInterruptNesting + lw s6, (s6) + addiu s6, s6, -1 + bne s6, zero, 1f nop -/* Adjust the stack to account for the additional FPU context.*/ - addiu sp, sp, -portFPU_CONTEXT_SIZE - - 1 : - /* Save the ulTaskHasFPUContext flag. */ - sw k1, portTASK_HAS_FPU_STACK_LOCATION( sp ) - - 2 : -#endif /* if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) */ - -mfc0 k1, _CP0_STATUS - -/* Also save s7, s6 and s5 so they can be used. Any nesting interrupts - * should maintain the values of these registers across the ISR. */ -sw s7, 48 ( sp ) -sw s6, 44 ( sp ) -sw s5, 40 ( sp ) -sw k1, portSTATUS_STACK_LOCATION( sp ) - -/* Prepare to enable interrupts above the current priority. */ -srl k0, k0, 0xa -ins k1, k0, 10, 7 -srl k0, k0, 0x7 /* This copies the MSB of the IPL, but it would be an error if it was set anyway. */ -ins k1, k0, 18, 1 -ins k1, zero, 1, 4 - -/* s5 is used as the frame pointer. */ -add s5, zero, sp - -/* Check the nesting count value. */ -la k0, uxInterruptNesting -lw s6, ( k0 ) - -/* If the nesting count is 0 then swap to the the system stack, otherwise - * the system stack is already being used. */ -bne s6, zero, 1f -nop - -/* Swap to the system stack. */ -la sp, xISRStackTop -lw sp, ( sp ) - -/* Increment and save the nesting count. */ -1 : addiu s6, s6, 1 -sw s6, 0 ( k0 ) - -/* s6 holds the EPC value, this is saved after interrupts are re-enabled. */ -mfc0 s6, _CP0_EPC - -/* Re-enable interrupts. */ -mtc0 k1, _CP0_STATUS - -/* Save the context into the space just created. s6 is saved again - * here as it now contains the EPC value. No other s registers need be - * saved. */ -sw ra, 120 ( s5 ) -sw s8, 116 ( s5 ) -sw t9, 112 ( s5 ) -sw t8, 108 ( s5 ) -sw t7, 104 ( s5 ) -sw t6, 100 ( s5 ) -sw t5, 96 ( s5 ) -sw t4, 92 ( s5 ) -sw t3, 88 ( s5 ) -sw t2, 84 ( s5 ) -sw t1, 80 ( s5 ) -sw t0, 76 ( s5 ) -sw a3, 72 ( s5 ) -sw a2, 68 ( s5 ) -sw a1, 64 ( s5 ) -sw a0, 60 ( s5 ) -sw v1, 56 ( s5 ) -sw v0, 52 ( s5 ) -sw s6, portEPC_STACK_LOCATION( s5 ) -sw $1, 16 ( s5 ) - -/* Save the AC0, AC1, AC2, AC3 registers from the DSP. s6 is used as a - * scratch register. */ -mfhi s6, $ac1 -sw s6, 128 ( s5 ) -mflo s6, $ac1 -sw s6, 124 ( s5 ) - -mfhi s6, $ac2 -sw s6, 136 ( s5 ) -mflo s6, $ac2 -sw s6, 132 ( s5 ) - -mfhi s6, $ac3 -sw s6, 144 ( s5 ) -mflo s6, $ac3 -sw s6, 140 ( s5 ) - -/* Save the DSP Control register */ -rddsp s6 -sw s6, 148 ( s5 ) - -/* ac0 is done separately to match the MX port. */ -mfhi s6, $ac0 -sw s6, 12 ( s5 ) -mflo s6, $ac0 -sw s6, 8 ( s5 ) - -/* Save the FPU context if the nesting count was zero. */ -#if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) - la s6, uxInterruptNesting - lw s6, 0 ( s6 ) - addiu s6, s6, -1 - bne s6, zero, 1f - nop - -/* Test if the current task needs the FPU context saving. */ - lw s6, portTASK_HAS_FPU_STACK_LOCATION( s5 ) - beq s6, zero, 1f - nop - /* Save the FPU registers. */ - portSAVE_FPU_REGS( portCONTEXT_SIZE + 8 ), s5 - -/* Save the FPU status register */ - cfc1 s6, $f31 - sw s6, ( portCONTEXT_SIZE + portFPCSR_STACK_LOCATION )( s5 ) - - 1 : -#endif /* if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) */ - -/* Update the task stack pointer value if nesting is zero. */ -la s6, uxInterruptNesting -lw s6, ( s6 ) -addiu s6, s6, -1 -bne s6, zero, 1f -nop - -/* Save the stack pointer. */ -la s6, uxSavedTaskStackPointer -sw s5, ( s6 ) -1 : -.endm + /* Save the stack pointer. */ + la s6, uxSavedTaskStackPointer + sw s5, (s6) +1: + .endm /******************************************************************/ - .macro portRESTORE_CONTEXT - -/* Restore the stack pointer from the TCB. This is only done if the - * nesting count is 1. */ -la s6, uxInterruptNesting -lw s6, ( s6 ) -addiu s6, s6, -1 -bne s6, zero, 1f -nop -la s6, uxSavedTaskStackPointer -lw s5, ( s6 ) - -#if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) - /* Restore the FPU context if required. */ - lw s6, portTASK_HAS_FPU_STACK_LOCATION( s5 ) - beq s6, zero, 1f - nop - /* Restore the FPU registers. */ - portLOAD_FPU_REGS( portCONTEXT_SIZE + 8 ), s5 - -/* Restore the FPU status register. */ - lw s6, ( portCONTEXT_SIZE + portFPCSR_STACK_LOCATION )( s5 ) - ctc1 s6, $f31 -#endif /* if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) */ - -1 : - -/* Restore the context. */ -lw s6, 128 ( s5 ) -mthi s6, $ac1 -lw s6, 124 ( s5 ) -mtlo s6, $ac1 - -lw s6, 136 ( s5 ) -mthi s6, $ac2 -lw s6, 132 ( s5 ) -mtlo s6, $ac2 - -lw s6, 144 ( s5 ) -mthi s6, $ac3 -lw s6, 140 ( s5 ) -mtlo s6, $ac3 - -/* Restore DSPControl. */ -lw s6, 148 ( s5 ) -wrdsp s6 - -lw s6, 8 ( s5 ) -mtlo s6, $ac0 -lw s6, 12 ( s5 ) -mthi s6, $ac0 -lw $1, 16 ( s5 ) - -/* s6 is loaded as it was used as a scratch register and therefore saved - * as part of the interrupt context. */ -lw s7, 48 ( s5 ) -lw s6, 44 ( s5 ) -lw v0, 52 ( s5 ) -lw v1, 56 ( s5 ) -lw a0, 60 ( s5 ) -lw a1, 64 ( s5 ) -lw a2, 68 ( s5 ) -lw a3, 72 ( s5 ) -lw t0, 76 ( s5 ) -lw t1, 80 ( s5 ) -lw t2, 84 ( s5 ) -lw t3, 88 ( s5 ) -lw t4, 92 ( s5 ) -lw t5, 96 ( s5 ) -lw t6, 100 ( s5 ) -lw t7, 104 ( s5 ) -lw t8, 108 ( s5 ) -lw t9, 112 ( s5 ) -lw s8, 116 ( s5 ) -lw ra, 120 ( s5 ) - -/* Protect access to the k registers, and others. */ -di -ehb - -/* Decrement the nesting count. */ -la k0, uxInterruptNesting -lw k1, ( k0 ) -addiu k1, k1, -1 -sw k1, 0 ( k0 ) - -#if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) - /* If the nesting count is now zero then the FPU context may be restored. */ - bne k1, zero, 1f +.macro portRESTORE_CONTEXT + + /* Restore the stack pointer from the TCB. This is only done if the + nesting count is 1. */ + la s6, uxInterruptNesting + lw s6, (s6) + addiu s6, s6, -1 + bne s6, zero, 1f nop - -/* Restore the value of ulTaskHasFPUContext */ - la k0, ulTaskHasFPUContext - lw k1, 0 ( s5 ) - sw k1, 0 ( k0 ) - -/* If the task does not have an FPU context then adjust the stack normally. */ - beq k1, zero, 1f + la s6, uxSavedTaskStackPointer + lw s5, (s6) + + #if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) + /* Restore the FPU context if required. */ + lw s6, portTASK_HAS_FPU_STACK_LOCATION(s5) + beq s6, zero, 1f + nop + + /* Restore the FPU registers. */ + portLOAD_FPU_REGS ( portCONTEXT_SIZE + 8 ), s5 + + /* Restore the FPU status register. */ + lw s6, ( portCONTEXT_SIZE + portFPCSR_STACK_LOCATION )(s5) + ctc1 s6, $f31 + #endif + +1: + + /* Restore the context. */ + lw s6, 128(s5) + mthi s6, $ac1 + lw s6, 124(s5) + mtlo s6, $ac1 + + lw s6, 136(s5) + mthi s6, $ac2 + lw s6, 132(s5) + mtlo s6, $ac2 + + lw s6, 144(s5) + mthi s6, $ac3 + lw s6, 140(s5) + mtlo s6, $ac3 + + /* Restore DSPControl. */ + lw s6, 148(s5) + wrdsp s6 + + lw s6, 8(s5) + mtlo s6, $ac0 + lw s6, 12(s5) + mthi s6, $ac0 + lw $1, 16(s5) + + /* s6 is loaded as it was used as a scratch register and therefore saved + as part of the interrupt context. */ + lw s7, 48(s5) + lw s6, 44(s5) + lw v0, 52(s5) + lw v1, 56(s5) + lw a0, 60(s5) + lw a1, 64(s5) + lw a2, 68(s5) + lw a3, 72(s5) + lw t0, 76(s5) + lw t1, 80(s5) + lw t2, 84(s5) + lw t3, 88(s5) + lw t4, 92(s5) + lw t5, 96(s5) + lw t6, 100(s5) + lw t7, 104(s5) + lw t8, 108(s5) + lw t9, 112(s5) + lw s8, 116(s5) + lw ra, 120(s5) + + /* Protect access to the k registers, and others. */ + di + ehb + + /* Decrement the nesting count. */ + la k0, uxInterruptNesting + lw k1, (k0) + addiu k1, k1, -1 + sw k1, 0(k0) + + #if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) + /* If the nesting count is now zero then the FPU context may be restored. */ + bne k1, zero, 1f + nop + + /* Restore the value of ulTaskHasFPUContext */ + la k0, ulTaskHasFPUContext + lw k1, 0(s5) + sw k1, 0(k0) + + /* If the task does not have an FPU context then adjust the stack normally. */ + beq k1, zero, 1f + nop + + /* Restore the STATUS and EPC registers */ + lw k0, portSTATUS_STACK_LOCATION(s5) + lw k1, portEPC_STACK_LOCATION(s5) + + /* Leave the stack in its original state. First load sp from s5, then + restore s5 from the stack. */ + add sp, zero, s5 + lw s5, 40(sp) + + /* Adjust the stack pointer to remove the FPU context */ + addiu sp, sp, portFPU_CONTEXT_SIZE + beq zero, zero, 2f + nop + + 1: /* Restore the STATUS and EPC registers */ + lw k0, portSTATUS_STACK_LOCATION(s5) + lw k1, portEPC_STACK_LOCATION(s5) + + /* Leave the stack in its original state. First load sp from s5, then + restore s5 from the stack. */ + add sp, zero, s5 + lw s5, 40(sp) + + 2: /* Adjust the stack pointer */ + addiu sp, sp, portCONTEXT_SIZE + + #else + + /* Restore the frame when there is no hardware FP support. */ + lw k0, portSTATUS_STACK_LOCATION(s5) + lw k1, portEPC_STACK_LOCATION(s5) + + /* Leave the stack in its original state. First load sp from s5, then + restore s5 from the stack. */ + add sp, zero, s5 + lw s5, 40(sp) + + addiu sp, sp, portCONTEXT_SIZE + + #endif // ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) + + mtc0 k0, _CP0_STATUS + mtc0 k1, _CP0_EPC + ehb + eret nop -/* Restore the STATUS and EPC registers */ - lw k0, portSTATUS_STACK_LOCATION( s5 ) - lw k1, portEPC_STACK_LOCATION( s5 ) - -/* Leave the stack in its original state. First load sp from s5, then - * restore s5 from the stack. */ - add sp, zero, s5 - lw s5, 40 ( sp ) - -/* Adjust the stack pointer to remove the FPU context */ - addiu sp, sp, portFPU_CONTEXT_SIZE - beq zero, zero, 2f - nop - - 1 : /* Restore the STATUS and EPC registers */ - lw k0, portSTATUS_STACK_LOCATION( s5 ) - lw k1, portEPC_STACK_LOCATION( s5 ) - -/* Leave the stack in its original state. First load sp from s5, then - * restore s5 from the stack. */ - add sp, zero, s5 - lw s5, 40 ( sp ) - - 2 : /* Adjust the stack pointer */ - addiu sp, sp, portCONTEXT_SIZE - -#else /* if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) */ - -/* Restore the frame when there is no hardware FP support. */ - lw k0, portSTATUS_STACK_LOCATION( s5 ) - lw k1, portEPC_STACK_LOCATION( s5 ) - -/* Leave the stack in its original state. First load sp from s5, then - * restore s5 from the stack. */ - add sp, zero, s5 - lw s5, 40 ( sp ) - - addiu sp, sp, portCONTEXT_SIZE - -#endif // ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) - -mtc0 k0, _CP0_STATUS -mtc0 k1, _CP0_EPC -ehb -eret -nop - - .endm + .endm diff --git a/portable/MPLAB/PIC32MZ/port.c b/portable/MPLAB/PIC32MZ/port.c index dafbf1d942b..b8b5708fef2 100644 --- a/portable/MPLAB/PIC32MZ/port.c +++ b/portable/MPLAB/PIC32MZ/port.c @@ -27,8 +27,8 @@ */ /*----------------------------------------------------------- -* Implementation of functions defined in portable.h for the PIC32MZ port. -*----------------------------------------------------------*/ + * Implementation of functions defined in portable.h for the PIC32MZ port. + *----------------------------------------------------------*/ /* Microchip specific headers. */ #include @@ -40,62 +40,62 @@ #include "FreeRTOS.h" #include "task.h" -#if !defined( __PIC32MZ__ ) +#if !defined(__PIC32MZ__) #error This port is designed to work with XC32 on PIC32MZ MCUs. Please update your C compiler version or settings. #endif -#if ( ( configMAX_SYSCALL_INTERRUPT_PRIORITY >= 0x7 ) || ( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 ) ) +#if( ( configMAX_SYSCALL_INTERRUPT_PRIORITY >= 0x7 ) || ( configMAX_SYSCALL_INTERRUPT_PRIORITY == 0 ) ) #error configMAX_SYSCALL_INTERRUPT_PRIORITY must be less than 7 and greater than 0 #endif /* Hardware specifics. */ -#define portTIMER_PRESCALE 8 -#define portPRESCALE_BITS 1 +#define portTIMER_PRESCALE 8 +#define portPRESCALE_BITS 1 /* Bits within various registers. */ -#define portIE_BIT ( 0x00000001 ) -#define portEXL_BIT ( 0x00000002 ) -#define portMX_BIT ( 0x01000000 ) /* Allow access to DSP instructions. */ -#define portCU1_BIT ( 0x20000000 ) /* enable CP1 for parts with hardware. */ -#define portFR_BIT ( 0x04000000 ) /* Enable 64 bit floating point registers. */ +#define portIE_BIT ( 0x00000001 ) +#define portEXL_BIT ( 0x00000002 ) +#define portMX_BIT ( 0x01000000 ) /* Allow access to DSP instructions. */ +#define portCU1_BIT ( 0x20000000 ) /* enable CP1 for parts with hardware. */ +#define portFR_BIT ( 0x04000000 ) /* Enable 64 bit floating point registers. */ /* Bits within the CAUSE register. */ -#define portCORE_SW_0 ( 0x00000100 ) -#define portCORE_SW_1 ( 0x00000200 ) +#define portCORE_SW_0 ( 0x00000100 ) +#define portCORE_SW_1 ( 0x00000200 ) /* The EXL bit is set to ensure interrupts do not occur while the context of - * the first task is being restored. */ +the first task is being restored. */ #if ( __mips_hard_float == 1 ) - #define portINITIAL_SR ( portIE_BIT | portEXL_BIT | portMX_BIT | portFR_BIT | portCU1_BIT ) + #define portINITIAL_SR ( portIE_BIT | portEXL_BIT | portMX_BIT | portFR_BIT | portCU1_BIT ) #else - #define portINITIAL_SR ( portIE_BIT | portEXL_BIT | portMX_BIT ) + #define portINITIAL_SR ( portIE_BIT | portEXL_BIT | portMX_BIT ) #endif /* The initial value to store into the FPU status and control register. This is - * only used on parts that support a hardware FPU. */ -#define portINITIAL_FPSCR ( 0x1000000 ) /* High perf on denormal ops */ + only used on parts that support a hardware FPU. */ +#define portINITIAL_FPSCR (0x1000000) /* High perf on denormal ops */ /* - * By default port.c generates its tick interrupt from TIMER1. The user can - * override this behaviour by: - * 1: Providing their own implementation of vApplicationSetupTickTimerInterrupt(), - * which is the function that configures the timer. The function is defined - * as a weak symbol in this file so if the same function name is used in the - * application code then the version in the application code will be linked - * into the application in preference to the version defined in this file. - * 2: Define configTICK_INTERRUPT_VECTOR to the vector number of the timer used - * to generate the tick interrupt. For example, when timer 1 is used then - * configTICK_INTERRUPT_VECTOR is set to _TIMER_1_VECTOR. - * configTICK_INTERRUPT_VECTOR should be defined in FreeRTOSConfig.h. - * 3: Define configCLEAR_TICK_TIMER_INTERRUPT() to clear the interrupt in the - * timer used to generate the tick interrupt. For example, when timer 1 is - * used configCLEAR_TICK_TIMER_INTERRUPT() is defined to - * IFS0CLR = _IFS0_T1IF_MASK. - */ +By default port.c generates its tick interrupt from TIMER1. The user can +override this behaviour by: + 1: Providing their own implementation of vApplicationSetupTickTimerInterrupt(), + which is the function that configures the timer. The function is defined + as a weak symbol in this file so if the same function name is used in the + application code then the version in the application code will be linked + into the application in preference to the version defined in this file. + 2: Define configTICK_INTERRUPT_VECTOR to the vector number of the timer used + to generate the tick interrupt. For example, when timer 1 is used then + configTICK_INTERRUPT_VECTOR is set to _TIMER_1_VECTOR. + configTICK_INTERRUPT_VECTOR should be defined in FreeRTOSConfig.h. + 3: Define configCLEAR_TICK_TIMER_INTERRUPT() to clear the interrupt in the + timer used to generate the tick interrupt. For example, when timer 1 is + used configCLEAR_TICK_TIMER_INTERRUPT() is defined to + IFS0CLR = _IFS0_T1IF_MASK. +*/ #ifndef configTICK_INTERRUPT_VECTOR - #define configTICK_INTERRUPT_VECTOR _TIMER_1_VECTOR - #define configCLEAR_TICK_TIMER_INTERRUPT() IFS0CLR = _IFS0_T1IF_MASK + #define configTICK_INTERRUPT_VECTOR _TIMER_1_VECTOR + #define configCLEAR_TICK_TIMER_INTERRUPT() IFS0CLR = _IFS0_T1IF_MASK #else #ifndef configCLEAR_TICK_TIMER_INTERRUPT #error If configTICK_INTERRUPT_VECTOR is defined in application code then configCLEAR_TICK_TIMER_INTERRUPT must also be defined in application code. @@ -103,36 +103,34 @@ #endif /* Let the user override the pre-loading of the initial RA with the address of - * prvTaskExitError() in case it messes up unwinding of the stack in the - * debugger - in which case configTASK_RETURN_ADDRESS can be defined as 0 (NULL). */ +prvTaskExitError() in case it messes up unwinding of the stack in the +debugger - in which case configTASK_RETURN_ADDRESS can be defined as 0 (NULL). */ #ifdef configTASK_RETURN_ADDRESS - #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS + #define portTASK_RETURN_ADDRESS configTASK_RETURN_ADDRESS #else - #define portTASK_RETURN_ADDRESS prvTaskExitError + #define portTASK_RETURN_ADDRESS prvTaskExitError #endif /* Set configCHECK_FOR_STACK_OVERFLOW to 3 to add ISR stack checking to task - * stack checking. A problem in the ISR stack will trigger an assert, not call the - * stack overflow hook function (because the stack overflow hook is specific to a - * task stack, not the ISR stack). */ -#if ( configCHECK_FOR_STACK_OVERFLOW > 2 ) - -/* Don't use 0xa5 as the stack fill bytes as that is used by the kernel for - * the task stacks, and so will legitimately appear in many positions within - * the ISR stack. */ - #define portISR_STACK_FILL_BYTE 0xee - - static const uint8_t ucExpectedStackBytes[] = - { - portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ - portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ - portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ - portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ - portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE - }; \ - - #define portCHECK_ISR_STACK() configASSERT( ( memcmp( ( void * ) xISRStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) == 0 ) ) -#else /* if ( configCHECK_FOR_STACK_OVERFLOW > 2 ) */ +stack checking. A problem in the ISR stack will trigger an assert, not call the +stack overflow hook function (because the stack overflow hook is specific to a +task stack, not the ISR stack). */ +#if( configCHECK_FOR_STACK_OVERFLOW > 2 ) + + /* Don't use 0xa5 as the stack fill bytes as that is used by the kernel for + the task stacks, and so will legitimately appear in many positions within + the ISR stack. */ + #define portISR_STACK_FILL_BYTE 0xee + + static const uint8_t ucExpectedStackBytes[] = { + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, \ + portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE, portISR_STACK_FILL_BYTE }; \ + + #define portCHECK_ISR_STACK() configASSERT( ( memcmp( ( void * ) xISRStack, ( void * ) ucExpectedStackBytes, sizeof( ucExpectedStackBytes ) ) == 0 ) ) +#else /* Define the function away. */ #define portCHECK_ISR_STACK() #endif /* configCHECK_FOR_STACK_OVERFLOW > 2 */ @@ -147,23 +145,23 @@ static void prvTaskExitError( void ); /*-----------------------------------------------------------*/ /* Records the interrupt nesting depth. This is initialised to one as it is - * decremented to 0 when the first task starts. */ +decremented to 0 when the first task starts. */ volatile UBaseType_t uxInterruptNesting = 0x01; /* Stores the task stack pointer when a switch is made to use the system stack. */ UBaseType_t uxSavedTaskStackPointer = 0; /* The stack used by interrupt service routines that cause a context switch. */ -__attribute__( ( aligned( 8 ) ) ) StackType_t xISRStack[ configISR_STACK_SIZE ] = { 0 }; +__attribute__ ((aligned(8))) StackType_t xISRStack[ configISR_STACK_SIZE ] = { 0 }; /* The top of stack value ensures there is enough space to store 6 registers on - * the callers stack, as some functions seem to want to do this. 8 byte alignment - * is required to allow double word floating point stack pushes generated by the - * compiler. */ +the callers stack, as some functions seem to want to do this. 8 byte alignment +is required to allow double word floating point stack pushes generated by the +compiler. */ const StackType_t * const xISRStackTop = &( xISRStack[ ( configISR_STACK_SIZE & ~portBYTE_ALIGNMENT_MASK ) - 8 ] ); /* Saved as part of the task context. Set to pdFALSE if the task does not - * require an FPU context. */ + require an FPU context. */ #if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) uint32_t ulTaskHasFPUContext = 0; #endif @@ -173,39 +171,37 @@ const StackType_t * const xISRStackTop = &( xISRStack[ ( configISR_STACK_SIZE & /* * See header file for description. */ -StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, - TaskFunction_t pxCode, - void * pvParameters ) +StackType_t *pxPortInitialiseStack( StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters ) { /* Ensure 8 byte alignment is maintained when leaving this function. */ pxTopOfStack--; pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0xDEADBEEF; + *pxTopOfStack = (StackType_t) 0xDEADBEEF; pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x12345678; /* Word to which the stack pointer will be left pointing after context restore. */ + *pxTopOfStack = (StackType_t) 0x12345678; /* Word to which the stack pointer will be left pointing after context restore. */ pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) _CP0_GET_CAUSE(); + *pxTopOfStack = (StackType_t) _CP0_GET_CAUSE(); pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) portINITIAL_SR; /* CP0_STATUS */ + *pxTopOfStack = (StackType_t) portINITIAL_SR;/* CP0_STATUS */ pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) pxCode; /* CP0_EPC */ + *pxTopOfStack = (StackType_t) pxCode; /* CP0_EPC */ pxTopOfStack--; - *pxTopOfStack = ( StackType_t ) 0x00000000; /* DSPControl */ - pxTopOfStack -= 7; /* Includes space for AC1 - AC3. */ + *pxTopOfStack = (StackType_t) 0x00000000; /* DSPControl */ + pxTopOfStack -= 7; /* Includes space for AC1 - AC3. */ - *pxTopOfStack = ( StackType_t ) portTASK_RETURN_ADDRESS; /* ra */ + *pxTopOfStack = (StackType_t) portTASK_RETURN_ADDRESS; /* ra */ pxTopOfStack -= 15; - *pxTopOfStack = ( StackType_t ) pvParameters; /* Parameters to pass in. */ + *pxTopOfStack = (StackType_t) pvParameters; /* Parameters to pass in. */ pxTopOfStack -= 15; - *pxTopOfStack = ( StackType_t ) pdFALSE; /*by default disable FPU context save on parts with FPU */ + *pxTopOfStack = (StackType_t) pdFALSE; /*by default disable FPU context save on parts with FPU */ return pxTopOfStack; } @@ -214,17 +210,14 @@ StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack, static void prvTaskExitError( void ) { /* A function that implements a task must not exit or attempt to return to - * its caller as there is nothing to return to. If a task wants to exit it - * should instead call vTaskDelete( NULL ). - * - * Artificially force an assert() to be triggered if configASSERT() is - * defined, then stop here so application writers can catch the error. */ + its caller as there is nothing to return to. If a task wants to exit it + should instead call vTaskDelete( NULL ). + + Artificially force an assert() to be triggered if configASSERT() is + defined, then stop here so application writers can catch the error. */ configASSERT( uxSavedTaskStackPointer == 0UL ); portDISABLE_INTERRUPTS(); - - for( ; ; ) - { - } + for( ;; ); } /*-----------------------------------------------------------*/ @@ -237,9 +230,9 @@ static void prvTaskExitError( void ) * vector number. When Timer 1 is used the vector number is defined as * _TIMER_1_VECTOR. */ -__attribute__( ( weak ) ) void vApplicationSetupTickTimerInterrupt( void ) +__attribute__(( weak )) void vApplicationSetupTickTimerInterrupt( void ) { - const uint32_t ulCompareMatch = ( ( configPERIPHERAL_CLOCK_HZ / portTIMER_PRESCALE ) / configTICK_RATE_HZ ) - 1UL; +const uint32_t ulCompareMatch = ( (configPERIPHERAL_CLOCK_HZ / portTIMER_PRESCALE) / configTICK_RATE_HZ ) - 1UL; T1CON = 0x0000; T1CONbits.TCKPS = portPRESCALE_BITS; @@ -257,18 +250,18 @@ __attribute__( ( weak ) ) void vApplicationSetupTickTimerInterrupt( void ) } /*-----------------------------------------------------------*/ -void vPortEndScheduler( void ) +void vPortEndScheduler(void) { /* Not implemented in ports where there is nothing to return to. - * Artificially force an assert. */ + Artificially force an assert. */ configASSERT( uxInterruptNesting == 1000UL ); } /*-----------------------------------------------------------*/ BaseType_t xPortStartScheduler( void ) { - extern void vPortStartFirstTask( void ); - extern void * pxCurrentTCB; +extern void vPortStartFirstTask( void ); +extern void *pxCurrentTCB; #if ( configCHECK_FOR_STACK_OVERFLOW > 2 ) { @@ -289,18 +282,18 @@ BaseType_t xPortStartScheduler( void ) IEC0SET = 1 << _IEC0_CS0IE_POSITION; /* Setup the timer to generate the tick. Interrupts will have been - * disabled by the time we get here. */ + disabled by the time we get here. */ vApplicationSetupTickTimerInterrupt(); /* Kick off the highest priority task that has been created so far. - * Its stack location is loaded into uxSavedTaskStackPointer. */ + Its stack location is loaded into uxSavedTaskStackPointer. */ uxSavedTaskStackPointer = *( UBaseType_t * ) pxCurrentTCB; vPortStartFirstTask(); /* Should never get here as the tasks will now be executing! Call the task - * exit error function to prevent compiler warnings about a static function - * not being called in the case that the application writer overrides this - * functionality by defining configTASK_RETURN_ADDRESS. */ + exit error function to prevent compiler warnings about a static function + not being called in the case that the application writer overrides this + functionality by defining configTASK_RETURN_ADDRESS. */ prvTaskExitError(); return pdFALSE; @@ -309,7 +302,7 @@ BaseType_t xPortStartScheduler( void ) void vPortIncrementTick( void ) { - UBaseType_t uxSavedStatus; +UBaseType_t uxSavedStatus; uxSavedStatus = uxPortSetInterruptMaskFromISR(); { @@ -331,17 +324,16 @@ void vPortIncrementTick( void ) UBaseType_t uxPortSetInterruptMaskFromISR( void ) { - UBaseType_t uxSavedStatusRegister; +UBaseType_t uxSavedStatusRegister; __builtin_disable_interrupts(); uxSavedStatusRegister = _CP0_GET_STATUS() | 0x01; - /* This clears the IPL bits, then sets them to - * configMAX_SYSCALL_INTERRUPT_PRIORITY. This function should not be called - * from an interrupt that has a priority above - * configMAX_SYSCALL_INTERRUPT_PRIORITY so, when used correctly, the action - * can only result in the IPL being unchanged or raised, and therefore never - * lowered. */ + configMAX_SYSCALL_INTERRUPT_PRIORITY. This function should not be called + from an interrupt that has a priority above + configMAX_SYSCALL_INTERRUPT_PRIORITY so, when used correctly, the action + can only result in the IPL being unchanged or raised, and therefore never + lowered. */ _CP0_SET_STATUS( ( ( uxSavedStatusRegister & ( ~portALL_IPL_BITS ) ) ) | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ); return uxSavedStatusRegister; @@ -356,17 +348,17 @@ void vPortClearInterruptMaskFromISR( UBaseType_t uxSavedStatusRegister ) #if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) - void vPortTaskUsesFPU( void ) + void vPortTaskUsesFPU(void) { - extern void vPortInitialiseFPSCR( uint32_t uxFPSCRInit ); + extern void vPortInitialiseFPSCR( uint32_t uxFPSCRInit ); portENTER_CRITICAL(); /* Initialise the floating point status register. */ - vPortInitialiseFPSCR( portINITIAL_FPSCR ); + vPortInitialiseFPSCR(portINITIAL_FPSCR); /* A task is registering the fact that it needs a FPU context. Set the - * FPU flag (saved as part of the task context). */ + FPU flag (saved as part of the task context). */ ulTaskHasFPUContext = pdTRUE; portEXIT_CRITICAL(); diff --git a/portable/MPLAB/PIC32MZ/portmacro.h b/portable/MPLAB/PIC32MZ/portmacro.h index 050bb31fa03..e6a3f5508c2 100644 --- a/portable/MPLAB/PIC32MZ/portmacro.h +++ b/portable/MPLAB/PIC32MZ/portmacro.h @@ -49,103 +49,102 @@ */ /* Type definitions. */ -#define portCHAR char -#define portFLOAT float -#define portDOUBLE double -#define portLONG long -#define portSHORT short -#define portSTACK_TYPE uint32_t -#define portBASE_TYPE long - -typedef portSTACK_TYPE StackType_t; -typedef long BaseType_t; -typedef unsigned long UBaseType_t; - -#if ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) - typedef uint16_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffff +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE uint32_t +#define portBASE_TYPE long + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + +#if( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_16_BITS ) + typedef uint16_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffff #elif ( configTICK_TYPE_WIDTH_IN_BITS == TICK_TYPE_WIDTH_32_BITS ) - typedef uint32_t TickType_t; - #define portMAX_DELAY ( TickType_t ) 0xffffffffUL + typedef uint32_t TickType_t; + #define portMAX_DELAY ( TickType_t ) 0xffffffffUL -/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do - * not need to be guarded with a critical section. */ - #define portTICK_TYPE_IS_ATOMIC 1 + /* 32-bit tick type on a 32-bit architecture, so reads of the tick count do + not need to be guarded with a critical section. */ + #define portTICK_TYPE_IS_ATOMIC 1 #else #error configTICK_TYPE_WIDTH_IN_BITS set to unsupported tick type width. #endif /*-----------------------------------------------------------*/ /* Hardware specifics. */ -#define portBYTE_ALIGNMENT 8 -#define portSTACK_GROWTH -1 -#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portBYTE_ALIGNMENT 8 +#define portSTACK_GROWTH -1 +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) /*-----------------------------------------------------------*/ /* Critical section management. */ -#define portIPL_SHIFT ( 10UL ) - +#define portIPL_SHIFT ( 10UL ) /* Don't straddle the CEE bit. Interrupts calling FreeRTOS functions should - * never have higher IPL bits set anyway. */ -#define portALL_IPL_BITS ( 0x7FUL << portIPL_SHIFT ) -#define portSW0_BIT ( 0x01 << 8 ) +never have higher IPL bits set anyway. */ +#define portALL_IPL_BITS ( 0x7FUL << portIPL_SHIFT ) +#define portSW0_BIT ( 0x01 << 8 ) /* This clears the IPL bits, then sets them to - * configMAX_SYSCALL_INTERRUPT_PRIORITY. An extra check is performed if - * configASSERT() is defined to ensure an assertion handler does not inadvertently - * attempt to lower the IPL when the call to assert was triggered because the IPL - * value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY when an ISR - * safe FreeRTOS API function was executed. ISR safe FreeRTOS API functions are - * those that end in FromISR. FreeRTOS maintains a separate interrupt API to - * ensure API function and interrupt entry is as fast and as simple as possible. */ +configMAX_SYSCALL_INTERRUPT_PRIORITY. An extra check is performed if +configASSERT() is defined to ensure an assertion handler does not inadvertently +attempt to lower the IPL when the call to assert was triggered because the IPL +value was found to be above configMAX_SYSCALL_INTERRUPT_PRIORITY when an ISR +safe FreeRTOS API function was executed. ISR safe FreeRTOS API functions are +those that end in FromISR. FreeRTOS maintains a separate interrupt API to +ensure API function and interrupt entry is as fast and as simple as possible. */ #ifdef configASSERT - #define portDISABLE_INTERRUPTS() \ - { \ - uint32_t ulStatus; \ - \ - /* Mask interrupts at and below the kernel interrupt priority. */ \ - ulStatus = _CP0_GET_STATUS(); \ - \ - /* Is the current IPL below configMAX_SYSCALL_INTERRUPT_PRIORITY? */ \ + #define portDISABLE_INTERRUPTS() \ + { \ + uint32_t ulStatus; \ + \ + /* Mask interrupts at and below the kernel interrupt priority. */ \ + ulStatus = _CP0_GET_STATUS(); \ + \ + /* Is the current IPL below configMAX_SYSCALL_INTERRUPT_PRIORITY? */ \ if( ( ( ulStatus & portALL_IPL_BITS ) >> portIPL_SHIFT ) < configMAX_SYSCALL_INTERRUPT_PRIORITY ) \ - { \ - ulStatus &= ~portALL_IPL_BITS; \ - _CP0_SET_STATUS( ( ulStatus | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ) ); \ - } \ + { \ + ulStatus &= ~portALL_IPL_BITS; \ + _CP0_SET_STATUS( ( ulStatus | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ) ); \ + } \ } #else /* configASSERT */ - #define portDISABLE_INTERRUPTS() \ - { \ - uint32_t ulStatus; \ - \ - /* Mask interrupts at and below the kernel interrupt priority. */ \ - ulStatus = _CP0_GET_STATUS(); \ - ulStatus &= ~portALL_IPL_BITS; \ + #define portDISABLE_INTERRUPTS() \ + { \ + uint32_t ulStatus; \ + \ + /* Mask interrupts at and below the kernel interrupt priority. */ \ + ulStatus = _CP0_GET_STATUS(); \ + ulStatus &= ~portALL_IPL_BITS; \ _CP0_SET_STATUS( ( ulStatus | ( configMAX_SYSCALL_INTERRUPT_PRIORITY << portIPL_SHIFT ) ) ); \ } #endif /* configASSERT */ -#define portENABLE_INTERRUPTS() \ - { \ - uint32_t ulStatus; \ - \ - /* Unmask all interrupts. */ \ - ulStatus = _CP0_GET_STATUS(); \ - ulStatus &= ~portALL_IPL_BITS; \ - _CP0_SET_STATUS( ulStatus ); \ - } +#define portENABLE_INTERRUPTS() \ +{ \ +uint32_t ulStatus; \ + \ + /* Unmask all interrupts. */ \ + ulStatus = _CP0_GET_STATUS(); \ + ulStatus &= ~portALL_IPL_BITS; \ + _CP0_SET_STATUS( ulStatus ); \ +} extern void vTaskEnterCritical( void ); extern void vTaskExitCritical( void ); -#define portCRITICAL_NESTING_IN_TCB 1 -#define portENTER_CRITICAL() vTaskEnterCritical() -#define portEXIT_CRITICAL() vTaskExitCritical() +#define portCRITICAL_NESTING_IN_TCB 1 +#define portENTER_CRITICAL() vTaskEnterCritical() +#define portEXIT_CRITICAL() vTaskExitCritical() extern UBaseType_t uxPortSetInterruptMaskFromISR(); extern void vPortClearInterruptMaskFromISR( UBaseType_t ); -#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMaskFromISR() -#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) vPortClearInterruptMaskFromISR( uxSavedStatusRegister ) +#define portSET_INTERRUPT_MASK_FROM_ISR() uxPortSetInterruptMaskFromISR() +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusRegister ) vPortClearInterruptMaskFromISR( uxSavedStatusRegister ) #if ( __mips_hard_float == 0 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) #error configUSE_TASK_FPU_SUPPORT can only be set to 1 when the part supports a hardware FPU module. @@ -153,27 +152,27 @@ extern void vPortClearInterruptMaskFromISR( UBaseType_t ); #if ( __mips_hard_float == 1 ) && ( configUSE_TASK_FPU_SUPPORT == 1 ) void vPortTaskUsesFPU( void ); - #define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU() + #define portTASK_USES_FLOATING_POINT() vPortTaskUsesFPU() #endif #ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION - #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + #define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 #endif #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 -/* Check the configuration. */ - #if ( configMAX_PRIORITIES > 32 ) + /* Check the configuration. */ + #if( configMAX_PRIORITIES > 32 ) #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. #endif -/* Store/clear the ready priorities in a bit map. */ - #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) - #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) + /* Store/clear the ready priorities in a bit map. */ + #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) + #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ) -/*-----------------------------------------------------------*/ + /*-----------------------------------------------------------*/ - #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - _clz( ( uxReadyPriorities ) ) ) + #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31UL - _clz( ( uxReadyPriorities ) ) ) #endif /* taskRECORD_READY_PRIORITY */ @@ -181,26 +180,26 @@ extern void vPortClearInterruptMaskFromISR( UBaseType_t ); /* Task utilities. */ -#define portYIELD() \ - { \ - uint32_t ulCause; \ - \ - /* Trigger software interrupt. */ \ - ulCause = _CP0_GET_CAUSE(); \ - ulCause |= portSW0_BIT; \ - _CP0_SET_CAUSE( ulCause ); \ - } +#define portYIELD() \ +{ \ +uint32_t ulCause; \ + \ + /* Trigger software interrupt. */ \ + ulCause = _CP0_GET_CAUSE(); \ + ulCause |= portSW0_BIT; \ + _CP0_SET_CAUSE( ulCause ); \ +} extern volatile UBaseType_t uxInterruptNesting; -#define portASSERT_IF_IN_ISR() configASSERT( uxInterruptNesting == 0 ) +#define portASSERT_IF_IN_ISR() configASSERT( uxInterruptNesting == 0 ) -#define portNOP() __asm volatile ( "nop" ) +#define portNOP() __asm volatile ( "nop" ) /*-----------------------------------------------------------*/ /* Task function macros as described on the FreeRTOS.org WEB site. */ -#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) __attribute__( ( noreturn ) ) -#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters ) __attribute__((noreturn)) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters ) /*-----------------------------------------------------------*/ #define portEND_SWITCHING_ISR( xSwitchRequired ) \