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