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

@ -163,9 +163,9 @@ const unsigned char ucIPAddress[ 4 ] = { emacIPADDR0, emacIPADDR1, emacIPADDR2,
/* See the header file for descriptions of public functions. */
/*
* Prototype for the EMAC interrupt function - called by the asm wrapper.
* Prototype for the EMAC interrupt function.
*/
void vEMACISR( void ) __attribute__ ((naked));
void vEMACISR_Wrapper( void ) __attribute__ ((naked));
/*
* Initialise both the Tx and Rx descriptors used by the EMAC.
@ -666,7 +666,7 @@ static void prvSetupEMACInterrupt( void )
AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RCOMP | AT91C_EMAC_TCOMP;
/* Enable the interrupts in the AIC. */
AT91F_AIC_ConfigureIt( AT91C_ID_EMAC, emacINTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, ( void (*)( void ) ) vEMACISR );
AT91F_AIC_ConfigureIt( AT91C_ID_EMAC, emacINTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, ( void (*)( void ) ) vEMACISR_Wrapper );
AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_EMAC;
}
portEXIT_CRITICAL();

View file

@ -33,18 +33,6 @@
***************************************************************************
*/
/*
Changes from V3.2.4
+ Also read the EMAC_RSR register in the EMAC ISR as a work around the
the EMAC bug that can reset the RX bit in EMAC_ISR register before the
bit has been read.
Changes from V4.0.1
+ Only check the interrupt status register to see if an EMAC Tx interrupt
has occurred. Previously the TSR register was also inspected.
*/
#include "FreeRTOS.h"
#include "task.h"
@ -58,26 +46,22 @@ Changes from V4.0.1
task. */
static xSemaphoreHandle xSemaphore = NULL;
void vEMACISR( void ) __attribute__((naked));
/* The interrupt entry point is naked so we can control the context saving. */
void vEMACISR_Wrapper( void ) __attribute__((naked));
/* The interrupt handler function must be separate from the entry function
to ensure the correct stack frame is set up. */
void vEMACISR_Handler( void );
/*-----------------------------------------------------------*/
/*
* The EMAC ISR. Handles both Tx and Rx complete interrupts.
*/
void vEMACISR( void )
void vEMACISR_Handler( void )
{
/* This ISR can cause a context switch, so the first statement must be a
call to the portENTER_SWITCHING_ISR() macro. This must be BEFORE any
variable declarations. */
portENTER_SWITCHING_ISR();
/* Variable definitions can be made now. These must be static. */
static volatile unsigned portLONG ulIntStatus, ulEventStatus;
static portBASE_TYPE xSwitchRequired;
extern void vClearEMACTxBuffer( void );
/* As the variable is static it must be initialised manually here. */
xSwitchRequired = pdFALSE;
volatile unsigned portLONG ulIntStatus, ulEventStatus;
portBASE_TYPE xSwitchRequired = pdFALSE;
extern void vClearEMACTxBuffer( void );
/* Find the cause of the interrupt. */
ulIntStatus = AT91C_BASE_EMAC->EMAC_ISR;
@ -103,8 +87,27 @@ void vEMACISR( void )
AT91C_BASE_AIC->AIC_EOICR = 0;
/* If a task was woken by either a frame being received then we may need to
switch to another task. */
portEXIT_SWITCHING_ISR( xSwitchRequired );
switch to another task. If the unblocked task was of higher priority then
the interrupted task it will then execute immediately that the ISR
completes. */
if( xSwitchRequired )
{
portYIELD_FROM_ISR();
}
}
/*-----------------------------------------------------------*/
void vEMACISR_Wrapper( void )
{
/* Save the context of the interrupted task. */
portSAVE_CONTEXT();
/* Call the handler to do the work. This must be a separate
function to ensure the stack frame is set up correctly. */
vEMACISR_Handler();
/* Restore the context of whichever task will execute next. */
portRESTORE_CONTEXT();
}
/*-----------------------------------------------------------*/

View file

@ -699,7 +699,7 @@ static void vDetachUSBInterface( void)
static void vInitUSBInterface( void )
{
extern void ( vUSB_ISR )( void );
extern void ( vUSB_ISR_Wrapper )( void );
/* Create the queue used to communicate between the USB ISR and task. */
xUSBInterruptQueue = xQueueCreate( usbQUEUE_LENGTH + 1, sizeof( xISRStatus * ) );
@ -759,7 +759,7 @@ extern void ( vUSB_ISR )( void );
/* Enable the USB interrupts - other interrupts get enabled as the
enumeration process progresses. */
AT91F_AIC_ConfigureIt( AT91C_ID_UDP, usbINTERRUPT_PRIORITY, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, ( void (*)( void ) ) vUSB_ISR );
AT91F_AIC_ConfigureIt( AT91C_ID_UDP, usbINTERRUPT_PRIORITY, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, ( void (*)( void ) ) vUSB_ISR_Wrapper );
AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_UDP;

View file

@ -59,27 +59,20 @@ extern xQueueHandle xUSBInterruptQueue;
/*-----------------------------------------------------------*/
/* The ISR can cause a context switch so is declared naked. */
void vUSB_ISR( void ) __attribute__ ((naked));
void vUSB_ISR_Wrapper( void ) __attribute__ ((naked));
/* The function that actually performs the ISR work. This must be separate
from the wrapper function to ensure the correct stack frame gets set up. */
void vUSB_ISR_Handler( void );
/*-----------------------------------------------------------*/
void vUSB_ISR( void )
void vUSB_ISR_Handler( void )
{
/* This ISR can cause a context switch. Therefore a call to the
portENTER_SWITCHING_ISR() macro is made. This must come BEFORE any
stack variable declarations. */
portENTER_SWITCHING_ISR();
/* Now variables can be declared. These must be static. */
static portCHAR cTaskWokenByPost;
static volatile unsigned portLONG ulNextMessage = 0;
static xISRStatus *pxMessage;
static unsigned portLONG ulRxBytes;
static unsigned portCHAR ucFifoIndex;
/* As the variables are static they must be initialised manually here. */
cTaskWokenByPost = pdFALSE;
portCHAR cTaskWokenByPost = pdFALSE;
static volatile unsigned portLONG ulNextMessage = 0;
xISRStatus *pxMessage;
unsigned portLONG ulRxBytes;
unsigned portCHAR ucFifoIndex;
/* Use the next message from the array. */
pxMessage = &( xISRMessages[ ( ulNextMessage & usbQUEUE_LENGTH ) ] );
@ -158,6 +151,27 @@ void vUSB_ISR( void )
AT91C_BASE_AIC->AIC_EOICR = 0;
/* Do a task switch if needed */
portEXIT_SWITCHING_ISR( cTaskWokenByPost )
if( cTaskWokenByPost )
{
/* This call will ensure that the unblocked task will be executed
immediately upon completion of the ISR if it has a priority higher
than the interrupted task. */
portYIELD_FROM_ISR();
}
}
/*-----------------------------------------------------------*/
void vUSB_ISR_Wrapper( void )
{
/* Save the context of the interrupted task. */
portSAVE_CONTEXT();
/* Call the handler to do the work. This must be a separate
function to ensure the stack frame is set up correctly. */
vUSB_ISR_Handler();
/* Restore the context of whichever task will execute next. */
portRESTORE_CONTEXT();
}