Complete the new comtest_strings.c file.

Somewhat optimise the calling of vTaskSwitchContext() from interrupts in the new MicroBlaze port to ensure it does not get called multiple times when more than one peripheral is called from the same interrupt.
This commit is contained in:
Richard Barry 2011-06-20 19:40:50 +00:00
parent a4de9fa8f6
commit 4108061316
6 changed files with 161 additions and 142 deletions

View file

@ -104,6 +104,13 @@ volatile unsigned portBASE_TYPE uxCriticalNesting = portINITIAL_NESTING_VALUE;
separate stack for interrupts. */
unsigned long *pulISRStack;
/* If an interrupt requests a context switch then ulTaskSwitchRequested will
get set to 1, which in turn will cause vTaskSwitchContext() to be called
prior to a task context getting restored on exit from the interrupt. This
mechanism is used as a single interrupt can cause multiple peripherals handlers
to get called, and vTaskSwitchContext() should not get called in each handler. */
volatile unsigned long ulTaskSwitchRequested = 0UL;
/* The instance of the interrupt controller used by this port. */
static XIntc xInterruptControllerInstance;
@ -276,45 +283,6 @@ extern void VPortYieldASM( void );
}
/*-----------------------------------------------------------*/
/*
* The task context has already been saved when this is called.
*
* This handler determines the interrupt source and calls the relevant
* peripheral handler.
*/
void vTaskISRHandler( void )
{
static unsigned long ulPending;
static XIntc_VectorTableEntry *pxTablePtr;
static XIntc_Config *pxConfig;
static unsigned long ulInterruptMask;
/* Which interrupts are pending? */
ulPending = XIntc_In32( ( XPAR_INTC_SINGLE_BASEADDR + XIN_IVR_OFFSET ) );
if( ulPending < XPAR_INTC_MAX_NUM_INTR_INPUTS )
{
ulInterruptMask = ( unsigned long ) 1 << ulPending;
/* Get the configuration data using the device ID */
pxConfig = &XIntc_ConfigTable[ ( unsigned long ) XPAR_INTC_SINGLE_DEVICE_ID ];
pxTablePtr = &( pxConfig->HandlerTable[ ulPending ] );
if( pxConfig->AckBeforeService & ( ulInterruptMask ) )
{
XIntc_AckIntr( pxConfig->BaseAddress, ulInterruptMask );
pxTablePtr->Handler( pxTablePtr->CallBackRef );
}
else
{
pxTablePtr->Handler( pxTablePtr->CallBackRef );
XIntc_AckIntr( pxConfig->BaseAddress, ulInterruptMask );
}
}
}
/*-----------------------------------------------------------*/
void vPortEnableInterrupt( unsigned char ucInterruptID )
{
XIntc_Enable( &xInterruptControllerInstance, ucInterruptID );
@ -357,7 +325,7 @@ portBASE_TYPE xReturn = XST_SUCCESS;
*/
void vTickISR( void *pvUnused )
{
extern void vApplicationClearTimerInterrupt();
extern void vApplicationClearTimerInterrupt( void );
/* Ensure the unused parameter does not generate a compiler warning. */
( void ) pvUnused;
@ -370,7 +338,8 @@ extern void vApplicationClearTimerInterrupt();
/* If we are using the preemptive scheduler then we also need to determine
if this tick should cause a context switch. */
#if configUSE_PREEMPTION == 1
vTaskSwitchContext();
/* Force vTaskSwitchContext() to be called as the interrupt exits. */
ulTaskSwitchRequested = 1;
#endif
}
/*-----------------------------------------------------------*/

View file

@ -108,6 +108,7 @@ back into the caller stack. */
.extern vTaskSwitchContext
.extern uxCriticalNesting
.extern pulISRStack
.extern ulTaskSwitchRequested
.global _interrupt_handler
.global VPortYieldASM
@ -282,6 +283,25 @@ _interrupt_handler:
bralid r15, XIntc_DeviceInterruptHandler
or r0, r0, r0
/* See if a new task should be selected to execute. */
lwi r18, r0, ulTaskSwitchRequested
or r18, r18, r0
/* If ulTaskSwitchRequested is already zero, then jump straight to
restoring the task that is already in the Running state. */
beqi r18, task_switch_not_requested
/* Set ulTaskSwitchRequested back to zero as a task switch is about to be
performed. */
swi r0, r0, ulTaskSwitchRequested
/* ulTaskSwitchRequested was not 0 when tested. Select the next task to
execute. */
bralid r15, vTaskSwitchContext
or r0, r0, r0
task_switch_not_requested:
/* Restore the context of the next task scheduled to execute. */
portRESTORE_CONTEXT

View file

@ -130,7 +130,8 @@ void vPortYield( void );
#define portYIELD() vPortYield()
void vTaskSwitchContext();
#define portYIELD_FROM_ISR( x ) if( x != pdFALSE ) vTaskSwitchContext() //_RB_ This needs re-implementing so it does not get called multiple times as multiple peripherals are servied in a single ISR. */
extern volatile unsigned long ulTaskSwitchRequested;
#define portYIELD_FROM_ISR( x ) if( x != pdFALSE ) ulTaskSwitchRequested = 1
/*-----------------------------------------------------------*/
/* Hardware specifics. */