mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-19 21:11:57 -04:00
Changed the way the ARM7/9 GCC ports enter interrupts that can cause a context switch.
This commit is contained in:
parent
c54ec1c639
commit
ada7fa862d
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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();
|
||||
|
||||
/* Now we can declare the local variables. These must be static. */
|
||||
static signed portCHAR cChar;
|
||||
static portBASE_TYPE xTaskWokenByTx, xTaskWokenByRx;
|
||||
/* Call the handler. This must be a separate function from the wrapper
|
||||
to ensure the correct stack frame is set up. */
|
||||
vUART_ISR_Handler();
|
||||
|
||||
/* As these variables are static they must be initialised manually here. */
|
||||
xTaskWokenByTx = pdFALSE;
|
||||
xTaskWokenByRx = pdFALSE;
|
||||
/* Restore the context of whichever task is going to run next. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
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 ) );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
||||
/* The handler that does the actual work. */
|
||||
void vEMAC_ISR_Handler( void );
|
||||
|
||||
extern xSemaphoreHandle xEMACSemaphore;
|
||||
|
||||
void vEMAC_ISR( void )
|
||||
|
||||
void vEMAC_ISR_Handler( void )
|
||||
{
|
||||
portENTER_SWITCHING_ISR();
|
||||
|
||||
static portBASE_TYPE xSwitchRequired;
|
||||
|
||||
xSwitchRequired = pdFALSE;
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -300,10 +300,10 @@ void vTCPHardReset( void )
|
|||
/* Install the ISR into the VIC - but don't enable it yet! */
|
||||
portENTER_CRITICAL();
|
||||
{
|
||||
extern void ( vEINT0_ISR )( void );
|
||||
extern void ( vEINT0_ISR_Wrapper )( void );
|
||||
|
||||
VICIntSelect &= ~( tcpEINT0_VIC_CHANNEL_BIT );
|
||||
VICVectAddr3 = ( portLONG ) vEINT0_ISR;
|
||||
VICVectAddr3 = ( portLONG ) vEINT0_ISR_Wrapper;
|
||||
|
||||
VICVectCntl3 = tcpEINT0_VIC_CHANNEL | tcpEINT0_VIC_ENABLE;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,10 @@
|
|||
#define tcpEINT0_VIC_CHANNEL_BIT ( ( unsigned portLONG ) 0x4000 )
|
||||
|
||||
/* EINT0 interrupt handler. This processes interrupts from the WIZnet device. */
|
||||
void vEINT0_ISR( void ) __attribute__((naked));
|
||||
void vEINT0_ISR_Wrapper( void ) __attribute__((naked));
|
||||
|
||||
/* The handler that goes with the EINT0 wrapper. */
|
||||
void vEINT0_ISR_Handler( void );
|
||||
|
||||
/* Variable is required for its address, but does not otherwise get used. */
|
||||
static portLONG lDummyVariable;
|
||||
|
@ -53,21 +56,16 @@ static portLONG lDummyVariable;
|
|||
* the TCP task. This wakes the task so the interrupt can be processed. The
|
||||
* source of the interrupt has to be ascertained by the TCP task as this
|
||||
* requires an I2C transaction which cannot be performed from this ISR.
|
||||
* Note this code predates the introduction of semaphores, a semaphore should
|
||||
* be used in place of the empty queue message.
|
||||
*/
|
||||
void vEINT0_ISR( void )
|
||||
void vEINT0_ISR_Handler( void )
|
||||
{
|
||||
portENTER_SWITCHING_ISR();
|
||||
|
||||
extern xQueueHandle xTCPISRQueue;
|
||||
|
||||
/* Must be declared static. */
|
||||
static portBASE_TYPE xTaskWoken;
|
||||
|
||||
/* As the variable is static it must be manually initialised. */
|
||||
xTaskWoken = pdFALSE;
|
||||
extern xQueueHandle xTCPISRQueue;
|
||||
portBASE_TYPE xTaskWoken = pdFALSE;
|
||||
|
||||
/* Just wake the TCP task so it knows an ISR has occurred. */
|
||||
xQueueSendFromISR( xTCPISRQueue, ( void * ) &lDummyVariable, xTaskWoken );
|
||||
xTaskWoken = xQueueSendFromISR( xTCPISRQueue, ( void * ) &lDummyVariable, xTaskWoken );
|
||||
|
||||
/* We cannot carry on processing interrupts until the TCP task has
|
||||
processed this one - so for now interrupts are disabled. The TCP task will
|
||||
|
@ -77,10 +75,24 @@ void vEINT0_ISR( void )
|
|||
/* Clear the interrupt bit. */
|
||||
VICVectAddr = tcpCLEAR_VIC_INTERRUPT;
|
||||
|
||||
/* Switch to the TCP task immediately so the cause of the interrupt can
|
||||
be ascertained. It is the responsibility of the TCP task to clear the
|
||||
interrupts. */
|
||||
portEXIT_SWITCHING_ISR( ( xTaskWoken ) );
|
||||
if( xTaskWoken )
|
||||
{
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vEINT0_ISR_Wrapper( void )
|
||||
{
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* The handler must be a separate function from the wrapper to
|
||||
ensure the correct stack frame is set up. */
|
||||
vEINT0_ISR_Handler();
|
||||
|
||||
/* Restore the context of whichever task is going to run next. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ signed portBASE_TYPE xReturn;
|
|||
|
||||
void i2cInit( void )
|
||||
{
|
||||
extern void ( vI2C_ISR )( void );
|
||||
extern void ( vI2C_ISR_Wrapper )( void );
|
||||
|
||||
/* Create the queue used to send messages to the ISR. */
|
||||
vI2CISRCreateQueues( i2cQUEUE_LENGTH, &xMessagesForTx, &pulBusFree );
|
||||
|
@ -203,7 +203,7 @@ extern void ( vI2C_ISR )( void );
|
|||
/* Setup the VIC for the i2c interrupt. */
|
||||
VICIntSelect &= ~( i2cI2C_VIC_CHANNEL_BIT );
|
||||
VICIntEnable |= i2cI2C_VIC_CHANNEL_BIT;
|
||||
VICVectAddr2 = ( portLONG ) vI2C_ISR;
|
||||
VICVectAddr2 = ( portLONG ) vI2C_ISR_Wrapper;
|
||||
|
||||
VICVectCntl2 = i2cI2C_VIC_CHANNEL | i2cI2C_VIC_ENABLE;
|
||||
}
|
||||
|
|
|
@ -119,21 +119,36 @@ void vI2CISRCreateQueues( unsigned portBASE_TYPE uxQueueLength, xQueueHandle *px
|
|||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vI2C_ISR( void ) __attribute__ (( naked ));
|
||||
void vI2C_ISR( void )
|
||||
/* The ISR entry point. */
|
||||
void vI2C_ISR_Wrapper( void ) __attribute__ (( naked ));
|
||||
|
||||
/* The ISR function to perform the actual work. This must be a separate
|
||||
function from the wrapper to ensure the correct stack frame is set up. */
|
||||
void vI2C_ISR_Handler( void );
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vI2C_ISR_Wrapper( void )
|
||||
{
|
||||
portENTER_SWITCHING_ISR();
|
||||
/* Save the context of the interrupted task. */
|
||||
portSAVE_CONTEXT();
|
||||
|
||||
/* Variables must be static. */
|
||||
/* Call the handler to perform the actual work. This must be a
|
||||
separate function to ensure the correct stack frame is set up. */
|
||||
vI2C_ISR_Handler();
|
||||
|
||||
/* Holds the current transmission state. */
|
||||
static I2C_STATE eCurrentState = eSentStart;
|
||||
static portLONG lMessageIndex = -i2cBUFFER_ADDRESS_BYTES; /* There are two address bytes to send prior to the data. */
|
||||
static portBASE_TYPE xTaskWokenByTx;
|
||||
static portLONG lBytesLeft;
|
||||
|
||||
xTaskWokenByTx = pdFALSE;
|
||||
/* Restore the context of whichever task is going to run next. */
|
||||
portRESTORE_CONTEXT();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vI2C_ISR_Handler( void )
|
||||
{
|
||||
/* Holds the current transmission state. */
|
||||
static I2C_STATE eCurrentState = eSentStart;
|
||||
static portLONG lMessageIndex = -i2cBUFFER_ADDRESS_BYTES; /* There are two address bytes to send prior to the data. */
|
||||
portBASE_TYPE xTaskWokenByTx = pdFALSE;
|
||||
portLONG lBytesLeft;
|
||||
|
||||
/* The action taken for this interrupt depends on our current state. */
|
||||
switch( eCurrentState )
|
||||
|
@ -342,7 +357,10 @@ void vI2C_ISR( void )
|
|||
I2C_I2CONCLR = i2cSI_BIT;
|
||||
VICVectAddr = i2cCLEAR_VIC_INTERRUPT;
|
||||
|
||||
portEXIT_SWITCHING_ISR( ( xTaskWokenByTx ) );
|
||||
if( xTaskWokenByTx )
|
||||
{
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
|
|
@ -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" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
|
|
@ -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" )
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue