unsigned portLONG ulSpeed;\r
 unsigned portLONG ulCD;\r
 xComPortHandle xReturn = serHANDLE;\r
-extern void ( vUART_ISR )( void );\r
+extern void ( vUART_ISR_Wrapper )( void );\r
 \r
        /* The queues are used in the serial ISR routine, so are created from\r
        serialISR.c (which is always compiled to ARM mode. */\r
                        /* Setup the interrupt for USART0.\r
 \r
                        Store interrupt handler function address in USART0 vector register... */\r
-                       AT91C_BASE_AIC->AIC_SVR[ portUSART0_AIC_CHANNEL ] = (unsigned long)vUART_ISR;\r
+                       AT91C_BASE_AIC->AIC_SVR[ portUSART0_AIC_CHANNEL ] = (unsigned long)vUART_ISR_Wrapper;\r
                        \r
                        /* USART0 interrupt level-sensitive, priority 1... */\r
                        AT91C_BASE_AIC->AIC_SMR[ portUSART0_AIC_CHANNEL ] = AIC_SRCTYPE_INT_LEVEL_SENSITIVE | 1;\r
 
 \r
 /* UART0 interrupt service routine.  This can cause a context switch so MUST\r
 be declared "naked". */\r
-void vUART_ISR( void ) __attribute__ ((naked));\r
+void vUART_ISR_Wrapper( void ) __attribute__ ((naked));\r
+\r
+/* The ISR function that actually performs the work.  This must be separate \r
+from the wrapper to ensure the correct stack frame is set up. */\r
+void vUART_ISR_Handler( void );\r
 \r
 /*-----------------------------------------------------------*/\r
 void vSerialISRCreateQueues( unsigned portBASE_TYPE uxQueueLength, xQueueHandle *pxRxedChars, xQueueHandle *pxCharsForTx )\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-void vUART_ISR( void )\r
+void vUART_ISR_Wrapper( void )\r
 {\r
-       /* This ISR can cause a context switch, so the first statement must be a\r
-       call to the portENTER_SWITCHING_ISR() macro.  This must be BEFORE any\r
-       variable declarations. */\r
-       portENTER_SWITCHING_ISR();\r
+       /* Save the context of the interrupted task. */\r
+       portSAVE_CONTEXT();\r
 \r
-       /* Now we can declare the local variables.   These must be static. */\r
-       static signed portCHAR cChar;\r
-       static portBASE_TYPE xTaskWokenByTx, xTaskWokenByRx;\r
-       static unsigned portLONG ulStatus;\r
+       /* Call the handler.  This must be a separate function to ensure the \r
+       stack frame is correctly set up. */\r
+       vUART_ISR_Handler();\r
 \r
-       /* These variables are static so need initialising manually here. */\r
-       xTaskWokenByTx = pdFALSE;\r
-       xTaskWokenByRx = pdFALSE;\r
+       /* Restore the context of whichever task will run next. */\r
+       portRESTORE_CONTEXT();\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vUART_ISR_Handler( void )\r
+{\r
+/* Now we can declare the local variables.   These must be static. */\r
+signed portCHAR cChar;\r
+portBASE_TYPE xTaskWokenByTx = pdFALSE, xTaskWokenByRx = pdFALSE;\r
+unsigned portLONG ulStatus;\r
 \r
        /* What caused the interrupt? */\r
        ulStatus = AT91C_BASE_US0->US_CSR & AT91C_BASE_US0->US_IMR;\r
        /* Acknowledge the interrupt at AIC level... */\r
        AT91C_BASE_AIC->AIC_EOICR = serCLEAR_AIC_INTERRUPT;\r
 \r
-       /* Exit the ISR.  If a task was woken by either a character being received\r
-       or transmitted then a context switch will occur. */\r
-       portEXIT_SWITCHING_ISR( ( xTaskWokenByTx || xTaskWokenByRx ) );\r
+       /* If an event caused a task to unblock then we call "Yield from ISR" to\r
+       ensure that the unblocked task is the task that executes when the interrupt\r
+       completes if the unblocked task has a priority higher than the interrupted\r
+       task. */\r
+       if( xTaskWokenByTx || xTaskWokenByRx )\r
+       {\r
+               portYIELD_FROM_ISR();\r
+       }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
 
 #define configTICK_RATE_HZ                     ( ( portTickType ) 1000 )\r
 #define configMAX_PRIORITIES           ( ( unsigned portBASE_TYPE ) 5 )\r
 #define configMINIMAL_STACK_SIZE       ( ( unsigned portSHORT ) 128 )\r
-#define configTOTAL_HEAP_SIZE          ( ( size_t ) ( 23 * 1024 ) )\r
+#define configTOTAL_HEAP_SIZE          ( ( size_t ) ( 24 * 1024 ) )\r
 #define configMAX_TASK_NAME_LEN                ( 16 )\r
 #define configUSE_TRACE_FACILITY       0\r
 #define configUSE_16_BIT_TICKS         0\r
 
 /* Priorities for the demo application tasks. */\r
 #define mainLED_TASK_PRIORITY          ( tskIDLE_PRIORITY + 3 )\r
 #define mainCOM_TEST_PRIORITY          ( tskIDLE_PRIORITY + 2 )\r
-#define mainQUEUE_POLL_PRIORITY                ( tskIDLE_PRIORITY + 2 )\r
+#define mainQUEUE_POLL_PRIORITY                ( tskIDLE_PRIORITY + 0 )\r
 #define mainCHECK_TASK_PRIORITY                ( tskIDLE_PRIORITY + 4 )\r
-#define mainSEM_TEST_PRIORITY          ( tskIDLE_PRIORITY + 1 )\r
+#define mainSEM_TEST_PRIORITY          ( tskIDLE_PRIORITY + 0 )\r
 #define mainBLOCK_Q_PRIORITY           ( tskIDLE_PRIORITY + 2 )\r
 \r
 /* The rate at which the on board LED will toggle when there is/is not an \r
                parameter. */\r
                ulMemCheckTaskRunningCount = mainCOUNT_INITIAL_VALUE;\r
                xCreatedTask = mainNO_TASK;\r
+\r
                if( xTaskCreate( vMemCheckTask, ( signed portCHAR * ) "MEM_CHECK", configMINIMAL_STACK_SIZE, ( void * ) &ulMemCheckTaskRunningCount, tskIDLE_PRIORITY, &xCreatedTask ) != pdPASS )\r
                {\r
                        /* Could not create the task - we have probably run out of heap. */\r
 
 {\r
 unsigned portLONG ulDivisor, ulWantedClock;\r
 xComPortHandle xReturn = serHANDLE;\r
-extern void ( vUART_ISR )( void );\r
+extern void ( vUART_ISR_Wrapper )( void );\r
 \r
        /* The queues are used in the serial ISR routine, so are created from\r
        serialISR.c (which is always compiled to ARM mode. */\r
                        /* Setup the VIC for the UART. */\r
                        VICIntSelect &= ~( serUART0_VIC_CHANNEL_BIT );\r
                        VICIntEnable |= serUART0_VIC_CHANNEL_BIT;\r
-                       VICVectAddr1 = ( portLONG ) vUART_ISR;\r
+                       VICVectAddr1 = ( portLONG ) vUART_ISR_Wrapper;\r
                        VICVectCntl1 = serUART0_VIC_CHANNEL | serUART0_VIC_ENABLE;\r
 \r
                        /* Enable UART0 interrupts. */\r
 
  */\r
 void vSerialISRCreateQueues( unsigned portBASE_TYPE uxQueueLength, xQueueHandle *pxRxedChars, xQueueHandle *pxCharsForTx, portLONG volatile **pplTHREEmptyFlag );\r
 \r
-/* UART0 interrupt service routine.  This can cause a context switch so MUST\r
-be declared "naked". */\r
-void vUART_ISR( void ) __attribute__ ((naked));\r
+/* UART0 interrupt service routine entry point. */\r
+void vUART_ISR_Wrapper( void ) __attribute__ ((naked));\r
+\r
+/* UART0 interrupt service routine handler. */\r
+void vUART_ISR_Handler( void );\r
 \r
 /*-----------------------------------------------------------*/\r
 void vSerialISRCreateQueues(   unsigned portBASE_TYPE uxQueueLength, xQueueHandle *pxRxedChars, \r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-void vUART_ISR( void )\r
+void vUART_ISR_Wrapper( void )\r
 {\r
-       /* This ISR can cause a context switch, so the first statement must be a\r
-       call to the portENTER_SWITCHING_ISR() macro.  This must be BEFORE any\r
-       variable declarations. */\r
-       portENTER_SWITCHING_ISR();\r
+       /* Save the context of the interrupted task. */\r
+       portSAVE_CONTEXT();\r
+\r
+       /* Call the handler.  This must be a separate function from the wrapper\r
+       to ensure the correct stack frame is set up. */\r
+       vUART_ISR_Handler();\r
 \r
-       /* Now we can declare the local variables.   These must be static. */\r
-       static signed portCHAR cChar;\r
-       static portBASE_TYPE xTaskWokenByTx, xTaskWokenByRx;\r
+       /* Restore the context of whichever task is going to run next. */\r
+       portRESTORE_CONTEXT();\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
-       /* As these variables are static they must be initialised manually here. */\r
-       xTaskWokenByTx = pdFALSE;\r
-       xTaskWokenByRx = pdFALSE;\r
+void vUART_ISR_Handler( void )\r
+{\r
+signed portCHAR cChar;\r
+portBASE_TYPE xTaskWokenByTx = pdFALSE, xTaskWokenByRx = pdFALSE;\r
 \r
        /* What caused the interrupt? */\r
        switch( UART0_IIR & serINTERRUPT_SOURCE_MASK )\r
                                                                break;\r
        }\r
 \r
+       if( xTaskWokenByTx || xTaskWokenByRx )\r
+       {\r
+               portYIELD_FROM_ISR();\r
+       }\r
+\r
        /* Clear the ISR in the VIC. */\r
        VICVectAddr = serCLEAR_VIC_INTERRUPT;\r
-\r
-       /* Exit the ISR.  If a task was woken by either a character being received\r
-       or transmitted then a context switch will occur. */\r
-       portEXIT_SWITCHING_ISR( ( xTaskWokenByTx || xTaskWokenByRx ) );\r
 }\r
-/*-----------------------------------------------------------*/\r
+\r
 \r
 \r
 \r
 
 #define mainLED_DELAY                                          ( ( portTickType ) 500 / portTICK_RATE_MS )\r
 #define mainCHECK_DELAY                                                ( ( portTickType ) 5000 / portTICK_RATE_MS )\r
 #define mainLIST_BUFFER_SIZE                           2048\r
+#define mainNO_DELAY                                           ( 0 )\r
+#define mainSHORT_DELAY                                                ( 150 / portTICK_RATE_MS )\r
 \r
 /* Task priorities. */\r
 #define mainLED_TASK_PRIORITY                          ( tskIDLE_PRIORITY + 2 )\r
        /* Start the scheduler. */\r
        vTaskStartScheduler();\r
 \r
-       /* The scheduler should now running, so we will only ever reach here if we\r
+       /* The scheduler should now be running, so we will only ever reach here if we\r
        ran out of heap space. */\r
 \r
        return 0;\r
 static portCHAR cListBuffer[ mainLIST_BUFFER_SIZE ];\r
 const portCHAR *pcList = &( cListBuffer[ 0 ] );\r
 const portCHAR * const pcHeader = "\nTask          State  Priority  Stack      #\n************************************************";\r
-extern void (vButtonISR) ( void );\r
+extern void (vButtonISRWrapper) ( void );\r
 \r
        /* Configure the interrupt. */\r
        portENTER_CRITICAL();   \r
                /* Setup the VIC for EINT 1. */\r
                VICIntSelect &= ~mainEINT_1_VIC_CHANNEL_BIT;\r
                VICIntEnable |= mainEINT_1_VIC_CHANNEL_BIT;\r
-               VICVectAddr1 = ( portLONG ) vButtonISR;\r
+               VICVectAddr1 = ( portLONG ) vButtonISRWrapper;\r
                VICVectCntl1 = mainEINT_1_ENABLE_BIT | mainEINT_1_CHANNEL;\r
        }\r
        portEXIT_CRITICAL();\r
 \r
        for( ;; )\r
        {\r
+               /* For debouncing, wait a while then clear the semaphore. */\r
+               vTaskDelay( mainSHORT_DELAY );\r
+               xSemaphoreTake( xButtonSemaphore, mainNO_DELAY );\r
+\r
                /* Wait for an interrupt. */\r
-               while( xSemaphoreTake( xButtonSemaphore, portMAX_DELAY ) != pdPASS );\r
+               xSemaphoreTake( xButtonSemaphore, portMAX_DELAY );\r
 \r
                /* Send the column headers to the print task for display. */\r
                xQueueSend( xPrintQueue, &pcHeader, portMAX_DELAY );\r
 
 \r
 /*\r
  * Interrupt routine that simply wakes vButtonHandlerTask on each interrupt \r
- * generated by a push of the built in button.\r
+ * generated by a push of the built in button.  The wrapper takes care of\r
+ * the ISR entry.  This then calls the actual handler function to perform\r
+ * the work.  This work should not be done in the wrapper itself unless\r
+ * you are absolutely sure that no stack space is used.\r
  */\r
-void vButtonISR( void ) __attribute__ ((naked));\r
+void vButtonISRWrapper( void ) __attribute__ ((naked));\r
+void vButtonHandler( void );\r
+\r
+void vButtonHandler( void )\r
+{\r
 extern xSemaphoreHandle xButtonSemaphore;\r
 \r
-void vButtonISR( void )\r
+       if( xSemaphoreGiveFromISR( xButtonSemaphore, pdFALSE ) )\r
+       {\r
+               /* We have woken a task.  Calling "yield from ISR" here will ensure\r
+               the interrupt returns to the woken task if it has a priority higher\r
+               than the interrupted task. */\r
+               portYIELD_FROM_ISR();\r
+       }\r
+\r
+    EXTINT = isrCLEAR_EINT_1;\r
+    VICVectAddr = 0;\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vButtonISRWrapper( void )\r
 {\r
-       portENTER_SWITCHING_ISR();\r
-               xSemaphoreGiveFromISR( xButtonSemaphore, pdFALSE );\r
-        EXTINT = isrCLEAR_EINT_1;\r
-        VICVectAddr = 0;\r
-       portEXIT_SWITCHING_ISR( pdTRUE );\r
+       /* Save the context of the interrupted task. */\r
+       portSAVE_CONTEXT();\r
+\r
+       /* Call the handler to do the work.  This must be a separate function to\r
+       the wrapper to ensure the correct stack frame is set up. */\r
+       vButtonHandler();\r
+\r
+       /* Restore the context of whichever task is going to run once the interrupt\r
+       completes. */\r
+       portRESTORE_CONTEXT();\r
 }\r
 \r
 \r
 
 #include "Semphr.h"\r
 #include "Task.h"\r
 \r
-void vEMAC_ISR( void ) __attribute__((naked));\r
+/* The interrupt entry point. */\r
+void vEMAC_ISR_Wrapper( void ) __attribute__((naked));\r
 \r
-extern xSemaphoreHandle xEMACSemaphore;\r
+/* The handler that does the actual work. */\r
+void vEMAC_ISR_Handler( void );\r
 \r
-void vEMAC_ISR( void )\r
-{\r
-    portENTER_SWITCHING_ISR();\r
+extern xSemaphoreHandle xEMACSemaphore;\r
 \r
-    static portBASE_TYPE xSwitchRequired;\r
 \r
-       xSwitchRequired = pdFALSE;\r
+void vEMAC_ISR_Handler( void )\r
+{\r
+portBASE_TYPE xSwitchRequired = pdFALSE;\r
 \r
     /* Clear the interrupt. */\r
     MAC_INTCLEAR = 0xffff;\r
     /* Ensure the uIP task is not blocked as data has arrived. */\r
     if( xSemaphoreGiveFromISR( xEMACSemaphore, pdFALSE ) )\r
     {\r
-        xSwitchRequired = pdTRUE;\r
+       /* Giving the semaphore woke a task. */\r
+        portYIELD_FROM_ISR();\r
     }\r
-\r
-    /* Switch to the uIP task. */\r
-    portEXIT_SWITCHING_ISR( xSwitchRequired );\r
 }\r
+/*-----------------------------------------------------------*/\r
 \r
+void vEMAC_ISR_Wrapper( void )\r
+{\r
+       /* Save the context of the interrupted task. */\r
+    portSAVE_CONTEXT();\r
+    \r
+    /* Call the handler.  This must be a separate function unless you can\r
+    guarantee that no stack will be used. */\r
+    vEMAC_ISR_Handler();\r
+    \r
+    /* Restore the context of whichever task is going to run next. */\r
+    portRESTORE_CONTEXT();\r
+}\r
 \r
 
 #define uipIP_ADDR0            172\r
 #define uipIP_ADDR1            25\r
 #define uipIP_ADDR2            218\r
-#define uipIP_ADDR3            10      \r
+#define uipIP_ADDR3            16      \r
 \r
 /* How long to wait before attempting to connect the MAC again. */\r
 #define uipINIT_WAIT    100\r
 portBASE_TYPE i;\r
 uip_ipaddr_t xIPAddr;\r
 struct timer periodic_timer, arp_timer;\r
-extern void ( vEMAC_ISR )( void );\r
+extern void ( vEMAC_ISR_Wrapper )( void );\r
 \r
        /* Create the semaphore used by the ISR to wake this task. */\r
        vSemaphoreCreateBinary( xEMACSemaphore );\r
        {\r
                MAC_INTENABLE = INT_RX_DONE;\r
         VICIntEnable |= 0x00200000;\r
-        VICVectAddr21 = ( portLONG ) vEMAC_ISR;\r
+        VICVectAddr21 = ( portLONG ) vEMAC_ISR_Wrapper;\r
                prvSetMACAddress();\r
        }\r
        portEXIT_CRITICAL();\r
 
 #include "Semphr.h"\r
 #include "Task.h"\r
 \r
-void vEMAC_ISR( void ) __attribute__((naked));\r
+/* The interrupt entry point. */\r
+void vEMAC_ISR_Wrapper( void ) __attribute__((naked));\r
+\r
+/* The function that actually performs the interrupt processing.  This must be \r
+separate to the wrapper to ensure the correct stack frame is set up. */\r
+void vEMAC_ISR_Handler( void );\r
 \r
 extern xSemaphoreHandle xEMACSemaphore;\r
 \r
-void vEMAC_ISR( void )\r
+void vEMAC_ISR_Handler( void )\r
 {\r
-    portENTER_SWITCHING_ISR();\r
-\r
-\r
-       /* Variable must be static. */\r
-    static portBASE_TYPE xSwitchRequired;\r
-\r
-       /* As the variable is static it must be manually initialised here. */\r
-       xSwitchRequired = pdFALSE;\r
-\r
     /* Clear the interrupt. */\r
     IntClear = 0xffff;\r
     VICVectAddr = 0;\r
     /* Ensure the uIP task is not blocked as data has arrived. */\r
     if( xSemaphoreGiveFromISR( xEMACSemaphore, pdFALSE ) )\r
     {\r
-        xSwitchRequired = pdTRUE;\r
+               /* If the uIP task was unblocked then calling "Yield from ISR" here\r
+               will ensure the interrupt returns directly to the uIP task, if it\r
+               is the highest priority read task. */\r
+        portYIELD_FROM_ISR();\r
     }\r
+}\r
+/*-----------------------------------------------------------*/\r
 \r
-    /* Switch to the uIP task. */\r
-    portEXIT_SWITCHING_ISR( xSwitchRequired );\r
+void vEMAC_ISR_Wrapper( void )\r
+{\r
+       /* Save the context of the interrupted task. */\r
+       portSAVE_CONTEXT();\r
+\r
+       /* Call the handler function.  This must be separate from the wrapper\r
+       function to ensure the correct stack frame is set up. */\r
+       vEMAC_ISR_Handler();\r
+\r
+       /* Restore the context of whichever task is going to run next. */\r
+       portRESTORE_CONTEXT();\r
 }\r
 \r
 \r
+\r
+\r
 
 portBASE_TYPE i;\r
 uip_ipaddr_t xIPAddr;\r
 struct timer periodic_timer, arp_timer;\r
-extern void ( vEMAC_ISR )( void );\r
+extern void ( vEMAC_ISR_Wrapper )( void );\r
 \r
        /* Create the semaphore used by the ISR to wake this task. */\r
        vSemaphoreCreateBinary( xEMACSemaphore );\r
        {\r
         IntEnable = INT_RX_DONE;\r
         VICIntEnable |= 0x00200000;\r
-        VICVectAddr21 = ( portLONG ) vEMAC_ISR;\r
+        VICVectAddr21 = ( portLONG ) vEMAC_ISR_Wrapper;\r
                prvSetMACAddress();\r
        }\r
        portEXIT_CRITICAL();\r
 
        /* Install the ISR into the VIC - but don't enable it yet! */\r
        portENTER_CRITICAL();\r
        {\r
-               extern void ( vEINT0_ISR )( void );\r
+               extern void ( vEINT0_ISR_Wrapper )( void );\r
 \r
                VICIntSelect &= ~( tcpEINT0_VIC_CHANNEL_BIT );\r
-               VICVectAddr3 = ( portLONG ) vEINT0_ISR;\r
+               VICVectAddr3 = ( portLONG ) vEINT0_ISR_Wrapper;\r
 \r
                VICVectCntl3 = tcpEINT0_VIC_CHANNEL | tcpEINT0_VIC_ENABLE;\r
        }\r
 
 #define tcpEINT0_VIC_CHANNEL_BIT       ( ( unsigned portLONG ) 0x4000 )\r
 \r
 /* EINT0 interrupt handler.  This processes interrupts from the WIZnet device. */\r
-void vEINT0_ISR( void ) __attribute__((naked));\r
+void vEINT0_ISR_Wrapper( void ) __attribute__((naked));\r
+\r
+/* The handler that goes with the EINT0 wrapper. */\r
+void vEINT0_ISR_Handler( void );\r
 \r
 /* Variable is required for its address, but does not otherwise get used. */\r
 static portLONG lDummyVariable;\r
  * the TCP task.  This wakes the task so the interrupt can be processed.  The\r
  * source of the interrupt has to be ascertained by the TCP task as this \r
  * requires an I2C transaction which cannot be performed from this ISR.\r
+ * Note this code predates the introduction of semaphores, a semaphore should\r
+ * be used in place of the empty queue message.\r
  */\r
-void vEINT0_ISR( void )\r
+void vEINT0_ISR_Handler( void )\r
 {\r
-       portENTER_SWITCHING_ISR();\r
-\r
-       extern xQueueHandle xTCPISRQueue;\r
-\r
-       /* Must be declared static. */\r
-       static portBASE_TYPE xTaskWoken;\r
-\r
-       /* As the variable is static it must be manually initialised. */\r
-       xTaskWoken = pdFALSE;\r
+extern xQueueHandle xTCPISRQueue;\r
+portBASE_TYPE xTaskWoken = pdFALSE;\r
 \r
        /* Just wake the TCP task so it knows an ISR has occurred. */\r
-       xQueueSendFromISR( xTCPISRQueue, ( void * ) &lDummyVariable, xTaskWoken );      \r
+       xTaskWoken = xQueueSendFromISR( xTCPISRQueue, ( void * ) &lDummyVariable, xTaskWoken ); \r
 \r
        /* We cannot carry on processing interrupts until the TCP task has \r
        processed this one - so for now interrupts are disabled.  The TCP task will\r
        /* Clear the interrupt bit. */  \r
        VICVectAddr = tcpCLEAR_VIC_INTERRUPT;\r
 \r
-       /* Switch to the TCP task immediately so the cause of the interrupt can\r
-       be ascertained.  It is the responsibility of the TCP task to clear the\r
-       interrupts. */\r
-       portEXIT_SWITCHING_ISR( ( xTaskWoken ) );\r
+       if( xTaskWoken )\r
+       {\r
+               portYIELD_FROM_ISR();\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vEINT0_ISR_Wrapper( void )\r
+{\r
+       /* Save the context of the interrupted task. */\r
+       portSAVE_CONTEXT();\r
+\r
+       /* The handler must be a separate function from the wrapper to\r
+       ensure the correct stack frame is set up. */\r
+       vEINT0_ISR_Handler();\r
+\r
+       /* Restore the context of whichever task is going to run next. */\r
+       portRESTORE_CONTEXT();\r
 }\r
 \r
 \r
 
 \r
 void i2cInit( void )\r
 {\r
-extern void ( vI2C_ISR )( void );\r
+extern void ( vI2C_ISR_Wrapper )( void );\r
 \r
        /* Create the queue used to send messages to the ISR. */\r
        vI2CISRCreateQueues( i2cQUEUE_LENGTH, &xMessagesForTx, &pulBusFree );\r
                /* Setup the VIC for the i2c interrupt. */\r
                VICIntSelect &= ~( i2cI2C_VIC_CHANNEL_BIT );\r
                VICIntEnable |= i2cI2C_VIC_CHANNEL_BIT;\r
-               VICVectAddr2 = ( portLONG ) vI2C_ISR;\r
+               VICVectAddr2 = ( portLONG ) vI2C_ISR_Wrapper;\r
 \r
                VICVectCntl2 = i2cI2C_VIC_CHANNEL | i2cI2C_VIC_ENABLE;\r
        }\r
 
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-void vI2C_ISR( void ) __attribute__ (( naked ));\r
-void vI2C_ISR( void )\r
-{\r
-       portENTER_SWITCHING_ISR();\r
+/* The ISR entry point. */\r
+void vI2C_ISR_Wrapper( void ) __attribute__ (( naked ));\r
 \r
-       /* Variables must be static. */\r
+/* The ISR function to perform the actual work.  This must be a separate\r
+function from the wrapper to ensure the correct stack frame is set up. */\r
+void vI2C_ISR_Handler( void );\r
 \r
-       /* Holds the current transmission state. */                                                     \r
-       static I2C_STATE eCurrentState = eSentStart;\r
-       static portLONG lMessageIndex = -i2cBUFFER_ADDRESS_BYTES; /* There are two address bytes to send prior to the data. */\r
-       static portBASE_TYPE xTaskWokenByTx;\r
-       static portLONG lBytesLeft;\r
+/*-----------------------------------------------------------*/\r
 \r
-       xTaskWokenByTx = pdFALSE;\r
+void vI2C_ISR_Wrapper( void )\r
+{\r
+       /* Save the context of the interrupted task. */\r
+       portSAVE_CONTEXT();\r
 \r
+       /* Call the handler to perform the actual work.  This must be a\r
+       separate function to ensure the correct stack frame is set up. */\r
+       vI2C_ISR_Handler();\r
+\r
+       /* Restore the context of whichever task is going to run next. */\r
+       portRESTORE_CONTEXT();\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vI2C_ISR_Handler( void )\r
+{\r
+/* Holds the current transmission state. */                                                    \r
+static I2C_STATE eCurrentState = eSentStart;\r
+static portLONG lMessageIndex = -i2cBUFFER_ADDRESS_BYTES; /* There are two address bytes to send prior to the data. */\r
+portBASE_TYPE xTaskWokenByTx = pdFALSE;\r
+portLONG lBytesLeft;\r
 \r
        /* The action taken for this interrupt depends on our current state. */\r
        switch( eCurrentState )\r
        I2C_I2CONCLR = i2cSI_BIT;\r
        VICVectAddr = i2cCLEAR_VIC_INTERRUPT;\r
 \r
-       portEXIT_SWITCHING_ISR( ( xTaskWokenByTx ) );\r
+       if( xTaskWokenByTx )\r
+       {\r
+               portYIELD_FROM_ISR();\r
+       }\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
 
 /* See the header file for descriptions of public functions. */\r
 \r
 /*\r
- * Prototype for the EMAC interrupt function - called by the asm wrapper.\r
+ * Prototype for the EMAC interrupt function.\r
  */\r
-void vEMACISR( void ) __attribute__ ((naked));\r
+void vEMACISR_Wrapper( void ) __attribute__ ((naked));\r
 \r
 /*\r
  * Initialise both the Tx and Rx descriptors used by the EMAC.\r
                        AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RCOMP | AT91C_EMAC_TCOMP;\r
 \r
                        /* Enable the interrupts in the AIC. */\r
-                       AT91F_AIC_ConfigureIt( AT91C_ID_EMAC, emacINTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, ( void (*)( void ) ) vEMACISR );\r
+                       AT91F_AIC_ConfigureIt( AT91C_ID_EMAC, emacINTERRUPT_LEVEL, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, ( void (*)( void ) ) vEMACISR_Wrapper );\r
             AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_EMAC;\r
                }\r
                portEXIT_CRITICAL();\r
 
        ***************************************************************************\r
 */\r
 \r
-/* \r
-Changes from V3.2.4\r
-\r
-       + Also read the EMAC_RSR register in the EMAC ISR as a work around the \r
-         the EMAC bug that can reset the RX bit in EMAC_ISR register before the\r
-         bit has been read.\r
-\r
-Changes from V4.0.1\r
-\r
-       + Only check the interrupt status register to see if an EMAC Tx interrupt\r
-         has occurred.  Previously the TSR register was also inspected.\r
-*/\r
 \r
 #include "FreeRTOS.h"\r
 #include "task.h"\r
 task. */\r
 static xSemaphoreHandle xSemaphore = NULL;\r
 \r
-void vEMACISR( void ) __attribute__((naked));\r
+/* The interrupt entry point is naked so we can control the context saving. */\r
+void vEMACISR_Wrapper( void ) __attribute__((naked));\r
+\r
+/* The interrupt handler function must be separate from the entry function\r
+to ensure the correct stack frame is set up. */\r
+void vEMACISR_Handler( void );\r
 \r
 /*-----------------------------------------------------------*/\r
 /*\r
  * The EMAC ISR.  Handles both Tx and Rx complete interrupts.\r
  */\r
-void vEMACISR( void )\r
+void vEMACISR_Handler( void )\r
 {\r
-       /* This ISR can cause a context switch, so the first statement must be a\r
-       call to the portENTER_SWITCHING_ISR() macro.  This must be BEFORE any\r
-       variable declarations. */\r
-       portENTER_SWITCHING_ISR();\r
-\r
-       /* Variable definitions can be made now.   These must be static. */\r
-       static volatile unsigned portLONG ulIntStatus, ulEventStatus;\r
-       static portBASE_TYPE xSwitchRequired;\r
-    extern void vClearEMACTxBuffer( void );\r
-\r
-       /* As the variable is static it must be initialised manually here. */\r
-       xSwitchRequired = pdFALSE;\r
+volatile unsigned portLONG ulIntStatus, ulEventStatus;\r
+portBASE_TYPE xSwitchRequired = pdFALSE;\r
+extern void vClearEMACTxBuffer( void );\r
 \r
        /* Find the cause of the interrupt. */\r
        ulIntStatus = AT91C_BASE_EMAC->EMAC_ISR;\r
        AT91C_BASE_AIC->AIC_EOICR = 0;\r
 \r
        /* If a task was woken by either a frame being received then we may need to \r
-       switch to another task. */\r
-       portEXIT_SWITCHING_ISR( xSwitchRequired );\r
+       switch to another task.  If the unblocked task was of higher priority then\r
+       the interrupted task it will then execute immediately that the ISR\r
+       completes. */\r
+       if( xSwitchRequired )\r
+       {\r
+               portYIELD_FROM_ISR();\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void  vEMACISR_Wrapper( void )\r
+{\r
+       /* Save the context of the interrupted task. */\r
+       portSAVE_CONTEXT();\r
+\r
+       /* Call the handler to do the work.  This must be a separate\r
+       function to ensure the stack frame is set up correctly. */\r
+       vEMACISR_Handler();\r
+\r
+       /* Restore the context of whichever task will execute next. */\r
+       portRESTORE_CONTEXT();\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
 
 \r
 static void vInitUSBInterface( void )\r
 {\r
-extern void ( vUSB_ISR )( void );\r
+extern void ( vUSB_ISR_Wrapper )( void );\r
 \r
        /* Create the queue used to communicate between the USB ISR and task. */\r
        xUSBInterruptQueue = xQueueCreate( usbQUEUE_LENGTH + 1, sizeof( xISRStatus * ) );\r
 \r
        /* Enable the USB interrupts - other interrupts get enabled as the \r
        enumeration process progresses. */\r
-       AT91F_AIC_ConfigureIt( AT91C_ID_UDP, usbINTERRUPT_PRIORITY, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, ( void (*)( void ) ) vUSB_ISR );\r
+       AT91F_AIC_ConfigureIt( AT91C_ID_UDP, usbINTERRUPT_PRIORITY, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, ( void (*)( void ) ) vUSB_ISR_Wrapper );\r
        AT91C_BASE_AIC->AIC_IECR = 0x1 << AT91C_ID_UDP;\r
 \r
 \r
 
 /*-----------------------------------------------------------*/\r
 \r
 /* The ISR can cause a context switch so is declared naked. */\r
-void vUSB_ISR( void ) __attribute__ ((naked));\r
+void vUSB_ISR_Wrapper( void ) __attribute__ ((naked));\r
 \r
+/* The function that actually performs the ISR work.  This must be separate\r
+from the wrapper function to ensure the correct stack frame gets set up. */\r
+void vUSB_ISR_Handler( void );\r
 /*-----------------------------------------------------------*/\r
 \r
-\r
-void vUSB_ISR( void )\r
+void vUSB_ISR_Handler( void )\r
 {\r
-       /* This ISR can cause a context switch.  Therefore a call to the \r
-       portENTER_SWITCHING_ISR() macro is made.  This must come BEFORE any \r
-       stack variable declarations. */\r
-       portENTER_SWITCHING_ISR();\r
-\r
-       /* Now variables can be declared.  These must be static. */\r
-       static portCHAR cTaskWokenByPost; \r
-       static volatile unsigned portLONG ulNextMessage = 0;\r
-       static xISRStatus *pxMessage;\r
-       static unsigned portLONG ulRxBytes;\r
-       static unsigned portCHAR ucFifoIndex;\r
-\r
-       /* As the variables are static they must be initialised manually here. */\r
-       cTaskWokenByPost = pdFALSE; \r
+portCHAR cTaskWokenByPost = pdFALSE;\r
+static volatile unsigned portLONG ulNextMessage = 0;\r
+xISRStatus *pxMessage;\r
+unsigned portLONG ulRxBytes;\r
+unsigned portCHAR ucFifoIndex;\r
 \r
     /* Use the next message from the array. */\r
        pxMessage = &( xISRMessages[ ( ulNextMessage & usbQUEUE_LENGTH ) ] );\r
        AT91C_BASE_AIC->AIC_EOICR = 0;\r
 \r
        /* Do a task switch if needed */\r
-       portEXIT_SWITCHING_ISR( cTaskWokenByPost )\r
+       if( cTaskWokenByPost )\r
+       {\r
+               /* This call will ensure that the unblocked task will be executed\r
+               immediately upon completion of the ISR if it has a priority higher\r
+               than the interrupted task. */\r
+               portYIELD_FROM_ISR();\r
+       }\r
+}\r
+/*-----------------------------------------------------------*/\r
+\r
+void vUSB_ISR_Wrapper( void )\r
+{\r
+       /* Save the context of the interrupted task. */\r
+       portSAVE_CONTEXT();\r
+\r
+       /* Call the handler to do the work.  This must be a separate\r
+       function to ensure the stack frame is set up correctly. */\r
+       vUSB_ISR_Handler();\r
+\r
+       /* Restore the context of whichever task will execute next. */\r
+       portRESTORE_CONTEXT();\r
 }\r
 \r
+\r
 
 \r
        Changes from V4.5.0\r
 \r
-       + The macro portENTER_SWITCHING_ISR() no longer attempts to use the frame\r
-         pointer.  Variables declared within ISRs must now be declared static.\r
+       + Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros\r
+         and replaced them with portYIELD_FROM_ISR() macro.  Application code \r
+         should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()\r
+         macros as per the V4.5.1 demo code.\r
 */\r
 \r
 #ifndef PORTMACRO_H\r
 #define portSTACK_GROWTH                       ( -1 )\r
 #define portTICK_RATE_MS                       ( ( portTickType ) 1000 / configTICK_RATE_HZ )          \r
 #define portBYTE_ALIGNMENT                     4\r
-#define portYIELD()                                    asm volatile ( "SWI" ); \r
-#define portNOP()                                      asm volatile ( "NOP" );\r
+#define portYIELD()                                    asm volatile ( "SWI" )\r
+#define portNOP()                                      asm volatile ( "NOP" )\r
 \r
 /*\r
  * These define the timer to use for generating the tick interrupt.\r
        ( void ) pxCurrentTCB;                                                                                          \\r
 }\r
 \r
-/*-----------------------------------------------------------\r
- * ISR entry and exit macros.  These are only required if a task switch\r
- * is required from the ISR.\r
- *----------------------------------------------------------*/\r
-\r
-#define portENTER_SWITCHING_ISR()                                                                              \\r
-       /* Save the context of the interrupted task. */                                         \\r
-       portSAVE_CONTEXT();                                                                                                     \\r
-       {\r
-\r
-#define portEXIT_SWITCHING_ISR( SwitchRequired )                                               \\r
-               /* If a switch is required then we just need to call */                 \\r
-               /* vTaskSwitchContext() as the context has already been */              \\r
-               /* saved. */                                                                                                    \\r
-               if( SwitchRequired )                                                                                    \\r
-               {                                                                                                                               \\r
-                       vTaskSwitchContext();                                                                           \\r
-               }                                                                                                                               \\r
-       }                                                                                                                                       \\r
-       /* Restore the context of which ever task is now the highest */         \\r
-       /* priority that is ready to run. */                                                            \\r
-       portRESTORE_CONTEXT();\r
-/*-----------------------------------------------------------*/        \r
+#define portYIELD_FROM_ISR() vTaskSwitchContext()\r
 \r
 /* Critical section handling. */\r
 \r
 
        + The assembler statements are now included in a single asm block rather\r
          than each line having its own asm block.\r
 \r
-       + The macro portENTER_SWITCHING_ISR() no longer attempts to use the frame\r
-         pointer.  Variables declared within ISRs must now be declared static.\r
+       Changes from V4.5.0\r
+\r
+       + Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros\r
+         and replaced them with portYIELD_FROM_ISR() macro.  Application code \r
+         should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()\r
+         macros as per the V4.5.1 demo code.\r
 */\r
 \r
 #ifndef PORTMACRO_H\r
 }\r
 \r
 \r
-/*-----------------------------------------------------------\r
- * ISR entry and exit macros.  These are only required if a task switch\r
- * is required from the ISR.\r
- *----------------------------------------------------------*/\r
-\r
-\r
-#define portENTER_SWITCHING_ISR()                                                                              \\r
-       /* Save the context of the interrupted task. */                                         \\r
-       portSAVE_CONTEXT();                                                                                                     \\r
-       {\r
-\r
-#define portEXIT_SWITCHING_ISR( SwitchRequired )                                               \\r
-               /* If a switch is required then we just need to call */                 \\r
-               /* vTaskSwitchContext() as the context has already been */              \\r
-               /* saved. */                                                                                                    \\r
-               if( SwitchRequired )                                                                                    \\r
-               {                                                                                                                               \\r
-                       vTaskSwitchContext();                                                                           \\r
-               }                                                                                                                               \\r
-       }                                                                                                                                       \\r
-       /* Restore the context of which ever task is now the highest */         \\r
-       /* priority that is ready to run. */                                                            \\r
-       portRESTORE_CONTEXT();\r
-\r
-#define portYIELD()                                    asm volatile ( "SWI" ); \r
+#define portYIELD_FROM_ISR()           vTaskSwitchContext()\r
+#define portYIELD()                                    asm volatile ( "SWI" )\r
 /*-----------------------------------------------------------*/\r
 \r
 \r
 
        + The assembler statements are now included in a single asm block rather\r
          than each line having its own asm block.\r
 \r
-       + The macro portENTER_SWITCHING_ISR() no longer attempts to use the frame\r
-         pointer.  Variables declared within ISRs must now be declared static.\r
+       Changes from V4.5.0\r
+\r
+       + Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros\r
+         and replaced them with portYIELD_FROM_ISR() macro.  Application code \r
+         should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()\r
+         macros as per the V4.5.1 demo code.\r
 */\r
 \r
 #ifndef PORTMACRO_H\r
 }\r
 \r
 \r
-/*-----------------------------------------------------------\r
- * ISR entry and exit macros.  These are only required if a task switch\r
- * is required from the ISR.\r
- *----------------------------------------------------------*/\r
-\r
-\r
-#define portENTER_SWITCHING_ISR()                                                                              \\r
-       /* Save the context of the interrupted task. */                                         \\r
-       portSAVE_CONTEXT();                                                                                                     \\r
-       {\r
-\r
-#define portEXIT_SWITCHING_ISR( SwitchRequired )                                               \\r
-               /* If a switch is required then we just need to call */                 \\r
-               /* vTaskSwitchContext() as the context has already been */              \\r
-               /* saved. */                                                                                                    \\r
-               if( SwitchRequired )                                                                                    \\r
-               {                                                                                                                               \\r
-                       vTaskSwitchContext();                                                                           \\r
-               }                                                                                                                               \\r
-       }                                                                                                                                       \\r
-       /* Restore the context of which ever task is now the highest */         \\r
-       /* priority that is ready to run. */                                                            \\r
-       portRESTORE_CONTEXT();\r
-\r
-#define portYIELD()                                    asm volatile ( "SWI" ); \r
+#define portYIELD_FROM_ISR()           vTaskSwitchContext()\r
+#define portYIELD()                                    asm volatile ( "SWI" )\r
 /*-----------------------------------------------------------*/\r
 \r
 \r
 
        + The assembler statements are now included in a single asm block rather\r
          than each line having its own asm block.\r
 \r
-       + The macro portENTER_SWITCHING_ISR() no longer attempts to use the frame\r
-         pointer.  Variables declared within ISRs must now be declared static.\r
+       Changes from V4.5.0\r
+\r
+       + Removed the portENTER_SWITCHING_ISR() and portEXIT_SWITCHING_ISR() macros\r
+         and replaced them with portYIELD_FROM_ISR() macro.  Application code \r
+         should now make use of the portSAVE_CONTEXT() and portRESTORE_CONTEXT()\r
+         macros as per the V4.5.1 demo code.\r
 */\r
 \r
 #ifndef PORTMACRO_H\r
 }\r
 \r
 \r
-/*-----------------------------------------------------------\r
- * ISR entry and exit macros.  These are only required if a task switch\r
- * is required from the ISR.\r
- *----------------------------------------------------------*/\r
-\r
-\r
-#define portENTER_SWITCHING_ISR()                                                                              \\r
-       /* Save the context of the interrupted task. */                                         \\r
-       portSAVE_CONTEXT();                                                                                                     \\r
-       {\r
-\r
-#define portEXIT_SWITCHING_ISR( SwitchRequired )                                               \\r
-               /* If a switch is required then we just need to call */                 \\r
-               /* vTaskSwitchContext() as the context has already been */              \\r
-               /* saved. */                                                                                                    \\r
-               if( SwitchRequired )                                                                                    \\r
-               {                                                                                                                               \\r
-                       vTaskSwitchContext();                                                                           \\r
-               }                                                                                                                               \\r
-       }                                                                                                                                       \\r
-       /* Restore the context of which ever task is now the highest */         \\r
-       /* priority that is ready to run. */                                                            \\r
-       portRESTORE_CONTEXT();\r
-\r
-#define portYIELD()                                    asm volatile ( "SWI" ); \r
+#define portYIELD_FROM_ISR()           vTaskSwitchContext()\r
+#define portYIELD()                                    asm volatile ( "SWI" )\r
 /*-----------------------------------------------------------*/\r
 \r
 \r