Problem with Tickless Idle in cooperative mode on STM32

Hi, I have been trying to get the Tickless Idle mode to work on an STM32F1 controller. The FreeRTOS version is 8.2.1. For my particular application i have disabled preemption. So, the idle task yeilds manually. The problem is that when the systick interrupt occurs when in the idle task and after the taskYIELD() call and a task is moved from the delayed list to the running list, the portSUPPRESS_TICKS_AND_SLEEP( ); is still called from the idle task. This happens because* prvGetExpectedIdleTime()* only checks if there is another waiting task with idle priority. ~~~~ static TickTypet prvGetExpectedIdleTime( void ) { TickTypet xReturn;
    if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
    {
        xReturn = 0;
    }
    else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
    {
        /* There are other idle priority tasks in the ready state.  If
        time slicing is used then the very next tick interrupt must be
        processed. */
        xReturn = 0;
    }
    else
    {
        xReturn = xNextTaskUnblockTime - xTickCount;
    }

    return xReturn;
}
~~~~ So even if there is a task in the ready list, the controller is put to sleep, since it’s priority is higher than the idle task. Could this be because i have done something wrong in my code or is this a bug in the RTOS?

Problem with Tickless Idle in cooperative mode on STM32

I wouldn’t say it is a bug, it’s just that the tickless idle mode assumes it is using pre-emption. I think this was discussed on the forum somewhere already. I will look to see if there is an efficient way of supporting pre-emptive mode too, but as a minimum we can add a #error into the code if configUSETICKLESSIDLE is 1 and configUSE_PREEMPTION is 0 at the same time. I have not tried it, but it might be possible for you to have all your applications tasks running at priorities above the idle priority – then if the idle task does run you know there are no higher priority tasks. Regards.

Problem with Tickless Idle in cooperative mode on STM32

I have not done much more than compile this, and step through one path, with one configuration, but please consider the following and report back as to whether it allows you to use co-operative mode. The following replaces the existing prvGetExpectedIdleTime() function: ~~~~ static TickTypet prvGetExpectedIdleTime( void ) { TickTypet xReturn; UBaseType_t uxHigherPriorityReadyTasks = pdFALSE;
/* uxHigherPriorityReadyTasks takes care of the case where
configUSE_PREEMPTION is 0, so there may be tasks above the idle priority
task that are in the Ready state, even though the idle task is
running. */
#if( configUSE_PORT_OPTIMISED_TASK_SELECTION == 0 )
{
    if( uxTopReadyPriority > tskIDLE_PRIORITY )
    {
        uxHigherPriorityReadyTasks = pdTRUE;
    }
}
#else
{
const UBaseType_t uxLeastSignificantBit = ( UBaseType_t ) 0x01;

    /* When port optimised task selection is used the uxTopReadyPriority
    variable is used as a bit map.  If bits other than the least 
    significant bit are set then there are tasks that have a priority
    above the idle priority that are in the Ready state. */
    if( uxTopReadyPriority > uxLeastSignificantBit )
    {
        uxHigherPriorityReadyTasks = pdTRUE;
    }
}
#endif

if( pxCurrentTCB->uxPriority > tskIDLE_PRIORITY )
{
    xReturn = 0;
}
else if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > 1 )
{
    /* There are other idle priority tasks in the ready state.  If
    time slicing is used then the very next tick interrupt must be
    processed. */
    xReturn = 0;
}
else if( uxHigherPriorityReadyTasks != pdFALSE )
{
    /* There are tasks in the Ready state that have a priority above the
    idle priority.  This path can only be reached if 
    configUSE_PREEMPTION is 0. */
    xReturn = 0;
}
else
{
    xReturn = xNextTaskUnblockTime - xTickCount;
}

return xReturn;
} ~~~~