Changed the way the ARM7/9 GCC ports enter interrupts that can cause a context switch.

This commit is contained in:
Richard Barry 2007-10-28 13:55:35 +00:00
parent c54ec1c639
commit ada7fa862d
24 changed files with 322 additions and 275 deletions

View file

@ -300,10 +300,10 @@ void vTCPHardReset( void )
/* Install the ISR into the VIC - but don't enable it yet! */
portENTER_CRITICAL();
{
extern void ( vEINT0_ISR )( void );
extern void ( vEINT0_ISR_Wrapper )( void );
VICIntSelect &= ~( tcpEINT0_VIC_CHANNEL_BIT );
VICVectAddr3 = ( portLONG ) vEINT0_ISR;
VICVectAddr3 = ( portLONG ) vEINT0_ISR_Wrapper;
VICVectCntl3 = tcpEINT0_VIC_CHANNEL | tcpEINT0_VIC_ENABLE;
}

View file

@ -43,7 +43,10 @@
#define tcpEINT0_VIC_CHANNEL_BIT ( ( unsigned portLONG ) 0x4000 )
/* EINT0 interrupt handler. This processes interrupts from the WIZnet device. */
void vEINT0_ISR( void ) __attribute__((naked));
void vEINT0_ISR_Wrapper( void ) __attribute__((naked));
/* The handler that goes with the EINT0 wrapper. */
void vEINT0_ISR_Handler( void );
/* Variable is required for its address, but does not otherwise get used. */
static portLONG lDummyVariable;
@ -53,21 +56,16 @@ static portLONG lDummyVariable;
* the TCP task. This wakes the task so the interrupt can be processed. The
* source of the interrupt has to be ascertained by the TCP task as this
* requires an I2C transaction which cannot be performed from this ISR.
* Note this code predates the introduction of semaphores, a semaphore should
* be used in place of the empty queue message.
*/
void vEINT0_ISR( void )
void vEINT0_ISR_Handler( void )
{
portENTER_SWITCHING_ISR();
extern xQueueHandle xTCPISRQueue;
/* Must be declared static. */
static portBASE_TYPE xTaskWoken;
/* As the variable is static it must be manually initialised. */
xTaskWoken = pdFALSE;
extern xQueueHandle xTCPISRQueue;
portBASE_TYPE xTaskWoken = pdFALSE;
/* Just wake the TCP task so it knows an ISR has occurred. */
xQueueSendFromISR( xTCPISRQueue, ( void * ) &lDummyVariable, xTaskWoken );
xTaskWoken = xQueueSendFromISR( xTCPISRQueue, ( void * ) &lDummyVariable, xTaskWoken );
/* We cannot carry on processing interrupts until the TCP task has
processed this one - so for now interrupts are disabled. The TCP task will
@ -77,10 +75,24 @@ void vEINT0_ISR( void )
/* Clear the interrupt bit. */
VICVectAddr = tcpCLEAR_VIC_INTERRUPT;
/* Switch to the TCP task immediately so the cause of the interrupt can
be ascertained. It is the responsibility of the TCP task to clear the
interrupts. */
portEXIT_SWITCHING_ISR( ( xTaskWoken ) );
if( xTaskWoken )
{
portYIELD_FROM_ISR();
}
}
/*-----------------------------------------------------------*/
void vEINT0_ISR_Wrapper( void )
{
/* Save the context of the interrupted task. */
portSAVE_CONTEXT();
/* The handler must be a separate function from the wrapper to
ensure the correct stack frame is set up. */
vEINT0_ISR_Handler();
/* Restore the context of whichever task is going to run next. */
portRESTORE_CONTEXT();
}

View file

@ -182,7 +182,7 @@ signed portBASE_TYPE xReturn;
void i2cInit( void )
{
extern void ( vI2C_ISR )( void );
extern void ( vI2C_ISR_Wrapper )( void );
/* Create the queue used to send messages to the ISR. */
vI2CISRCreateQueues( i2cQUEUE_LENGTH, &xMessagesForTx, &pulBusFree );
@ -203,7 +203,7 @@ extern void ( vI2C_ISR )( void );
/* Setup the VIC for the i2c interrupt. */
VICIntSelect &= ~( i2cI2C_VIC_CHANNEL_BIT );
VICIntEnable |= i2cI2C_VIC_CHANNEL_BIT;
VICVectAddr2 = ( portLONG ) vI2C_ISR;
VICVectAddr2 = ( portLONG ) vI2C_ISR_Wrapper;
VICVectCntl2 = i2cI2C_VIC_CHANNEL | i2cI2C_VIC_ENABLE;
}

View file

@ -119,21 +119,36 @@ void vI2CISRCreateQueues( unsigned portBASE_TYPE uxQueueLength, xQueueHandle *px
}
/*-----------------------------------------------------------*/
void vI2C_ISR( void ) __attribute__ (( naked ));
void vI2C_ISR( void )
/* The ISR entry point. */
void vI2C_ISR_Wrapper( void ) __attribute__ (( naked ));
/* The ISR function to perform the actual work. This must be a separate
function from the wrapper to ensure the correct stack frame is set up. */
void vI2C_ISR_Handler( void );
/*-----------------------------------------------------------*/
void vI2C_ISR_Wrapper( void )
{
portENTER_SWITCHING_ISR();
/* Save the context of the interrupted task. */
portSAVE_CONTEXT();
/* Variables must be static. */
/* Call the handler to perform the actual work. This must be a
separate function to ensure the correct stack frame is set up. */
vI2C_ISR_Handler();
/* Holds the current transmission state. */
static I2C_STATE eCurrentState = eSentStart;
static portLONG lMessageIndex = -i2cBUFFER_ADDRESS_BYTES; /* There are two address bytes to send prior to the data. */
static portBASE_TYPE xTaskWokenByTx;
static portLONG lBytesLeft;
xTaskWokenByTx = pdFALSE;
/* Restore the context of whichever task is going to run next. */
portRESTORE_CONTEXT();
}
/*-----------------------------------------------------------*/
void vI2C_ISR_Handler( void )
{
/* Holds the current transmission state. */
static I2C_STATE eCurrentState = eSentStart;
static portLONG lMessageIndex = -i2cBUFFER_ADDRESS_BYTES; /* There are two address bytes to send prior to the data. */
portBASE_TYPE xTaskWokenByTx = pdFALSE;
portLONG lBytesLeft;
/* The action taken for this interrupt depends on our current state. */
switch( eCurrentState )
@ -342,7 +357,10 @@ void vI2C_ISR( void )
I2C_I2CONCLR = i2cSI_BIT;
VICVectAddr = i2cCLEAR_VIC_INTERRUPT;
portEXIT_SWITCHING_ISR( ( xTaskWokenByTx ) );
if( xTaskWokenByTx )
{
portYIELD_FROM_ISR();
}
}
/*-----------------------------------------------------------*/