Probs w/ xSemaphoreGiveFromISR & on …
I have an ISR that communicates with a task via a semaphore. If I use xSemaphoreGive in the ISR (against the documentation), everything works fine. However, if I use xSemaphoreGiveFromISR and (conditionally) call vPortYieldFromISR as I should, the scheduler becomes confused after the first interrupt and never finds a task to schedule after the waiting task blocks, even though there’s another task that’s always ready to run.
The scenario is as follows:
There are two tasks – a low-priority task that does something to cause an interrupt, and a higher priority task that’s waiting on a semaphore. The ISR simply posts to the semaphore. In the case were I use the correct “FromISR” functions from the ISR, the waiting task wakes up, performs it’s function (nothing) , and goes back to waiting for the semaphore. The low-priority task never gets scheduled again. However, if I use the INCORRECT function in the ISR, everything works smoothly, and the low-priority task gets scheduled after the waiting task re-waits.
I’m using the GCC/ARM_CM3 port on a ARM Cortex-M3 target. I’m actually pre-silicon and am running on RTL/VCS simulations.
Any help would be greatly appreciated.
Probs w/ xSemaphoreGiveFromISR & on …
I found the previous post where you using binary semaphores fixed the problem. I tried a binary semaphore with no success. Further, I need counting semaphores in this instance.
Probs w/ xSemaphoreGiveFromISR & on …
Which CM3 will you use when it is ready.
Are you sure your simulator is working correctly? Many don’t when simulating an RTOS.
Probs w/ xSemaphoreGiveFromISR & on …
Also, can you post the code of the two tasks, which sound like they are only a few lines of code. Use the
tags to keep the formatting.
Probs w/ xSemaphoreGiveFromISR & on …
Per your question about the simulator, I have never had a problem with the simulator before. The simulator is VCS and it’s simulating the M3 processor from the RTL, so it should be cycle-accurate. And I’ve been simulating other things under freeRTOS and other RTOS’s with this simulator with no problems.
Per your question about which CM3 I’ll be using, I’m writing code for a new chip incorporating a Cortex-M3.
The task and the ISR are shown below, somewhat simplified.
Thanks for your help with this.
Richard
/**
* GPIOHelpersTask is the task that performs most of the functionality for
* all GPIO interrupts. It spends most of its time waiting on a signal
* from the ISR that an interrupt has occurred. When it receives a signal
* (actually a "put" on its semaphore), it processes all GPIO interrupts
* that have occurred since the last signal.
*
* void GPIOHelpersTask(void)
*
*
**/
void GPIOHelpersTask(void)
{
uint32_t retCode;
uint32_t i;
uint8_t lclIntPending[HW_MAX_GPIO];
/* init the gpio and the ISR-to-this-task counting semaphore*/
gpioHelpers_sysInit();
/* this is the main task loop; it runs off of a counting semaphore so it doesn't miss any semaphore posts */
while (pdTRUE)
{
/* wait on semaphore */
retCode = xSemaphoreTake(((posixSemaphore *)gpioHelpersSema)->handle,0xffffffff);
if (retCode < 0)
{
/***TODO***log an error***/
while (1) {};
}
/* process "pending" interrupts */
/* first pick up all pending interrupts and save them locally */
/* to avoid multiple interrupt enable/disables */
taskENTER_CRITICAL();
for (i = 0 ; i < HW_MAX_GPIO ; i++)
{
lclIntPending[i] = gpioHelper.gpioPendInt[i];
gpioHelper.gpioPendInt[i] = 0;
}
taskEXIT_CRITICAL();
/* process each entry in table (comparing to pending mask for that gpio) ***/
/* note: races shouldn't be an issue here, as count is never decrementing */
/* and all other change, we'll either get before or after, but not */
/* inconsistent state. */
for (i = 0 ; i < gpioHelper.gpioHandleCount ; i++)
{
/* check each entry against the corresponding pending interrupt bits */
if ((lclIntPending[gpioHelper.configTable[i].gpioNum] &
gpioHelper.configTable[i].mask) &&
gpioHelper.configTable[i].IOType > GPIO_INT_TYPES)
{
/* found one, now process it (call call-back) */
((gpio_callback_t)gpioHelper.configTable[i].notifier)
(
GPIO_DATA_R(gpioHelper.configTable[i].gpioNum,
gpioHelper.configTable[i].basePin,
BIT_MASK(gpioHelper.configTable[i].numPins))
);
}
} /* if (lclIntPending[gpioHelper.configTable[i].gpioNum] & ... */
}
} /* while (pdTRUE) */
/*** should never get here ***/
}
/**
* GPIOISR is the interrupt service routine for the GPIO blocks. It fields
* all GPIO interrupts and signals the background function to determine what
* to do with the interrupt.
*
* void GPIOISR(void)
*
*
**/
void GPIOISR(void)
{
uint32_t retCode;
uint8_t IRQNum;
uint8_t gpioNum;
uint8_t intsPending;
portBASE_TYPE preEmptionRequired = pdFALSE;
/* determine which GPIO is firing */
IRQNum = get_irq_in_process();
/* convert IRQ to gpio # and check validity */
gpioNum = HW_IRQ2GPIO(IRQNum);
if (gpioNum > HW_MAX_GPIO)
{
/*****BAD ERROR -- should never get here. IGNORE THIS *****/
/***** or, during debug, hang ***/
while (pdTRUE){};
return;
}
/* pick up its pending interrupts and "or" it into the saved */
/* pending interrupts then clear the interrupts in GPIO. */
/* NOTE: "pend" in NVIC is automatically cleared when an */
/* the isr is entered, so it doesn't need to be cleared, and */
/* in fact, shouldn't be cleared, as it means another intrupt*/
/* has arrived after the current one was active. Also, the */
/* "active" bit is read-only and automagically set & cleared */
/* by the NVIC. */
intsPending = GPIO_MIS_R(gpioNum);
gpioHelper.gpioPendInt[gpioNum] |= intsPending;
GPIO_INTCLR_W(gpioNum,intsPending);
/* now notify the gpio helper task that it's got work to do */
given = xSemaphoreGiveFromISR(sem->handle,&preEmptionRequired);
/****handle pre-emption****/
if (preEmptionRequired != pdFALSE)
{
vPortYieldFromISR();
}
}
Probs w/ xSemaphoreGiveFromISR & on …
Is anyone successfully using xSemaphoreGiveFromISR/vPortYieldFromISR on a counting semaphore on a CORTEX_M3?
Probs w/ xSemaphoreGiveFromISR & on …
Problem solved. This was my problem and NOT a freeRTOS problem.
I had configSYSCALL_INTERRUPT_PRIORITY set at lower priority (higher priority # on ARM CORTEX M3) than my GPIO interrupt was running at. When I fixed this, the problem went away.
Richard