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

@ -87,7 +87,7 @@ xComPortHandle xSerialPortInitMinimal( unsigned portLONG ulWantedBaud, unsigned
unsigned portLONG ulSpeed; unsigned portLONG ulSpeed;
unsigned portLONG ulCD; unsigned portLONG ulCD;
xComPortHandle xReturn = serHANDLE; xComPortHandle xReturn = serHANDLE;
extern void ( vUART_ISR )( void ); extern void ( vUART_ISR_Wrapper )( void );
/* The queues are used in the serial ISR routine, so are created from /* The queues are used in the serial ISR routine, so are created from
serialISR.c (which is always compiled to ARM mode. */ serialISR.c (which is always compiled to ARM mode. */
@ -139,7 +139,7 @@ extern void ( vUART_ISR )( void );
/* Setup the interrupt for USART0. /* Setup the interrupt for USART0.
Store interrupt handler function address in USART0 vector register... */ Store interrupt handler function address in USART0 vector register... */
AT91C_BASE_AIC->AIC_SVR[ portUSART0_AIC_CHANNEL ] = (unsigned long)vUART_ISR; AT91C_BASE_AIC->AIC_SVR[ portUSART0_AIC_CHANNEL ] = (unsigned long)vUART_ISR_Wrapper;
/* USART0 interrupt level-sensitive, priority 1... */ /* USART0 interrupt level-sensitive, priority 1... */
AT91C_BASE_AIC->AIC_SMR[ portUSART0_AIC_CHANNEL ] = AIC_SRCTYPE_INT_LEVEL_SENSITIVE | 1; AT91C_BASE_AIC->AIC_SMR[ portUSART0_AIC_CHANNEL ] = AIC_SRCTYPE_INT_LEVEL_SENSITIVE | 1;

View file

@ -74,7 +74,11 @@ static xQueueHandle xCharsForTx;
/* UART0 interrupt service routine. This can cause a context switch so MUST /* UART0 interrupt service routine. This can cause a context switch so MUST
be declared "naked". */ be declared "naked". */
void vUART_ISR( void ) __attribute__ ((naked)); void vUART_ISR_Wrapper( void ) __attribute__ ((naked));
/* The ISR function that actually performs the work. This must be separate
from the wrapper to ensure the correct stack frame is set up. */
void vUART_ISR_Handler( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vSerialISRCreateQueues( unsigned portBASE_TYPE uxQueueLength, xQueueHandle *pxRxedChars, xQueueHandle *pxCharsForTx ) void vSerialISRCreateQueues( unsigned portBASE_TYPE uxQueueLength, xQueueHandle *pxRxedChars, xQueueHandle *pxCharsForTx )
@ -90,21 +94,26 @@ void vSerialISRCreateQueues( unsigned portBASE_TYPE uxQueueLength, xQueueHandle
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vUART_ISR( void ) void vUART_ISR_Wrapper( void )
{ {
/* This ISR can cause a context switch, so the first statement must be a /* Save the context of the interrupted task. */
call to the portENTER_SWITCHING_ISR() macro. This must be BEFORE any portSAVE_CONTEXT();
variable declarations. */
portENTER_SWITCHING_ISR();
/* Now we can declare the local variables. These must be static. */ /* Call the handler. This must be a separate function to ensure the
static signed portCHAR cChar; stack frame is correctly set up. */
static portBASE_TYPE xTaskWokenByTx, xTaskWokenByRx; vUART_ISR_Handler();
static unsigned portLONG ulStatus;
/* These variables are static so need initialising manually here. */ /* Restore the context of whichever task will run next. */
xTaskWokenByTx = pdFALSE; portRESTORE_CONTEXT();
xTaskWokenByRx = pdFALSE; }
/*-----------------------------------------------------------*/
void vUART_ISR_Handler( void )
{
/* Now we can declare the local variables. These must be static. */
signed portCHAR cChar;
portBASE_TYPE xTaskWokenByTx = pdFALSE, xTaskWokenByRx = pdFALSE;
unsigned portLONG ulStatus;
/* What caused the interrupt? */ /* What caused the interrupt? */
ulStatus = AT91C_BASE_US0->US_CSR & AT91C_BASE_US0->US_IMR; ulStatus = AT91C_BASE_US0->US_CSR & AT91C_BASE_US0->US_IMR;
@ -140,9 +149,14 @@ void vUART_ISR( void )
/* Acknowledge the interrupt at AIC level... */ /* Acknowledge the interrupt at AIC level... */
AT91C_BASE_AIC->AIC_EOICR = serCLEAR_AIC_INTERRUPT; AT91C_BASE_AIC->AIC_EOICR = serCLEAR_AIC_INTERRUPT;
/* Exit the ISR. If a task was woken by either a character being received /* If an event caused a task to unblock then we call "Yield from ISR" to
or transmitted then a context switch will occur. */ ensure that the unblocked task is the task that executes when the interrupt
portEXIT_SWITCHING_ISR( ( xTaskWokenByTx || xTaskWokenByRx ) ); completes if the unblocked task has a priority higher than the interrupted
task. */
if( xTaskWokenByTx || xTaskWokenByRx )
{
portYIELD_FROM_ISR();
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -56,7 +56,7 @@
#define configTICK_RATE_HZ ( ( portTickType ) 1000 ) #define configTICK_RATE_HZ ( ( portTickType ) 1000 )
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 ) #define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
#define configMINIMAL_STACK_SIZE ( ( unsigned portSHORT ) 128 ) #define configMINIMAL_STACK_SIZE ( ( unsigned portSHORT ) 128 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 23 * 1024 ) ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 24 * 1024 ) )
#define configMAX_TASK_NAME_LEN ( 16 ) #define configMAX_TASK_NAME_LEN ( 16 )
#define configUSE_TRACE_FACILITY 0 #define configUSE_TRACE_FACILITY 0
#define configUSE_16_BIT_TICKS 0 #define configUSE_16_BIT_TICKS 0

View file

@ -130,9 +130,9 @@
/* Priorities for the demo application tasks. */ /* Priorities for the demo application tasks. */
#define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 ) #define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 )
#define mainCOM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainCOM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 0 )
#define mainCHECK_TASK_PRIORITY ( tskIDLE_PRIORITY + 4 ) #define mainCHECK_TASK_PRIORITY ( tskIDLE_PRIORITY + 4 )
#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 ) #define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 0 )
#define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 )
/* The rate at which the on board LED will toggle when there is/is not an /* The rate at which the on board LED will toggle when there is/is not an
@ -247,6 +247,7 @@ xTaskHandle xCreatedTask;
parameter. */ parameter. */
ulMemCheckTaskRunningCount = mainCOUNT_INITIAL_VALUE; ulMemCheckTaskRunningCount = mainCOUNT_INITIAL_VALUE;
xCreatedTask = mainNO_TASK; xCreatedTask = mainNO_TASK;
if( xTaskCreate( vMemCheckTask, ( signed portCHAR * ) "MEM_CHECK", configMINIMAL_STACK_SIZE, ( void * ) &ulMemCheckTaskRunningCount, tskIDLE_PRIORITY, &xCreatedTask ) != pdPASS ) if( xTaskCreate( vMemCheckTask, ( signed portCHAR * ) "MEM_CHECK", configMINIMAL_STACK_SIZE, ( void * ) &ulMemCheckTaskRunningCount, tskIDLE_PRIORITY, &xCreatedTask ) != pdPASS )
{ {
/* Could not create the task - we have probably run out of heap. */ /* Could not create the task - we have probably run out of heap. */

View file

@ -118,7 +118,7 @@ xComPortHandle xSerialPortInitMinimal( unsigned portLONG ulWantedBaud, unsigned
{ {
unsigned portLONG ulDivisor, ulWantedClock; unsigned portLONG ulDivisor, ulWantedClock;
xComPortHandle xReturn = serHANDLE; xComPortHandle xReturn = serHANDLE;
extern void ( vUART_ISR )( void ); extern void ( vUART_ISR_Wrapper )( void );
/* The queues are used in the serial ISR routine, so are created from /* The queues are used in the serial ISR routine, so are created from
serialISR.c (which is always compiled to ARM mode. */ serialISR.c (which is always compiled to ARM mode. */
@ -153,7 +153,7 @@ extern void ( vUART_ISR )( void );
/* Setup the VIC for the UART. */ /* Setup the VIC for the UART. */
VICIntSelect &= ~( serUART0_VIC_CHANNEL_BIT ); VICIntSelect &= ~( serUART0_VIC_CHANNEL_BIT );
VICIntEnable |= serUART0_VIC_CHANNEL_BIT; VICIntEnable |= serUART0_VIC_CHANNEL_BIT;
VICVectAddr1 = ( portLONG ) vUART_ISR; VICVectAddr1 = ( portLONG ) vUART_ISR_Wrapper;
VICVectCntl1 = serUART0_VIC_CHANNEL | serUART0_VIC_ENABLE; VICVectCntl1 = serUART0_VIC_CHANNEL | serUART0_VIC_ENABLE;
/* Enable UART0 interrupts. */ /* Enable UART0 interrupts. */

View file

@ -80,9 +80,11 @@ static volatile portLONG lTHREEmpty;
*/ */
void vSerialISRCreateQueues( unsigned portBASE_TYPE uxQueueLength, xQueueHandle *pxRxedChars, xQueueHandle *pxCharsForTx, portLONG volatile **pplTHREEmptyFlag ); void vSerialISRCreateQueues( unsigned portBASE_TYPE uxQueueLength, xQueueHandle *pxRxedChars, xQueueHandle *pxCharsForTx, portLONG volatile **pplTHREEmptyFlag );
/* UART0 interrupt service routine. This can cause a context switch so MUST /* UART0 interrupt service routine entry point. */
be declared "naked". */ void vUART_ISR_Wrapper( void ) __attribute__ ((naked));
void vUART_ISR( void ) __attribute__ ((naked));
/* UART0 interrupt service routine handler. */
void vUART_ISR_Handler( void );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vSerialISRCreateQueues( unsigned portBASE_TYPE uxQueueLength, xQueueHandle *pxRxedChars, void vSerialISRCreateQueues( unsigned portBASE_TYPE uxQueueLength, xQueueHandle *pxRxedChars,
@ -103,20 +105,24 @@ void vSerialISRCreateQueues( unsigned portBASE_TYPE uxQueueLength, xQueueHandle
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
void vUART_ISR( void ) void vUART_ISR_Wrapper( void )
{ {
/* This ISR can cause a context switch, so the first statement must be a /* Save the context of the interrupted task. */
call to the portENTER_SWITCHING_ISR() macro. This must be BEFORE any portSAVE_CONTEXT();
variable declarations. */
portENTER_SWITCHING_ISR();
/* Now we can declare the local variables. These must be static. */ /* Call the handler. This must be a separate function from the wrapper
static signed portCHAR cChar; to ensure the correct stack frame is set up. */
static portBASE_TYPE xTaskWokenByTx, xTaskWokenByRx; vUART_ISR_Handler();
/* As these variables are static they must be initialised manually here. */ /* Restore the context of whichever task is going to run next. */
xTaskWokenByTx = pdFALSE; portRESTORE_CONTEXT();
xTaskWokenByRx = pdFALSE; }
/*-----------------------------------------------------------*/
void vUART_ISR_Handler( void )
{
signed portCHAR cChar;
portBASE_TYPE xTaskWokenByTx = pdFALSE, xTaskWokenByRx = pdFALSE;
/* What caused the interrupt? */ /* What caused the interrupt? */
switch( UART0_IIR & serINTERRUPT_SOURCE_MASK ) switch( UART0_IIR & serINTERRUPT_SOURCE_MASK )
@ -154,14 +160,15 @@ void vUART_ISR( void )
break; break;
} }
if( xTaskWokenByTx || xTaskWokenByRx )
{
portYIELD_FROM_ISR();
}
/* Clear the ISR in the VIC. */ /* Clear the ISR in the VIC. */
VICVectAddr = serCLEAR_VIC_INTERRUPT; VICVectAddr = serCLEAR_VIC_INTERRUPT;
/* Exit the ISR. If a task was woken by either a character being received
or transmitted then a context switch will occur. */
portEXIT_SWITCHING_ISR( ( xTaskWokenByTx || xTaskWokenByRx ) );
} }
/*-----------------------------------------------------------*/

View file

@ -96,6 +96,8 @@
#define mainLED_DELAY ( ( portTickType ) 500 / portTICK_RATE_MS ) #define mainLED_DELAY ( ( portTickType ) 500 / portTICK_RATE_MS )
#define mainCHECK_DELAY ( ( portTickType ) 5000 / portTICK_RATE_MS ) #define mainCHECK_DELAY ( ( portTickType ) 5000 / portTICK_RATE_MS )
#define mainLIST_BUFFER_SIZE 2048 #define mainLIST_BUFFER_SIZE 2048
#define mainNO_DELAY ( 0 )
#define mainSHORT_DELAY ( 150 / portTICK_RATE_MS )
/* Task priorities. */ /* Task priorities. */
#define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 )
@ -178,7 +180,7 @@ int main( void )
/* Start the scheduler. */ /* Start the scheduler. */
vTaskStartScheduler(); vTaskStartScheduler();
/* The scheduler should now running, so we will only ever reach here if we /* The scheduler should now be running, so we will only ever reach here if we
ran out of heap space. */ ran out of heap space. */
return 0; return 0;
@ -290,7 +292,7 @@ static void vButtonHandlerTask( void *pvParameters )
static portCHAR cListBuffer[ mainLIST_BUFFER_SIZE ]; static portCHAR cListBuffer[ mainLIST_BUFFER_SIZE ];
const portCHAR *pcList = &( cListBuffer[ 0 ] ); const portCHAR *pcList = &( cListBuffer[ 0 ] );
const portCHAR * const pcHeader = "\nTask State Priority Stack #\n************************************************"; const portCHAR * const pcHeader = "\nTask State Priority Stack #\n************************************************";
extern void (vButtonISR) ( void ); extern void (vButtonISRWrapper) ( void );
/* Configure the interrupt. */ /* Configure the interrupt. */
portENTER_CRITICAL(); portENTER_CRITICAL();
@ -303,15 +305,19 @@ extern void (vButtonISR) ( void );
/* Setup the VIC for EINT 1. */ /* Setup the VIC for EINT 1. */
VICIntSelect &= ~mainEINT_1_VIC_CHANNEL_BIT; VICIntSelect &= ~mainEINT_1_VIC_CHANNEL_BIT;
VICIntEnable |= mainEINT_1_VIC_CHANNEL_BIT; VICIntEnable |= mainEINT_1_VIC_CHANNEL_BIT;
VICVectAddr1 = ( portLONG ) vButtonISR; VICVectAddr1 = ( portLONG ) vButtonISRWrapper;
VICVectCntl1 = mainEINT_1_ENABLE_BIT | mainEINT_1_CHANNEL; VICVectCntl1 = mainEINT_1_ENABLE_BIT | mainEINT_1_CHANNEL;
} }
portEXIT_CRITICAL(); portEXIT_CRITICAL();
for( ;; ) for( ;; )
{ {
/* For debouncing, wait a while then clear the semaphore. */
vTaskDelay( mainSHORT_DELAY );
xSemaphoreTake( xButtonSemaphore, mainNO_DELAY );
/* Wait for an interrupt. */ /* Wait for an interrupt. */
while( xSemaphoreTake( xButtonSemaphore, portMAX_DELAY ) != pdPASS ); xSemaphoreTake( xButtonSemaphore, portMAX_DELAY );
/* Send the column headers to the print task for display. */ /* Send the column headers to the print task for display. */
xQueueSend( xPrintQueue, &pcHeader, portMAX_DELAY ); xQueueSend( xPrintQueue, &pcHeader, portMAX_DELAY );

View file

@ -39,18 +39,43 @@
/* /*
* Interrupt routine that simply wakes vButtonHandlerTask on each interrupt * Interrupt routine that simply wakes vButtonHandlerTask on each interrupt
* generated by a push of the built in button. * generated by a push of the built in button. The wrapper takes care of
* the ISR entry. This then calls the actual handler function to perform
* the work. This work should not be done in the wrapper itself unless
* you are absolutely sure that no stack space is used.
*/ */
void vButtonISR( void ) __attribute__ ((naked)); void vButtonISRWrapper( void ) __attribute__ ((naked));
void vButtonHandler( void );
void vButtonHandler( void )
{
extern xSemaphoreHandle xButtonSemaphore; extern xSemaphoreHandle xButtonSemaphore;
void vButtonISR( void ) if( xSemaphoreGiveFromISR( xButtonSemaphore, pdFALSE ) )
{ {
portENTER_SWITCHING_ISR(); /* We have woken a task. Calling "yield from ISR" here will ensure
xSemaphoreGiveFromISR( xButtonSemaphore, pdFALSE ); the interrupt returns to the woken task if it has a priority higher
than the interrupted task. */
portYIELD_FROM_ISR();
}
EXTINT = isrCLEAR_EINT_1; EXTINT = isrCLEAR_EINT_1;
VICVectAddr = 0; VICVectAddr = 0;
portEXIT_SWITCHING_ISR( pdTRUE ); }
/*-----------------------------------------------------------*/
void vButtonISRWrapper( void )
{
/* Save the context of the interrupted task. */
portSAVE_CONTEXT();
/* Call the handler to do the work. This must be a separate function to
the wrapper to ensure the correct stack frame is set up. */
vButtonHandler();
/* Restore the context of whichever task is going to run once the interrupt
completes. */
portRESTORE_CONTEXT();
} }

View file

@ -2,17 +2,18 @@
#include "Semphr.h" #include "Semphr.h"
#include "Task.h" #include "Task.h"
void vEMAC_ISR( void ) __attribute__((naked)); /* The interrupt entry point. */
void vEMAC_ISR_Wrapper( void ) __attribute__((naked));
/* The handler that does the actual work. */
void vEMAC_ISR_Handler( void );
extern xSemaphoreHandle xEMACSemaphore; extern xSemaphoreHandle xEMACSemaphore;
void vEMAC_ISR( void )
void vEMAC_ISR_Handler( void )
{ {
portENTER_SWITCHING_ISR(); portBASE_TYPE xSwitchRequired = pdFALSE;
static portBASE_TYPE xSwitchRequired;
xSwitchRequired = pdFALSE;
/* Clear the interrupt. */ /* Clear the interrupt. */
MAC_INTCLEAR = 0xffff; MAC_INTCLEAR = 0xffff;
@ -21,11 +22,22 @@ void vEMAC_ISR( void )
/* Ensure the uIP task is not blocked as data has arrived. */ /* Ensure the uIP task is not blocked as data has arrived. */
if( xSemaphoreGiveFromISR( xEMACSemaphore, pdFALSE ) ) if( xSemaphoreGiveFromISR( xEMACSemaphore, pdFALSE ) )
{ {
xSwitchRequired = pdTRUE; /* Giving the semaphore woke a task. */
portYIELD_FROM_ISR();
} }
}
/*-----------------------------------------------------------*/
/* Switch to the uIP task. */ void vEMAC_ISR_Wrapper( void )
portEXIT_SWITCHING_ISR( xSwitchRequired ); {
/* Save the context of the interrupted task. */
portSAVE_CONTEXT();
/* Call the handler. This must be a separate function unless you can
guarantee that no stack will be used. */
vEMAC_ISR_Handler();
/* Restore the context of whichever task is going to run next. */
portRESTORE_CONTEXT();
} }

View file

@ -62,7 +62,7 @@
#define uipIP_ADDR0 172 #define uipIP_ADDR0 172
#define uipIP_ADDR1 25 #define uipIP_ADDR1 25
#define uipIP_ADDR2 218 #define uipIP_ADDR2 218
#define uipIP_ADDR3 10 #define uipIP_ADDR3 16
/* How long to wait before attempting to connect the MAC again. */ /* How long to wait before attempting to connect the MAC again. */
#define uipINIT_WAIT 100 #define uipINIT_WAIT 100
@ -115,7 +115,7 @@ void vuIP_Task( void *pvParameters )
portBASE_TYPE i; portBASE_TYPE i;
uip_ipaddr_t xIPAddr; uip_ipaddr_t xIPAddr;
struct timer periodic_timer, arp_timer; struct timer periodic_timer, arp_timer;
extern void ( vEMAC_ISR )( void ); extern void ( vEMAC_ISR_Wrapper )( void );
/* Create the semaphore used by the ISR to wake this task. */ /* Create the semaphore used by the ISR to wake this task. */
vSemaphoreCreateBinary( xEMACSemaphore ); vSemaphoreCreateBinary( xEMACSemaphore );
@ -138,7 +138,7 @@ extern void ( vEMAC_ISR )( void );
{ {
MAC_INTENABLE = INT_RX_DONE; MAC_INTENABLE = INT_RX_DONE;
VICIntEnable |= 0x00200000; VICIntEnable |= 0x00200000;
VICVectAddr21 = ( portLONG ) vEMAC_ISR; VICVectAddr21 = ( portLONG ) vEMAC_ISR_Wrapper;
prvSetMACAddress(); prvSetMACAddress();
} }
portEXIT_CRITICAL(); portEXIT_CRITICAL();

View file

@ -2,21 +2,17 @@
#include "Semphr.h" #include "Semphr.h"
#include "Task.h" #include "Task.h"
void vEMAC_ISR( void ) __attribute__((naked)); /* The interrupt entry point. */
void vEMAC_ISR_Wrapper( void ) __attribute__((naked));
/* The function that actually performs the interrupt processing. This must be
separate to the wrapper to ensure the correct stack frame is set up. */
void vEMAC_ISR_Handler( void );
extern xSemaphoreHandle xEMACSemaphore; extern xSemaphoreHandle xEMACSemaphore;
void vEMAC_ISR( void ) void vEMAC_ISR_Handler( void )
{ {
portENTER_SWITCHING_ISR();
/* Variable must be static. */
static portBASE_TYPE xSwitchRequired;
/* As the variable is static it must be manually initialised here. */
xSwitchRequired = pdFALSE;
/* Clear the interrupt. */ /* Clear the interrupt. */
IntClear = 0xffff; IntClear = 0xffff;
VICVectAddr = 0; VICVectAddr = 0;
@ -24,11 +20,27 @@ void vEMAC_ISR( void )
/* Ensure the uIP task is not blocked as data has arrived. */ /* Ensure the uIP task is not blocked as data has arrived. */
if( xSemaphoreGiveFromISR( xEMACSemaphore, pdFALSE ) ) if( xSemaphoreGiveFromISR( xEMACSemaphore, pdFALSE ) )
{ {
xSwitchRequired = pdTRUE; /* If the uIP task was unblocked then calling "Yield from ISR" here
will ensure the interrupt returns directly to the uIP task, if it
is the highest priority read task. */
portYIELD_FROM_ISR();
} }
}
/*-----------------------------------------------------------*/
/* Switch to the uIP task. */ void vEMAC_ISR_Wrapper( void )
portEXIT_SWITCHING_ISR( xSwitchRequired ); {
/* Save the context of the interrupted task. */
portSAVE_CONTEXT();
/* Call the handler function. This must be separate from the wrapper
function to ensure the correct stack frame is set up. */
vEMAC_ISR_Handler();
/* Restore the context of whichever task is going to run next. */
portRESTORE_CONTEXT();
} }

View file

@ -115,7 +115,7 @@ void vuIP_Task( void *pvParameters )
portBASE_TYPE i; portBASE_TYPE i;
uip_ipaddr_t xIPAddr; uip_ipaddr_t xIPAddr;
struct timer periodic_timer, arp_timer; struct timer periodic_timer, arp_timer;
extern void ( vEMAC_ISR )( void ); extern void ( vEMAC_ISR_Wrapper )( void );
/* Create the semaphore used by the ISR to wake this task. */ /* Create the semaphore used by the ISR to wake this task. */
vSemaphoreCreateBinary( xEMACSemaphore ); vSemaphoreCreateBinary( xEMACSemaphore );
@ -138,7 +138,7 @@ extern void ( vEMAC_ISR )( void );
{ {
IntEnable = INT_RX_DONE; IntEnable = INT_RX_DONE;
VICIntEnable |= 0x00200000; VICIntEnable |= 0x00200000;
VICVectAddr21 = ( portLONG ) vEMAC_ISR; VICVectAddr21 = ( portLONG ) vEMAC_ISR_Wrapper;
prvSetMACAddress(); prvSetMACAddress();
} }
portEXIT_CRITICAL(); portEXIT_CRITICAL();

View file

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

View file

@ -43,7 +43,10 @@
#define tcpEINT0_VIC_CHANNEL_BIT ( ( unsigned portLONG ) 0x4000 ) #define tcpEINT0_VIC_CHANNEL_BIT ( ( unsigned portLONG ) 0x4000 )
/* EINT0 interrupt handler. This processes interrupts from the WIZnet device. */ /* 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. */ /* Variable is required for its address, but does not otherwise get used. */
static portLONG lDummyVariable; static portLONG lDummyVariable;
@ -53,21 +56,16 @@ static portLONG lDummyVariable;
* the TCP task. This wakes the task so the interrupt can be processed. The * 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 * 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. * 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;
portBASE_TYPE xTaskWoken = pdFALSE;
extern xQueueHandle xTCPISRQueue;
/* Must be declared static. */
static portBASE_TYPE xTaskWoken;
/* As the variable is static it must be manually initialised. */
xTaskWoken = pdFALSE;
/* Just wake the TCP task so it knows an ISR has occurred. */ /* 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 /* We cannot carry on processing interrupts until the TCP task has
processed this one - so for now interrupts are disabled. The TCP task will 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. */ /* Clear the interrupt bit. */
VICVectAddr = tcpCLEAR_VIC_INTERRUPT; VICVectAddr = tcpCLEAR_VIC_INTERRUPT;
/* Switch to the TCP task immediately so the cause of the interrupt can if( xTaskWoken )
be ascertained. It is the responsibility of the TCP task to clear the {
interrupts. */ portYIELD_FROM_ISR();
portEXIT_SWITCHING_ISR( ( xTaskWoken ) ); }
}
/*-----------------------------------------------------------*/
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 ) void i2cInit( void )
{ {
extern void ( vI2C_ISR )( void ); extern void ( vI2C_ISR_Wrapper )( void );
/* Create the queue used to send messages to the ISR. */ /* Create the queue used to send messages to the ISR. */
vI2CISRCreateQueues( i2cQUEUE_LENGTH, &xMessagesForTx, &pulBusFree ); vI2CISRCreateQueues( i2cQUEUE_LENGTH, &xMessagesForTx, &pulBusFree );
@ -203,7 +203,7 @@ extern void ( vI2C_ISR )( void );
/* Setup the VIC for the i2c interrupt. */ /* Setup the VIC for the i2c interrupt. */
VICIntSelect &= ~( i2cI2C_VIC_CHANNEL_BIT ); VICIntSelect &= ~( i2cI2C_VIC_CHANNEL_BIT );
VICIntEnable |= 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; 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 )); /* The ISR entry point. */
void vI2C_ISR( void ) 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. */ /* Restore the context of whichever task is going to run next. */
static I2C_STATE eCurrentState = eSentStart; portRESTORE_CONTEXT();
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;
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. */ /* The action taken for this interrupt depends on our current state. */
switch( eCurrentState ) switch( eCurrentState )
@ -342,7 +357,10 @@ void vI2C_ISR( void )
I2C_I2CONCLR = i2cSI_BIT; I2C_I2CONCLR = i2cSI_BIT;
VICVectAddr = i2cCLEAR_VIC_INTERRUPT; VICVectAddr = i2cCLEAR_VIC_INTERRUPT;
portEXIT_SWITCHING_ISR( ( xTaskWokenByTx ) ); if( xTaskWokenByTx )
{
portYIELD_FROM_ISR();
}
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -163,9 +163,9 @@ const unsigned char ucIPAddress[ 4 ] = { emacIPADDR0, emacIPADDR1, emacIPADDR2,
/* See the header file for descriptions of public functions. */ /* 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. * 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; AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RCOMP | AT91C_EMAC_TCOMP;
/* Enable the interrupts in the AIC. */ /* 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; AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_EMAC;
} }
portEXIT_CRITICAL(); 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 "FreeRTOS.h"
#include "task.h" #include "task.h"
@ -58,26 +46,22 @@ Changes from V4.0.1
task. */ task. */
static xSemaphoreHandle xSemaphore = NULL; 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. * 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 volatile unsigned portLONG ulIntStatus, ulEventStatus;
call to the portENTER_SWITCHING_ISR() macro. This must be BEFORE any portBASE_TYPE xSwitchRequired = pdFALSE;
variable declarations. */ extern void vClearEMACTxBuffer( void );
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;
/* Find the cause of the interrupt. */ /* Find the cause of the interrupt. */
ulIntStatus = AT91C_BASE_EMAC->EMAC_ISR; ulIntStatus = AT91C_BASE_EMAC->EMAC_ISR;
@ -103,8 +87,27 @@ void vEMACISR( void )
AT91C_BASE_AIC->AIC_EOICR = 0; AT91C_BASE_AIC->AIC_EOICR = 0;
/* If a task was woken by either a frame being received then we may need to /* If a task was woken by either a frame being received then we may need to
switch to another task. */ switch to another task. If the unblocked task was of higher priority then
portEXIT_SWITCHING_ISR( xSwitchRequired ); 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 ) 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. */ /* Create the queue used to communicate between the USB ISR and task. */
xUSBInterruptQueue = xQueueCreate( usbQUEUE_LENGTH + 1, sizeof( xISRStatus * ) ); 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 /* Enable the USB interrupts - other interrupts get enabled as the
enumeration process progresses. */ 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; 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. */ /* 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_Handler( void )
void vUSB_ISR( void )
{ {
/* This ISR can cause a context switch. Therefore a call to the portCHAR cTaskWokenByPost = pdFALSE;
portENTER_SWITCHING_ISR() macro is made. This must come BEFORE any static volatile unsigned portLONG ulNextMessage = 0;
stack variable declarations. */ xISRStatus *pxMessage;
portENTER_SWITCHING_ISR(); unsigned portLONG ulRxBytes;
unsigned portCHAR ucFifoIndex;
/* 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;
/* Use the next message from the array. */ /* Use the next message from the array. */
pxMessage = &( xISRMessages[ ( ulNextMessage & usbQUEUE_LENGTH ) ] ); pxMessage = &( xISRMessages[ ( ulNextMessage & usbQUEUE_LENGTH ) ] );
@ -158,6 +151,27 @@ void vUSB_ISR( void )
AT91C_BASE_AIC->AIC_EOICR = 0; AT91C_BASE_AIC->AIC_EOICR = 0;
/* Do a task switch if needed */ /* 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();
} }

View file

@ -50,8 +50,10 @@
Changes from V4.5.0 Changes from V4.5.0
+ The macro portENTER_SWITCHING_ISR() no longer attempts to use the frame + Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
pointer. Variables declared within ISRs must now be declared static. and replaced them with portYIELD_FROM_ISR() macro. Application code
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
macros as per the V4.5.1 demo code.
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
@ -89,8 +91,8 @@
#define portSTACK_GROWTH ( -1 ) #define portSTACK_GROWTH ( -1 )
#define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) #define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ )
#define portBYTE_ALIGNMENT 4 #define portBYTE_ALIGNMENT 4
#define portYIELD() asm volatile ( "SWI" ); #define portYIELD() asm volatile ( "SWI" )
#define portNOP() asm volatile ( "NOP" ); #define portNOP() asm volatile ( "NOP" )
/* /*
* These define the timer to use for generating the tick interrupt. * These define the timer to use for generating the tick interrupt.
@ -194,29 +196,7 @@ extern volatile unsigned portLONG ulCriticalNesting; \
( void ) pxCurrentTCB; \ ( void ) pxCurrentTCB; \
} }
/*----------------------------------------------------------- #define portYIELD_FROM_ISR() vTaskSwitchContext()
* ISR entry and exit macros. These are only required if a task switch
* is required from the ISR.
*----------------------------------------------------------*/
#define portENTER_SWITCHING_ISR() \
/* Save the context of the interrupted task. */ \
portSAVE_CONTEXT(); \
{
#define portEXIT_SWITCHING_ISR( SwitchRequired ) \
/* If a switch is required then we just need to call */ \
/* vTaskSwitchContext() as the context has already been */ \
/* saved. */ \
if( SwitchRequired ) \
{ \
vTaskSwitchContext(); \
} \
} \
/* Restore the context of which ever task is now the highest */ \
/* priority that is ready to run. */ \
portRESTORE_CONTEXT();
/*-----------------------------------------------------------*/
/* Critical section handling. */ /* Critical section handling. */

View file

@ -48,8 +48,12 @@
+ The assembler statements are now included in a single asm block rather + The assembler statements are now included in a single asm block rather
than each line having its own asm block. than each line having its own asm block.
+ The macro portENTER_SWITCHING_ISR() no longer attempts to use the frame Changes from V4.5.0
pointer. Variables declared within ISRs must now be declared static.
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
and replaced them with portYIELD_FROM_ISR() macro. Application code
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
macros as per the V4.5.1 demo code.
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
@ -184,31 +188,8 @@ extern volatile unsigned portLONG ulCriticalNesting; \
} }
/*----------------------------------------------------------- #define portYIELD_FROM_ISR() vTaskSwitchContext()
* ISR entry and exit macros. These are only required if a task switch #define portYIELD() asm volatile ( "SWI" )
* is required from the ISR.
*----------------------------------------------------------*/
#define portENTER_SWITCHING_ISR() \
/* Save the context of the interrupted task. */ \
portSAVE_CONTEXT(); \
{
#define portEXIT_SWITCHING_ISR( SwitchRequired ) \
/* If a switch is required then we just need to call */ \
/* vTaskSwitchContext() as the context has already been */ \
/* saved. */ \
if( SwitchRequired ) \
{ \
vTaskSwitchContext(); \
} \
} \
/* Restore the context of which ever task is now the highest */ \
/* priority that is ready to run. */ \
portRESTORE_CONTEXT();
#define portYIELD() asm volatile ( "SWI" );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -48,8 +48,12 @@
+ The assembler statements are now included in a single asm block rather + The assembler statements are now included in a single asm block rather
than each line having its own asm block. than each line having its own asm block.
+ The macro portENTER_SWITCHING_ISR() no longer attempts to use the frame Changes from V4.5.0
pointer. Variables declared within ISRs must now be declared static.
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
and replaced them with portYIELD_FROM_ISR() macro. Application code
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
macros as per the V4.5.1 demo code.
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
@ -184,31 +188,8 @@ extern volatile unsigned portLONG ulCriticalNesting; \
} }
/*----------------------------------------------------------- #define portYIELD_FROM_ISR() vTaskSwitchContext()
* ISR entry and exit macros. These are only required if a task switch #define portYIELD() asm volatile ( "SWI" )
* is required from the ISR.
*----------------------------------------------------------*/
#define portENTER_SWITCHING_ISR() \
/* Save the context of the interrupted task. */ \
portSAVE_CONTEXT(); \
{
#define portEXIT_SWITCHING_ISR( SwitchRequired ) \
/* If a switch is required then we just need to call */ \
/* vTaskSwitchContext() as the context has already been */ \
/* saved. */ \
if( SwitchRequired ) \
{ \
vTaskSwitchContext(); \
} \
} \
/* Restore the context of which ever task is now the highest */ \
/* priority that is ready to run. */ \
portRESTORE_CONTEXT();
#define portYIELD() asm volatile ( "SWI" );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/

View file

@ -45,8 +45,12 @@
+ The assembler statements are now included in a single asm block rather + The assembler statements are now included in a single asm block rather
than each line having its own asm block. than each line having its own asm block.
+ The macro portENTER_SWITCHING_ISR() no longer attempts to use the frame Changes from V4.5.0
pointer. Variables declared within ISRs must now be declared static.
+ Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros
and replaced them with portYIELD_FROM_ISR() macro. Application code
should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()
macros as per the V4.5.1 demo code.
*/ */
#ifndef PORTMACRO_H #ifndef PORTMACRO_H
@ -181,31 +185,8 @@ extern volatile unsigned portLONG ulCriticalNesting; \
} }
/*----------------------------------------------------------- #define portYIELD_FROM_ISR() vTaskSwitchContext()
* ISR entry and exit macros. These are only required if a task switch #define portYIELD() asm volatile ( "SWI" )
* is required from the ISR.
*----------------------------------------------------------*/
#define portENTER_SWITCHING_ISR() \
/* Save the context of the interrupted task. */ \
portSAVE_CONTEXT(); \
{
#define portEXIT_SWITCHING_ISR( SwitchRequired ) \
/* If a switch is required then we just need to call */ \
/* vTaskSwitchContext() as the context has already been */ \
/* saved. */ \
if( SwitchRequired ) \
{ \
vTaskSwitchContext(); \
} \
} \
/* Restore the context of which ever task is now the highest */ \
/* priority that is ready to run. */ \
portRESTORE_CONTEXT();
#define portYIELD() asm volatile ( "SWI" );
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/