From 924ae6217ce22b16e4035c5090e9f188efab8cde Mon Sep 17 00:00:00 2001 From: richardbarry Date: Sun, 28 Oct 2007 13:55:35 +0000 Subject: [PATCH] Changed the way the ARM7/9 GCC ports enter interrupts that can cause a context switch. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@113 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- Demo/ARM7_AT91FR40008_GCC/serial/serial.c | 4 +- Demo/ARM7_AT91FR40008_GCC/serial/serialISR.c | 46 ++++++++++----- Demo/ARM7_LPC2106_GCC/FreeRTOSConfig.h | 2 +- Demo/ARM7_LPC2106_GCC/main.c | 5 +- Demo/ARM7_LPC2106_GCC/serial/serial.c | 4 +- Demo/ARM7_LPC2106_GCC/serial/serialISR.c | 45 ++++++++------ Demo/ARM7_LPC2138_Rowley/main.c | 14 +++-- Demo/ARM7_LPC2138_Rowley/mainISR.c | 41 ++++++++++--- .../RTOSDemo/webserver/EMAC_ISR.c | 34 +++++++---- .../RTOSDemo/webserver/uIP_Task.c | 6 +- Demo/ARM7_LPC2368_Rowley/webserver/EMAC_ISR.c | 40 ++++++++----- Demo/ARM7_LPC2368_Rowley/webserver/uIP_Task.c | 4 +- Demo/WizNET_DEMO_GCC_ARM7/TCP.c | 4 +- Demo/WizNET_DEMO_GCC_ARM7/TCPISR.c | 44 +++++++++----- Demo/WizNET_DEMO_GCC_ARM7/i2c.c | 4 +- Demo/WizNET_DEMO_GCC_ARM7/i2cISR.c | 42 +++++++++---- Demo/lwIP_Demo_Rowley_ARM7/EMAC/SAM7_EMAC.c | 6 +- .../EMAC/SAM7_EMAC_ISR.c | 59 ++++++++++--------- Demo/lwIP_Demo_Rowley_ARM7/USB/USB-CDC.c | 4 +- Demo/lwIP_Demo_Rowley_ARM7/USB/USBIsr.c | 50 ++++++++++------ .../portable/GCC/ARM7_AT91FR40008/portmacro.h | 34 +++-------- .../portable/GCC/ARM7_AT91SAM7S/portmacro.h | 35 +++-------- Source/portable/GCC/ARM7_LPC2000/portmacro.h | 35 +++-------- Source/portable/GCC/ARM7_LPC23xx/portmacro.h | 35 +++-------- 24 files changed, 322 insertions(+), 275 deletions(-) diff --git a/Demo/ARM7_AT91FR40008_GCC/serial/serial.c b/Demo/ARM7_AT91FR40008_GCC/serial/serial.c index 49ab7fabf..34603757a 100644 --- a/Demo/ARM7_AT91FR40008_GCC/serial/serial.c +++ b/Demo/ARM7_AT91FR40008_GCC/serial/serial.c @@ -87,7 +87,7 @@ xComPortHandle xSerialPortInitMinimal( unsigned portLONG ulWantedBaud, unsigned unsigned portLONG ulSpeed; unsigned portLONG ulCD; 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 serialISR.c (which is always compiled to ARM mode. */ @@ -139,7 +139,7 @@ extern void ( vUART_ISR )( void ); /* Setup the interrupt for USART0. 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... */ AT91C_BASE_AIC->AIC_SMR[ portUSART0_AIC_CHANNEL ] = AIC_SRCTYPE_INT_LEVEL_SENSITIVE | 1; diff --git a/Demo/ARM7_AT91FR40008_GCC/serial/serialISR.c b/Demo/ARM7_AT91FR40008_GCC/serial/serialISR.c index a8b3ad577..34d45f2eb 100644 --- a/Demo/ARM7_AT91FR40008_GCC/serial/serialISR.c +++ b/Demo/ARM7_AT91FR40008_GCC/serial/serialISR.c @@ -74,7 +74,11 @@ static xQueueHandle xCharsForTx; /* UART0 interrupt service routine. This can cause a context switch so MUST 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 ) @@ -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 - call to the portENTER_SWITCHING_ISR() macro. This must be BEFORE any - variable declarations. */ - portENTER_SWITCHING_ISR(); + /* Save the context of the interrupted task. */ + portSAVE_CONTEXT(); - /* Now we can declare the local variables. These must be static. */ - static signed portCHAR cChar; - static portBASE_TYPE xTaskWokenByTx, xTaskWokenByRx; - static unsigned portLONG ulStatus; + /* Call the handler. This must be a separate function to ensure the + stack frame is correctly set up. */ + vUART_ISR_Handler(); - /* These variables are static so need initialising manually here. */ - xTaskWokenByTx = pdFALSE; - xTaskWokenByRx = pdFALSE; + /* Restore the context of whichever task will run next. */ + portRESTORE_CONTEXT(); +} +/*-----------------------------------------------------------*/ + +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? */ 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... */ AT91C_BASE_AIC->AIC_EOICR = serCLEAR_AIC_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 ) ); + /* If an event caused a task to unblock then we call "Yield from ISR" to + ensure that the unblocked task is the task that executes when the interrupt + completes if the unblocked task has a priority higher than the interrupted + task. */ + if( xTaskWokenByTx || xTaskWokenByRx ) + { + portYIELD_FROM_ISR(); + } } /*-----------------------------------------------------------*/ diff --git a/Demo/ARM7_LPC2106_GCC/FreeRTOSConfig.h b/Demo/ARM7_LPC2106_GCC/FreeRTOSConfig.h index ffb291e88..ed948898d 100644 --- a/Demo/ARM7_LPC2106_GCC/FreeRTOSConfig.h +++ b/Demo/ARM7_LPC2106_GCC/FreeRTOSConfig.h @@ -56,7 +56,7 @@ #define configTICK_RATE_HZ ( ( portTickType ) 1000 ) #define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 ) #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 configUSE_TRACE_FACILITY 0 #define configUSE_16_BIT_TICKS 0 diff --git a/Demo/ARM7_LPC2106_GCC/main.c b/Demo/ARM7_LPC2106_GCC/main.c index f5bc1dd3c..2e3bf2b90 100644 --- a/Demo/ARM7_LPC2106_GCC/main.c +++ b/Demo/ARM7_LPC2106_GCC/main.c @@ -130,9 +130,9 @@ /* Priorities for the demo application tasks. */ #define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 ) #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 mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 ) +#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 0 ) #define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 ) /* The rate at which the on board LED will toggle when there is/is not an @@ -247,6 +247,7 @@ xTaskHandle xCreatedTask; parameter. */ ulMemCheckTaskRunningCount = mainCOUNT_INITIAL_VALUE; xCreatedTask = mainNO_TASK; + 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. */ diff --git a/Demo/ARM7_LPC2106_GCC/serial/serial.c b/Demo/ARM7_LPC2106_GCC/serial/serial.c index bbb5b207a..694d8a890 100644 --- a/Demo/ARM7_LPC2106_GCC/serial/serial.c +++ b/Demo/ARM7_LPC2106_GCC/serial/serial.c @@ -118,7 +118,7 @@ xComPortHandle xSerialPortInitMinimal( unsigned portLONG ulWantedBaud, unsigned { unsigned portLONG ulDivisor, ulWantedClock; 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 serialISR.c (which is always compiled to ARM mode. */ @@ -153,7 +153,7 @@ extern void ( vUART_ISR )( void ); /* Setup the VIC for the UART. */ VICIntSelect &= ~( 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; /* Enable UART0 interrupts. */ diff --git a/Demo/ARM7_LPC2106_GCC/serial/serialISR.c b/Demo/ARM7_LPC2106_GCC/serial/serialISR.c index 34d542f7c..4aaae9856 100644 --- a/Demo/ARM7_LPC2106_GCC/serial/serialISR.c +++ b/Demo/ARM7_LPC2106_GCC/serial/serialISR.c @@ -80,9 +80,11 @@ static volatile portLONG lTHREEmpty; */ 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 -be declared "naked". */ -void vUART_ISR( void ) __attribute__ ((naked)); +/* UART0 interrupt service routine entry point. */ +void vUART_ISR_Wrapper( void ) __attribute__ ((naked)); + +/* UART0 interrupt service routine handler. */ +void vUART_ISR_Handler( void ); /*-----------------------------------------------------------*/ 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 - call to the portENTER_SWITCHING_ISR() macro. This must be BEFORE any - variable declarations. */ - portENTER_SWITCHING_ISR(); + /* Save the context of the interrupted task. */ + portSAVE_CONTEXT(); + + /* Call the handler. This must be a separate function from the wrapper + to ensure the correct stack frame is set up. */ + vUART_ISR_Handler(); - /* Now we can declare the local variables. These must be static. */ - static signed portCHAR cChar; - static portBASE_TYPE xTaskWokenByTx, xTaskWokenByRx; + /* Restore the context of whichever task is going to run next. */ + portRESTORE_CONTEXT(); +} +/*-----------------------------------------------------------*/ - /* As these variables are static they must be initialised manually here. */ - xTaskWokenByTx = pdFALSE; - xTaskWokenByRx = pdFALSE; +void vUART_ISR_Handler( void ) +{ +signed portCHAR cChar; +portBASE_TYPE xTaskWokenByTx = pdFALSE, xTaskWokenByRx = pdFALSE; /* What caused the interrupt? */ switch( UART0_IIR & serINTERRUPT_SOURCE_MASK ) @@ -154,14 +160,15 @@ void vUART_ISR( void ) break; } + if( xTaskWokenByTx || xTaskWokenByRx ) + { + portYIELD_FROM_ISR(); + } + /* Clear the ISR in the VIC. */ 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 ) ); } -/*-----------------------------------------------------------*/ + diff --git a/Demo/ARM7_LPC2138_Rowley/main.c b/Demo/ARM7_LPC2138_Rowley/main.c index 1e6e33944..ab1e2ecd1 100644 --- a/Demo/ARM7_LPC2138_Rowley/main.c +++ b/Demo/ARM7_LPC2138_Rowley/main.c @@ -96,6 +96,8 @@ #define mainLED_DELAY ( ( portTickType ) 500 / portTICK_RATE_MS ) #define mainCHECK_DELAY ( ( portTickType ) 5000 / portTICK_RATE_MS ) #define mainLIST_BUFFER_SIZE 2048 +#define mainNO_DELAY ( 0 ) +#define mainSHORT_DELAY ( 150 / portTICK_RATE_MS ) /* Task priorities. */ #define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) @@ -178,7 +180,7 @@ int main( void ) /* Start the scheduler. */ 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. */ return 0; @@ -290,7 +292,7 @@ static void vButtonHandlerTask( void *pvParameters ) static portCHAR cListBuffer[ mainLIST_BUFFER_SIZE ]; const portCHAR *pcList = &( cListBuffer[ 0 ] ); const portCHAR * const pcHeader = "\nTask State Priority Stack #\n************************************************"; -extern void (vButtonISR) ( void ); +extern void (vButtonISRWrapper) ( void ); /* Configure the interrupt. */ portENTER_CRITICAL(); @@ -303,15 +305,19 @@ extern void (vButtonISR) ( void ); /* Setup the VIC for EINT 1. */ VICIntSelect &= ~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; } portEXIT_CRITICAL(); for( ;; ) { + /* For debouncing, wait a while then clear the semaphore. */ + vTaskDelay( mainSHORT_DELAY ); + xSemaphoreTake( xButtonSemaphore, mainNO_DELAY ); + /* Wait for an interrupt. */ - while( xSemaphoreTake( xButtonSemaphore, portMAX_DELAY ) != pdPASS ); + xSemaphoreTake( xButtonSemaphore, portMAX_DELAY ); /* Send the column headers to the print task for display. */ xQueueSend( xPrintQueue, &pcHeader, portMAX_DELAY ); diff --git a/Demo/ARM7_LPC2138_Rowley/mainISR.c b/Demo/ARM7_LPC2138_Rowley/mainISR.c index ae9370562..7890a9638 100644 --- a/Demo/ARM7_LPC2138_Rowley/mainISR.c +++ b/Demo/ARM7_LPC2138_Rowley/mainISR.c @@ -39,18 +39,43 @@ /* * 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; -void vButtonISR( void ) + if( xSemaphoreGiveFromISR( xButtonSemaphore, pdFALSE ) ) + { + /* We have woken a task. Calling "yield from ISR" here will ensure + the interrupt returns to the woken task if it has a priority higher + than the interrupted task. */ + portYIELD_FROM_ISR(); + } + + EXTINT = isrCLEAR_EINT_1; + VICVectAddr = 0; +} +/*-----------------------------------------------------------*/ + +void vButtonISRWrapper( void ) { - portENTER_SWITCHING_ISR(); - xSemaphoreGiveFromISR( xButtonSemaphore, pdFALSE ); - EXTINT = isrCLEAR_EINT_1; - VICVectAddr = 0; - portEXIT_SWITCHING_ISR( pdTRUE ); + /* 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(); } diff --git a/Demo/ARM7_LPC2368_Eclipse/RTOSDemo/webserver/EMAC_ISR.c b/Demo/ARM7_LPC2368_Eclipse/RTOSDemo/webserver/EMAC_ISR.c index 495fea500..b78837d13 100644 --- a/Demo/ARM7_LPC2368_Eclipse/RTOSDemo/webserver/EMAC_ISR.c +++ b/Demo/ARM7_LPC2368_Eclipse/RTOSDemo/webserver/EMAC_ISR.c @@ -2,17 +2,18 @@ #include "Semphr.h" #include "Task.h" -void vEMAC_ISR( void ) __attribute__((naked)); +/* The interrupt entry point. */ +void vEMAC_ISR_Wrapper( void ) __attribute__((naked)); -extern xSemaphoreHandle xEMACSemaphore; +/* The handler that does the actual work. */ +void vEMAC_ISR_Handler( void ); -void vEMAC_ISR( void ) -{ - portENTER_SWITCHING_ISR(); +extern xSemaphoreHandle xEMACSemaphore; - static portBASE_TYPE xSwitchRequired; - xSwitchRequired = pdFALSE; +void vEMAC_ISR_Handler( void ) +{ +portBASE_TYPE xSwitchRequired = pdFALSE; /* Clear the interrupt. */ MAC_INTCLEAR = 0xffff; @@ -21,11 +22,22 @@ void vEMAC_ISR( void ) /* Ensure the uIP task is not blocked as data has arrived. */ if( xSemaphoreGiveFromISR( xEMACSemaphore, pdFALSE ) ) { - xSwitchRequired = pdTRUE; + /* Giving the semaphore woke a task. */ + portYIELD_FROM_ISR(); } - - /* Switch to the uIP task. */ - portEXIT_SWITCHING_ISR( xSwitchRequired ); } +/*-----------------------------------------------------------*/ +void vEMAC_ISR_Wrapper( void ) +{ + /* 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(); +} diff --git a/Demo/ARM7_LPC2368_Eclipse/RTOSDemo/webserver/uIP_Task.c b/Demo/ARM7_LPC2368_Eclipse/RTOSDemo/webserver/uIP_Task.c index 1520d1524..77e1ec278 100644 --- a/Demo/ARM7_LPC2368_Eclipse/RTOSDemo/webserver/uIP_Task.c +++ b/Demo/ARM7_LPC2368_Eclipse/RTOSDemo/webserver/uIP_Task.c @@ -62,7 +62,7 @@ #define uipIP_ADDR0 172 #define uipIP_ADDR1 25 #define uipIP_ADDR2 218 -#define uipIP_ADDR3 10 +#define uipIP_ADDR3 16 /* How long to wait before attempting to connect the MAC again. */ #define uipINIT_WAIT 100 @@ -115,7 +115,7 @@ void vuIP_Task( void *pvParameters ) portBASE_TYPE i; uip_ipaddr_t xIPAddr; 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. */ vSemaphoreCreateBinary( xEMACSemaphore ); @@ -138,7 +138,7 @@ extern void ( vEMAC_ISR )( void ); { MAC_INTENABLE = INT_RX_DONE; VICIntEnable |= 0x00200000; - VICVectAddr21 = ( portLONG ) vEMAC_ISR; + VICVectAddr21 = ( portLONG ) vEMAC_ISR_Wrapper; prvSetMACAddress(); } portEXIT_CRITICAL(); diff --git a/Demo/ARM7_LPC2368_Rowley/webserver/EMAC_ISR.c b/Demo/ARM7_LPC2368_Rowley/webserver/EMAC_ISR.c index 9df1ffe26..1796ce757 100644 --- a/Demo/ARM7_LPC2368_Rowley/webserver/EMAC_ISR.c +++ b/Demo/ARM7_LPC2368_Rowley/webserver/EMAC_ISR.c @@ -2,21 +2,17 @@ #include "Semphr.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; -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. */ IntClear = 0xffff; VICVectAddr = 0; @@ -24,11 +20,27 @@ void vEMAC_ISR( void ) /* Ensure the uIP task is not blocked as data has arrived. */ 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. */ - portEXIT_SWITCHING_ISR( xSwitchRequired ); +void vEMAC_ISR_Wrapper( void ) +{ + /* 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(); } + + diff --git a/Demo/ARM7_LPC2368_Rowley/webserver/uIP_Task.c b/Demo/ARM7_LPC2368_Rowley/webserver/uIP_Task.c index 304004f02..1c16824e9 100644 --- a/Demo/ARM7_LPC2368_Rowley/webserver/uIP_Task.c +++ b/Demo/ARM7_LPC2368_Rowley/webserver/uIP_Task.c @@ -115,7 +115,7 @@ void vuIP_Task( void *pvParameters ) portBASE_TYPE i; uip_ipaddr_t xIPAddr; 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. */ vSemaphoreCreateBinary( xEMACSemaphore ); @@ -138,7 +138,7 @@ extern void ( vEMAC_ISR )( void ); { IntEnable = INT_RX_DONE; VICIntEnable |= 0x00200000; - VICVectAddr21 = ( portLONG ) vEMAC_ISR; + VICVectAddr21 = ( portLONG ) vEMAC_ISR_Wrapper; prvSetMACAddress(); } portEXIT_CRITICAL(); diff --git a/Demo/WizNET_DEMO_GCC_ARM7/TCP.c b/Demo/WizNET_DEMO_GCC_ARM7/TCP.c index c1639b079..71262a07e 100644 --- a/Demo/WizNET_DEMO_GCC_ARM7/TCP.c +++ b/Demo/WizNET_DEMO_GCC_ARM7/TCP.c @@ -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; } diff --git a/Demo/WizNET_DEMO_GCC_ARM7/TCPISR.c b/Demo/WizNET_DEMO_GCC_ARM7/TCPISR.c index 5b1d3bff6..94261378e 100644 --- a/Demo/WizNET_DEMO_GCC_ARM7/TCPISR.c +++ b/Demo/WizNET_DEMO_GCC_ARM7/TCPISR.c @@ -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(); } diff --git a/Demo/WizNET_DEMO_GCC_ARM7/i2c.c b/Demo/WizNET_DEMO_GCC_ARM7/i2c.c index 19cd69da0..7b9bbfcd2 100644 --- a/Demo/WizNET_DEMO_GCC_ARM7/i2c.c +++ b/Demo/WizNET_DEMO_GCC_ARM7/i2c.c @@ -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; } diff --git a/Demo/WizNET_DEMO_GCC_ARM7/i2cISR.c b/Demo/WizNET_DEMO_GCC_ARM7/i2cISR.c index cfb4e9aad..22d6df619 100644 --- a/Demo/WizNET_DEMO_GCC_ARM7/i2cISR.c +++ b/Demo/WizNET_DEMO_GCC_ARM7/i2cISR.c @@ -119,21 +119,36 @@ void vI2CISRCreateQueues( unsigned portBASE_TYPE uxQueueLength, xQueueHandle *px } /*-----------------------------------------------------------*/ -void vI2C_ISR( void ) __attribute__ (( naked )); -void vI2C_ISR( void ) -{ - portENTER_SWITCHING_ISR(); +/* The ISR entry point. */ +void vI2C_ISR_Wrapper( void ) __attribute__ (( naked )); - /* Variables must be static. */ +/* 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 ); - /* 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; +void vI2C_ISR_Wrapper( void ) +{ + /* Save the context of the interrupted task. */ + portSAVE_CONTEXT(); + /* 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(); + + /* 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(); + } } /*-----------------------------------------------------------*/ diff --git a/Demo/lwIP_Demo_Rowley_ARM7/EMAC/SAM7_EMAC.c b/Demo/lwIP_Demo_Rowley_ARM7/EMAC/SAM7_EMAC.c index f5477f74c..8e7665845 100644 --- a/Demo/lwIP_Demo_Rowley_ARM7/EMAC/SAM7_EMAC.c +++ b/Demo/lwIP_Demo_Rowley_ARM7/EMAC/SAM7_EMAC.c @@ -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(); diff --git a/Demo/lwIP_Demo_Rowley_ARM7/EMAC/SAM7_EMAC_ISR.c b/Demo/lwIP_Demo_Rowley_ARM7/EMAC/SAM7_EMAC_ISR.c index 32d982fe3..a8a717843 100644 --- a/Demo/lwIP_Demo_Rowley_ARM7/EMAC/SAM7_EMAC_ISR.c +++ b/Demo/lwIP_Demo_Rowley_ARM7/EMAC/SAM7_EMAC_ISR.c @@ -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(); } /*-----------------------------------------------------------*/ diff --git a/Demo/lwIP_Demo_Rowley_ARM7/USB/USB-CDC.c b/Demo/lwIP_Demo_Rowley_ARM7/USB/USB-CDC.c index 92a7f3cce..47a9939f5 100644 --- a/Demo/lwIP_Demo_Rowley_ARM7/USB/USB-CDC.c +++ b/Demo/lwIP_Demo_Rowley_ARM7/USB/USB-CDC.c @@ -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; diff --git a/Demo/lwIP_Demo_Rowley_ARM7/USB/USBIsr.c b/Demo/lwIP_Demo_Rowley_ARM7/USB/USBIsr.c index db1f9cf91..85f233f30 100644 --- a/Demo/lwIP_Demo_Rowley_ARM7/USB/USBIsr.c +++ b/Demo/lwIP_Demo_Rowley_ARM7/USB/USBIsr.c @@ -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(); } + diff --git a/Source/portable/GCC/ARM7_AT91FR40008/portmacro.h b/Source/portable/GCC/ARM7_AT91FR40008/portmacro.h index 2458050a3..60baa50ea 100644 --- a/Source/portable/GCC/ARM7_AT91FR40008/portmacro.h +++ b/Source/portable/GCC/ARM7_AT91FR40008/portmacro.h @@ -50,8 +50,10 @@ Changes from V4.5.0 - + The macro portENTER_SWITCHING_ISR() no longer attempts to use the frame - 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 @@ -89,8 +91,8 @@ #define portSTACK_GROWTH ( -1 ) #define portTICK_RATE_MS ( ( portTickType ) 1000 / configTICK_RATE_HZ ) #define portBYTE_ALIGNMENT 4 -#define portYIELD() asm volatile ( "SWI" ); -#define portNOP() asm volatile ( "NOP" ); +#define portYIELD() asm volatile ( "SWI" ) +#define portNOP() asm volatile ( "NOP" ) /* * These define the timer to use for generating the tick interrupt. @@ -194,29 +196,7 @@ extern volatile unsigned portLONG ulCriticalNesting; \ ( void ) pxCurrentTCB; \ } -/*----------------------------------------------------------- - * 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(); -/*-----------------------------------------------------------*/ +#define portYIELD_FROM_ISR() vTaskSwitchContext() /* Critical section handling. */ diff --git a/Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h b/Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h index 9ec48a238..d5d2ece77 100644 --- a/Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h +++ b/Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h @@ -48,8 +48,12 @@ + The assembler statements are now included in a single asm block rather than each line having its own asm block. - + The macro portENTER_SWITCHING_ISR() no longer attempts to use the frame - pointer. Variables declared within ISRs must now be declared static. + Changes from V4.5.0 + + + 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 @@ -184,31 +188,8 @@ extern volatile unsigned portLONG ulCriticalNesting; \ } -/*----------------------------------------------------------- - * 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(); - -#define portYIELD() asm volatile ( "SWI" ); +#define portYIELD_FROM_ISR() vTaskSwitchContext() +#define portYIELD() asm volatile ( "SWI" ) /*-----------------------------------------------------------*/ diff --git a/Source/portable/GCC/ARM7_LPC2000/portmacro.h b/Source/portable/GCC/ARM7_LPC2000/portmacro.h index 9ec48a238..d5d2ece77 100644 --- a/Source/portable/GCC/ARM7_LPC2000/portmacro.h +++ b/Source/portable/GCC/ARM7_LPC2000/portmacro.h @@ -48,8 +48,12 @@ + The assembler statements are now included in a single asm block rather than each line having its own asm block. - + The macro portENTER_SWITCHING_ISR() no longer attempts to use the frame - pointer. Variables declared within ISRs must now be declared static. + Changes from V4.5.0 + + + 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 @@ -184,31 +188,8 @@ extern volatile unsigned portLONG ulCriticalNesting; \ } -/*----------------------------------------------------------- - * 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(); - -#define portYIELD() asm volatile ( "SWI" ); +#define portYIELD_FROM_ISR() vTaskSwitchContext() +#define portYIELD() asm volatile ( "SWI" ) /*-----------------------------------------------------------*/ diff --git a/Source/portable/GCC/ARM7_LPC23xx/portmacro.h b/Source/portable/GCC/ARM7_LPC23xx/portmacro.h index d6d3f4de5..c74b3d017 100644 --- a/Source/portable/GCC/ARM7_LPC23xx/portmacro.h +++ b/Source/portable/GCC/ARM7_LPC23xx/portmacro.h @@ -45,8 +45,12 @@ + The assembler statements are now included in a single asm block rather than each line having its own asm block. - + The macro portENTER_SWITCHING_ISR() no longer attempts to use the frame - pointer. Variables declared within ISRs must now be declared static. + Changes from V4.5.0 + + + 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 @@ -181,31 +185,8 @@ extern volatile unsigned portLONG ulCriticalNesting; \ } -/*----------------------------------------------------------- - * 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(); - -#define portYIELD() asm volatile ( "SWI" ); +#define portYIELD_FROM_ISR() vTaskSwitchContext() +#define portYIELD() asm volatile ( "SWI" ) /*-----------------------------------------------------------*/ -- 2.39.5