mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-08-11 13:54:16 -04:00
Changed the way the ARM7/9 GCC ports enter interrupts that can cause a context switch.
This commit is contained in:
parent
c54ec1c639
commit
ada7fa862d
24 changed files with 322 additions and 275 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue