FreeRTOSDemoRL78_RL78G13_Promo_Board_IAR Software Timer problem on RL78 G13 R5F100LEA

Hello, I am an electrical engineering student and i am currently implementing an application using FreeRTOS v8.2.2 I want to report a Bug that appears in my projects and the Demo FreeRTOSDemoRL78RL78G13PromoBoardIAR, when using the software timer functionality. Currently I use the YRDKRL78-G13 REV2.1 for testing FreeRTOS and other applications in combination with the IAR EW v1.2 for the RL78 series. ( If a portable layer exists for IAR EW v2.1 RL78, please notify me ) I noticed an error while testing the Demo application on my YRDKRL78-G13. I left the Demo project unchanged, just the LED used in the project changed to P63 which is LED 3 on my board. I set the Debugger to TK. The Demo seems to be working fine on the first impression, but if you leave the Demo running the LED will stop to toggle after some time approx. 1 minute. Debugging the project revealed that the software timer stops working after the first xTickCount overflow. I set a breakpoint into the TimerTask after the Overflow the Timertask will not be called. Further debugging reveals that the TimerTask gets to block indefinitely and is moved into the suspended list and remains there the entire time. This behavior was replicable in the release version and in new Projects that used the Software Timer and the vSuspendTask functionality. I found a quick dirty solution by simply changeing one line in the function vTaskPlaceOnEventListRestricted I inserted 0 instead of the xWaitIndefinitely == pdTRUE disabling the part with the insertion to the suspended list
        #if( INCLUDE_vTaskSuspend == 1 )
    {
                    /* xWaitIndefinitely == pdTRUE set to 0 */
        if( 0 )
        {
            /* Add the task to the suspended task list instead of a delayed
            task list to ensure the task is not woken by a timing event.  It
            will block indefinitely. */
            traceTASK_DELAY_SUSPEND( pxCurrentTCB );
            vListInsertEnd( &xSuspendedTaskList, &( pxCurrentTCB->xGenericListItem ) );

        }
        else
        {
            /* Calculate the time at which the task should be woken if the
            event does not occur.  This may overflow but this doesn't
            matter. */
            xTimeToWake = xTickCount + xTicksToWait;
            traceTASK_DELAY_UNTIL();
            prvAddCurrentTaskToDelayedList( xTimeToWake );
        }
    }
    #else
The modified version works fine. The LED keeps toggling even after the first overflow. I hope the behavior is replicable and if someone has a clue on where the problem might be, please inform me. Best regards from germany, Patrick

FreeRTOSDemoRL78_RL78G13_Promo_Board_IAR Software Timer problem on RL78 G13 R5F100LEA

Thank you for the detail in your report. This is an area of code that changed very recently (in the last release) and it looks like an error may mave been introduced. We will investigate immediately and report back.

FreeRTOSDemoRL78_RL78G13_Promo_Board_IAR Software Timer problem on RL78 G13 R5F100LEA

This needs a lot more testing – but a possible fix is below. 1) Find the call to vQueueWaitForMessageRestricted(), which is in the function prvProcessTimerOrBlockTask() within timers.c 2) Add the following code immediately before the call to prvProcessTimerOrBlockTask(): ~~~~ if( xListWasEmpty != pdFALSE ) { /* The current timer list is empty – is the overflow list also empty? */ xListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList ); } ~~~~ Please report back your findings.

FreeRTOSDemoRL78_RL78G13_Promo_Board_IAR Software Timer problem on RL78 G13 R5F100LEA

Hello, this won t fix the problem since when you jump into the prvProcessTimerOrBlockTask() function
    /* The tick count has not overflowed, has the timer expired? */
    if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) )
    {
        ( void ) xTaskResumeAll();
        prvProcessExpiredTimer( xNextExpireTime, xTimeNow );
    }
The if statement will become true since we just set xListWasEmpty to 0 when the OverflowTimerList still contains elements and the second statement will be true as well since we are before the xTickCount overflow xNextExpireTime = 0 <= xTimeNow < 65535, thus calling prvProcessExpiredTimer( ). The problem here is there is nothing to process, the current Timerlist is empty. I made modifications to your proposal and changed prvProcessTimerOrBlockTask() function the following way: ~~~~ static void prvProcessTimerOrBlockTask( const TickTypet xNextExpireTime, const BaseTypet xListWasEmpty ) { TickTypet xTimeNow; BaseTypet xTimerListsWereSwitched; /* Added Code for Software Timer Fix */ BaseType_t xOverflowListWasEmpty;
vTaskSuspendAll();
{
    /* Obtain the time now to make an assessment as to whether the timer
    has expired or not.  If obtaining the time causes the lists to switch
    then don't process this timer as any timers that remained in the list
    when the lists were switched will have been processed within the
    prvSampleTimeNow() function. */
    xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );
    if( xTimerListsWereSwitched == pdFALSE )
    {
        /* The tick count has not overflowed, has the timer expired? */
        if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) )
        {
            ( void ) xTaskResumeAll();
            prvProcessExpiredTimer( xNextExpireTime, xTimeNow );
        }
        else
        {
            /* The tick count has not overflowed, and the next expire
            time has not been reached yet.  This task should therefore
            block to wait for the next expire time or a command to be
            received - whichever comes first.  The following line cannot
            be reached unless xNextExpireTime > xTimeNow, except in the
            case when the current timer list is empty. */

                                            /* Added Code for Software Timer Fix */
                            if( xListWasEmpty != pdFALSE )
                            {
                            /* The current timer list is empty - is the overflow list
                            also empty? */
                            xOverflowListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList );
                            }

            vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xOverflowListWasEmpty );

            if( xTaskResumeAll() == pdFALSE )
            {
                /* Yield to wait for either a command to arrive, or the
                block time to expire.  If a command arrived between the
                critical section being exited and this yield then the yield
                will not cause the task to block. */
                portYIELD_WITHIN_API();
            }
            else
            {
                mtCOVERAGE_TEST_MARKER();
            }
        }
    }
    else
    {
        ( void ) xTaskResumeAll();
    }
}
} /———————————————————–/ ~~~~ As you can see i added a new Variable** xOverflowListWasEmpty** who should check just before the Overflow occurs, if it is OK to set the TimerTask into the suspended list waiting there with no timeout. I tested this version for some time and it seems to be working. I didn t look into the behavior what happens when i stop the timers midway trough and Restart them some time later.

FreeRTOSDemoRL78_RL78G13_Promo_Board_IAR Software Timer problem on RL78 G13 R5F100LEA

Did you actually try the change? There were some ‘const’ keywords that would need to be removed to get it to compile. I think the intent of your code is the same as the code I posted. The point at which it has been inserted in the code is identical, and its structure is identical, but your code is using a new variable, rather than re-using the xListWasEmpty variable. In your code however the new variable is not initialised, so will take a random value, and as such will probably never equal pdFALSE – hence it will appear to work most of the time (but not for code that uses the tick-less idle mode, which is what this change was included for). Also in your code there will (I think) be problems when the overflow timer list is empty, but the current timer list is not. Background for others reading this – lets try and describe why the issue occurs (if I have it right): [as you no doubt already know] In FreeRTOS there are two lists of software timers – a list that contains timers that are due to expire before the tick count overflows (called the current timer list), and a list that contains timers that are due to expire after the tick count has next overflow (called the overflow timer list). My understanding is (?) that the issue arose when the current timer list was empty, but the overflow timer list was not empty – and that the route cause of the problem was that the decision as to whether the timer task was placed into the Suspended or Blocked state was taken after only looking at the current timer list. Therefore, the timer task entered the Suspended state when there were still active timers. The fix was to consider both the current and overflow timer lists – but that cannot be done until after the line:
if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) )
xListWasEmpty passed into prvProcessTimerOrBlockTask() is true if the current timer list is empty. In my fix, if xListWasEmpty is set to true, then a second check is performed to see if the overflow timer list is also true, and the value passed into vQueueWaitForMessageRestricted() therefore takes into account bother timer lists. In your fix, if xListWasEmpty is true, then the value passed into vQueueWaitForMessageRestricted() is set to true if the overflow timer list is also empty, but if xListWasEmpty is false, the value passed into vQueueWaitForMessageRestricted() is an uninitalised variable - but I think the intent is the same. If any of my post here is not correct, please let me know. If you didn't try my fix then please do - all you need to do - it is almost the same as your fix. Regards.

FreeRTOSDemoRL78_RL78G13_Promo_Board_IAR Software Timer problem on RL78 G13 R5F100LEA

Yes you are right, it seems I missunderstood your intentions since you said 2) Add the following code immediately before the call to prvProcessTimerOrBlockTask(): this way the statement in the function doesn t work properly. I tried it once and it failed if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) ) I removed the const expresseion before xListWasEmpty and the Variable i used before. Now it looks like this. It works fine so far. I m just thinking about the case if the TimerTask gets suspended due to the Timerlists being empty. Does it still work when I restart the Timers? I haven t looked into this case yet. ~~~~ /-----------------------------------------------------------/ static void prvProcessTimerOrBlockTask( const TickTypet xNextExpireTime, BaseTypet xListWasEmpty ) { TickTypet xTimeNow; BaseTypet xTimerListsWereSwitched;
vTaskSuspendAll();
{
    /* Obtain the time now to make an assessment as to whether the timer
    has expired or not.  If obtaining the time causes the lists to switch
    then don't process this timer as any timers that remained in the list
    when the lists were switched will have been processed within the
    prvSampleTimeNow() function. */
    xTimeNow = prvSampleTimeNow( &xTimerListsWereSwitched );
    if( xTimerListsWereSwitched == pdFALSE )
    {
        /* The tick count has not overflowed, has the timer expired? */
        if( ( xListWasEmpty == pdFALSE ) && ( xNextExpireTime <= xTimeNow ) )
        {
            ( void ) xTaskResumeAll();
            prvProcessExpiredTimer( xNextExpireTime, xTimeNow );
        }
        else
        {
            /* The tick count has not overflowed, and the next expire
            time has not been reached yet.  This task should therefore
            block to wait for the next expire time or a command to be
            received - whichever comes first.  The following line cannot
            be reached unless xNextExpireTime > xTimeNow, except in the
            case when the current timer list is empty. */

                                            /* Added Code for Software Timer Fix */
                            if( xListWasEmpty != pdFALSE )
                            {
                            /* The current timer list is empty - is the overflow list
                            also empty? */
                            xListWasEmpty = listLIST_IS_EMPTY( pxOverflowTimerList );
                            }

            vQueueWaitForMessageRestricted( xTimerQueue, ( xNextExpireTime - xTimeNow ), xListWasEmpty );

            if( xTaskResumeAll() == pdFALSE )
            {
                /* Yield to wait for either a command to arrive, or the
                block time to expire.  If a command arrived between the
                critical section being exited and this yield then the yield
                will not cause the task to block. */
                portYIELD_WITHIN_API();
            }
            else
            {
                mtCOVERAGE_TEST_MARKER();
            }
        }
    }
    else
    {
        ( void ) xTaskResumeAll();
    }
}
} /-----------------------------------------------------------/ ~~~~

FreeRTOSDemoRL78_RL78G13_Promo_Board_IAR Software Timer problem on RL78 G13 R5F100LEA

Yes you are right, it seems I missunderstood your intentions since you said 2) Add the following code immediately before the call to prvProcessTimerOrBlockTask():
Oops, my bad, sorry for the confusion. I meant to say "immediately before the call to vQueueWaitForMessageRestricted()".
Im just thinking about the case if the TimerTask gets suspended due to the Timerlists being empty. Does it still work when I restart the Timers?
Although internally the task is placed into the Suspended tasks list - conceptually it is in the Blocked state, not the suspended state. It is identical to blocking indefinitely on a queue - when data is written to the queue the timer task is unblocked. In fact, that is exactly what is happening - it is the timer command queue that is being blocked on. You are getting into the guts of the internal implementation here - which is good :o) Note that the task's "event list item" is placed into the event list of the timer command queue, and its "generic list item" is placed into the Suspended list. When you restart a timer, the API call you make sends a command to the timer command queue (that happens inside the API function). As soon as data arrives in the timer command queue the queue's event list is used to locate tasks that are waiting for data, which in this case is the timer task, and the timer task is then removed from the Suspended list and placed in a Ready list. Once in the Ready list it will start running as soon as it is the higher priority task.

FreeRTOSDemoRL78_RL78G13_Promo_Board_IAR Software Timer problem on RL78 G13 R5F100LEA

Thank you, very much for your support so far. I will report back if any other issues arise or the robustness seems satisfactory within my projects. There is still one question I have concerning a different topic. I wanted to ask if there will be a FreeRTOS port available for the RL78 series that works on IAR Embedded Workbench v2.1 . Due to changes to the Linker and directives the current port is not useable.

FreeRTOSDemoRL78_RL78G13_Promo_Board_IAR Software Timer problem on RL78 G13 R5F100LEA

I wanted to ask if there will be a FreeRTOS port available for the RL78 series that works on IAR Embedded Workbench v2.1 . Due to changes to the Linker and directives the current port is not useable.
I wasn't aware of this issue - hence there was no plan to update. Our current work load and development schedule would mean an update would not be scheduled for a while if there were.