Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Real time embedded FreeRTOS mailing list 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT Training




Loading

1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by bernatikv on April 5, 2017

Hello, I got nRF52 port of FreeRtos and there were tick bug. They called correctly vTaskStepTick(diff); but then they did not clear RTC->Compare Event flag. Thus they effectively jumped into RTC ISR and added extra tick. And thus effectively after every portSUPPRESS_TICKS_AND_SLEEP system tick was 1 tick faster and timing was wrong. I did fix that by clearing RTC Compare Event Flag. That fixed frequency when in my test code I was calling function vTaskDelayUntil( &xLastWakeTime, xFrequency ); . But I noticed another problem. I noticed there is one tick delay - between CPU wake up #define configPOST_SLEEP_PROCESSING( x ) nrf_gpio_pin_set(CPU_RUN_PIN); and actually starting the task. I find out it is due to fact that adding delayed task from pxDelayedTaskList is happenning only in xTaskIncrementTick(). I assume that is not correct. I assume that it shall also happen in vTaskStepTick(). So I assume it is bug in FreeRTOS. I'm actually having old version FreeRTOS V8.2.1, but I downloaded later FreeRTOS V9.0.0 and I saw there is same vTaskStepTick(). I know how to workaround it. I just call vTaskStepTick() with update value 1 tick lower than should be and I keep RTC compare event flag. So I let xTaskIncrementTick() to count last tick and it is working fine. It just seems like bug that many people may not notice and could have 1 tick of CPU being in zombie mode where task is still in pxDelayedTaskList although it shall be running already. What do you think? Can vTaskStepTick() be updated with delayed task timeout expire check?


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by rtel on April 5, 2017

It is not clear, are you saying you can replicate this in the code provided by us? As I recall in the default tickless mode the step tick function is passed one less than the expected idle time because when it executes there is already a tick interrupt pending.


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by bernatikv on April 10, 2017

I have no platform to test your original distro. I'm observing the bug on Nordic SDK 12.0 and 13.0. I hate those Nordic guys for giving me buggy SDK so I'm biased against them. But frankly I think FreeRTOS is partially in fault here. If you look into documentation http://www.freertos.org/vTaskStepTick.html freeRTOS just say call this function and correct time. There shall be some warning (ideally with big red letters) that this function is not rescheduling tasks. And task are rescheduled only after xTaskIncrementTick() is actually called. So what you want to do is correct the time -1 and call xTaskIncrementTick(). This bug is hard to find because it only delays starting the task 1 tick. But if you do low power design and you let CPU run wait loop for one tick then it is not such banality as it may sound...


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by bernatikv on April 10, 2017

I think free rtos shall modify documentation into this way: into documentation http://www.freertos.org/vTaskStepTick.html

~~~ ... /* Determine how long the microcontroller was actually in a low power state for, which will be less than xExpectedIdleTime if the microcontroller was brought out of low power mode by an interrupt other than that configured by the vSetWakeTimeInterrupt() call. Note that the scheduler is suspended before portSUPPRESSTICKSANDSLEEP() is called, and resumed when portSUPPRESSTICKSANDSLEEP() returns. Therefore no other tasks will execute until this function completes. */ ulLowPowerTimeAfterSleep = ulGetExternalTime();

/* Correct the kernels tick count to account for the time the microcontroller
spent in its low power state. 
Subtract one as it will be counted by xTaskIncrementTick() later*/
vTaskStepTick( ulLowPowerTimeAfterSleep – ulLowPowerTimeBeforeSleep -1);

// call once tick so rescheduling is forced when xTaskResumeAll() is 
//   called - otherwise task start one tick later,
// and there is one tick of useless CPU consumption
xTaskIncrementTick();

/* Restart the timer that is generating the tick interrupt. */
prvStartTickInterruptTimer();
...

~~~


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by rtel on April 10, 2017

I'm still not really following what the problem is. I know Nordic had a bug in their implementation as it is mentioned on their forum some times - at which time they also point the poster's to the fix they provided.

vTaskStepTick() is not something the application writer should be calling directly. It is only for use by tickless low power implementations.

The tickless idle implementation does not switch to another task. It stops the tick, places the system into a low power state, correct the time when it starts running again, and restarts the tick. It is brought out of low power mode by an interrupt. If the interrupt handler (which may be the timer interrupt set to mark the end of the idle period) requests a context switch then the context switch will be held pending until the 'suppress ticks and sleep' function exits. The 'suppress ticks and sleep' function is called with the scheduler suspended, so when it exits the scheduler is unsuspended, and at which point any pending context switches will occur.

For the tickless idle function to perform a context switch itself would be a logical error - besides which - it is called with the scheduler suspended so it couldn't even if it tried. The context switch would just pend until the scheduler was restarted.

It sounds like you are describing what might be subtle bug, and maybe you are right, but I'm afraid I don't understand what it is you are describing. You say the suppress ticks and sleep function is not switching tasks - which is right - it definitely should not.

So please clearly describe the scenario where you think there is a problem, something like this:

1) The clock is programmed to wake in 10000 clock counts. 2) Interrupts are disabled. 3) Low power mode is entered. 4) TBD interrupt occurs, bringing the MCU out of low power mode after 5000 clock counts. 5) Etc.

until I see the bit that you think is wrong.


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by bernatikv on April 10, 2017

Ok let's go step by step: 1. expect there is one task and that task will call vTaskDelayUntil( ...); 2. FreeRTOS starts idle task portTASK_FUNCTION( prvIdleTask, pvParameters ) 3. Idle tasks calls vTaskSuspendAll(); 4. Then it put CPU to sleep calling: portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ); 5. When CPU wakes up it will just correct time as is in free rtos help: vTaskStepTick(diff); 6. Then it returns to idle task and it will call: ( void ) xTaskResumeAll(); But here is a problem. Nor vTaskStepTick() nor xTaskResumeAll() checks if tasks is unblocked. Someone has to call BaseType_t xTaskIncrementTick( void ) which would place the task on ready list: prvAddTaskToReadyList( pxTCB );. Since no-one did that what is hapenning? CPU is in forever loop in idle task. Consumes energy and doing nothing for whole 1 tick. After tick finally happen ISR void xPortSysTickHandler( void ) calls xTaskIncrementTick(); and it will unblock task and put it to ready list. But 1 tick late!.

How to fix it? In step 5 you can call instead of vTaskStepTick(diff); follwoing sequence: ~~~ vTaskStepTick(diff-1); // -1 because we will call tick event just in next command xTaskIncrementTick(); // this will actually use ++uxPendedTicks; because task sheduler is suspended ~~~ Now if you move to step 6 everything is going fine. xTaskResumeAll(); restart scheduler, detects uxPendedTicks, thus calls xTaskIncrementTick() which will add task to prvAddTaskToReadyList( pxTCB ); and retrun true so xTaskResumeAll(); will call taskYIELD_IF_USING_PREEMPTION(); and task is switched to right after CPU waking up Hurray! everything works now :)

So what I think you shall do - either document this into vTaskStepTick() that it is developer responsibility to call xTaskIncrementTick(); or better rewrite vTaskStepTick() to do: ~~~ xTickCount += xTicksToJump-1; xTaskIncrementTick(); ~~~

Did I made myself clear enough this time??


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by rtel on April 11, 2017

Ok let's go step by step:

This is good...

  1. expect there is one task and that task will call |vTaskDelayUntil( ...);|

Lets say the call is vTaskDelay( 10 ), and to make it easy, that 10 means 10 milliseconds (1KHz tick).

  1. FreeRTOS starts idle task |portTASK_FUNCTION( prvIdleTask, pvParameters )|
  2. Idle tasks calls |vTaskSuspendAll();|

That will prevent context switches occurring, but will keep any requested context switches pending.

  1. Then it put CPU to sleep calling: |portSUPPRESSTICKSAND_SLEEP( xExpectedIdleTime );|

Lets say the MCU slept for the full 10ms, so it is the timer interrupt (SysTick interrupt) that brings the CPU out of sleep mode.

When the CPU comes out of sleep mode interrupts become enabled for a short while, at which point the SysTick interrupt executes. The SysTick handler calls xTaskIncrementTick() - but the scheduler is suspended so xTaskIncrementTick() just increments the uxPendedTicks variable to hold the tick pending.

  1. When CPU wakes up it will just correct time as is in free rtos help: |vTaskStepTick(diff);|

vTaskStepTick() should now be called with 9 as its parameter. That is, 9 ticks are going to be stepped, one tick is already pending, making the total of 10 ticks. Therefore the tick count should be stepped forward to the time the task that called vTaskDelay( 10 ) should unblock.

  1. Then it returns to idle task and it will call: |( void ) xTaskResumeAll();|

xTaskResumeAll() calls xTaskIncrementTick() once per count held pending in the uxPendedTicks variable. The tick count has already been stepped forward 9, calling xTaskIncrementTick() increments the tick for the 10th time, so the time reaches the time at which the task that called vTaskDelay() should leave the blocked state, and the task is unblocked, and a context switch pended. The context switch will execute before xTaskResumeAll() exits - as soon as xTaskResumeAll() exits its critical section.

But here is a problem. Nor |vTaskStepTick()| nor |xTaskResumeAll()| checks if tasks is unblocked.

In the scenario above xTaskResumeAll() unblocks the task when it calls xTaskIncrementTick().

Someone has to call |BaseType_t xTaskIncrementTick( void )| which would place the task on ready list: |prvAddTaskToReadyList( pxTCB );|. Since no-one did that what is hapenning? CPU is in forever loop in idle task. Consumes energy and doing nothing for whole 1 tick.

It sounds like there is something else wrong in your code. Do you have the fixed code from Nordic?

How to fix it? In step 5 you can call instead of |vTaskStepTick(diff);| follwoing sequence:

vTaskStepTick(diff-1); // -1 because we will call tick event just in next command xTaskIncrementTick(); // this will actually use ++uxPendedTicks; because task sheduler is suspended

That will result in the tick count being one ahead of where it should be.

So what I think you shall do - either document this into |vTaskStepTick()| that it is developer responsibility to call |xTaskIncrementTick();| or better rewrite |vTaskStepTick()| to do:

xTickCount += xTicksToJump-1; xTaskIncrementTick();

Did I made myself clear enough this time??

Yes, understood this time, thanks, but the scenario you describe is not the scenario I see in the code. Can you determine where your observed behaviour differs from the sequence I have described above?

The sequence I describe above assumes it is the tick that brings the MCU out of sleep mode. If another interrupt brings the CPU out of sleep mode then it is up to that interrupt to pend a context switch if one is necessary - but that is true of all interrupts that perform an action that brings a task out of the Blocked state. Make sure your interrupt handlers are doing that correctly if you have something other than the tick bringing your CPU out of sleep mode.


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by bernatikv on April 11, 2017

Hello your sentence:

"When the CPU comes out of sleep mode interrupts become enabled for a short while, at which point the SysTick interrupt executes."

is not correct. Nordic goes to sleep with global interrupt disabled. The CPU is woken up on interrupts but would not go to ISR.

Also such behavior might be quite dangerous from other point of view. Imagine that CPU is woken by other event. And imagine that ISR of that other even would ask to get sysTick from ISR. It might be very imprecise before correction is done. The CPU could have slept for minute and thus timestamp of event stored by such ISR would be totaly old and incorect.

Also nordic quite reasonably after correcting time using function vTaskStepTick() clears the RTC IRQ Flags, because they already fixed the time. And there was not written in documentation that vTaskStepTick() won't reschedule delayed tasks into ready tasks (what in my opinion would be expectable and nice from that function).

You can see what they do in portcmsissystick.c: ~~~ void vPortSuppressTicksAndSleep( TickTypet xExpectedIdleTime ) { /* * Implementation note: * * To help debugging the option configUSETICKLESSIDLESIMPLEDEBUG was presented. * This option would make sure that even if program execution was stopped inside * this function no more than expected number of ticks would be skipped. * * Normally RTC works all the time even if firmware execution was stopped * and that may lead to skipping too much of ticks. */ TickTypet enterTime;

/* Make sure the SysTick reload value does not overflow the counter. */
if ( xExpectedIdleTime > portNRF_RTC_MAXTICKS - configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
{
    xExpectedIdleTime = portNRF_RTC_MAXTICKS - configEXPECTED_IDLE_TIME_BEFORE_SLEEP;
}
/* Block all the interrupts globally */
ifdef SOFTDEVICE_PRESENT
do{
    uint8_t dummy = 0;
    uint32_t err_code = sd_nvic_critical_region_enter(&dummy);
    APP_ERROR_CHECK(err_code);
}while(0);
else
__disable_irq();
endif
enterTime = nrf_rtc_counter_get(portNRF_RTC_REG);

if ( eTaskConfirmSleepModeStatus() != eAbortSleep )
{
    TickType_t xModifiableIdleTime;
    TickType_t wakeupTime = (enterTime + xExpectedIdleTime) & portNRF_RTC_MAXTICKS;

    /* Stop tick events */
    nrf_rtc_int_disable(portNRF_RTC_REG, NRF_RTC_INT_TICK_MASK);

    /* Configure CTC interrupt */
    nrf_rtc_cc_set(portNRF_RTC_REG, 0, wakeupTime);
    nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);
    nrf_rtc_int_enable(portNRF_RTC_REG, NRF_RTC_INT_COMPARE0_MASK);

    __DSB();

    /* Sleep until something happens.  configPRE_SLEEP_PROCESSING() can
     * set its parameter to 0 to indicate that its implementation contains
     * its own wait for interrupt or wait for event instruction, and so wfi
     * should not be executed again.  However, the original expected idle
     * time variable must remain unmodified, so a copy is taken. */
    xModifiableIdleTime = xExpectedIdleTime;
    configPRE_SLEEP_PROCESSING( xModifiableIdleTime );
    if ( xModifiableIdleTime > 0 )
    {
ifdef SOFTDEVICE_PRESENT
        if (softdevice_handler_is_enabled())
        {
            uint32_t err_code = sd_app_evt_wait();
            APP_ERROR_CHECK(err_code);
        }
        else
endif
        {
            /* No SD -  we would just block interrupts globally.
            * BASEPRI cannot be used for that because it would prevent WFE from wake up.
            */
            do{
                __WFE();
            } while (0 == (NVIC->ISPR[0] | NVIC->ISPR[1]));
        }
    }
    configPOST_SLEEP_PROCESSING( xExpectedIdleTime );

    nrf_rtc_int_disable(portNRF_RTC_REG, NRF_RTC_INT_COMPARE0_MASK);
    nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_COMPARE_0);

    /* Correct the system ticks */
    {
        TickType_t diff;

        nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_TICK);
        nrf_rtc_int_enable (portNRF_RTC_REG, NRF_RTC_INT_TICK_MASK);

        /* check for overflow in TICK counter */
        if(nrf_rtc_event_pending(portNRF_RTC_REG, NRF_RTC_EVENT_OVERFLOW))
        {
            nrf_rtc_event_clear(portNRF_RTC_REG, NRF_RTC_EVENT_OVERFLOW);
            m_tick_overflow_count++;
        }

        diff = ((m_tick_overflow_count << portNRF_RTC_BITWIDTH) + nrf_rtc_counter_get(portNRF_RTC_REG)) - xTaskGetTickCount();

        /* It is important that we clear pending here so that our corrections are latest and in sync with tick_interrupt handler */
        NVIC_ClearPendingIRQ(portNRF_RTC_IRQn);

        if((configUSE_TICKLESS_IDLE_SIMPLE_DEBUG) && (diff > xExpectedIdleTime))
        {
            diff = xExpectedIdleTime;
        }

        if (diff > 0)
        {
            vTaskStepTick(diff);
        }
    }
}
ifdef SOFTDEVICE_PRESENT
uint32_t err_code = sd_nvic_critical_region_exit(0);
APP_ERROR_CHECK(err_code);
else
__enable_irq();
endif

} ~~~


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by rtel on April 11, 2017

"When the CPU comes out of sleep mode interrupts become enabled for a short while, at which point the SysTick interrupt executes."

is not correct.

Umm, yes it is. I can point to the lines of code that do it if you like.

Nordic goes to sleep with global interrupt disabled. The CPU is woken up on interrupts but would not go to ISR.

I am confused here. I thought we had established that we were relating to the FreeRTOS code, not code provided by a third party that we cannot be expected to support or otherwise influence. You seem to be looking at Nordic code, but saying there are bugs in and suggesting updates to the FreeRTOS mainline code.

You can see what they do in portcmsissystick.c:

I don't want to see what they do. I just focus on what we do. As I told you before, there were bugs in their implementation, which they claim to have fixed. I asked you a couple of times if you have their fixed code.


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by bernatikv on April 11, 2017

I have latest code from Nordic (From 2017 W11). There is nothing newer as far as I know. But obviously that code is not fixed. So no I have no fixed code, and I doubt such code exists.

I think we have reached an impasse.

I told you that big company (claiming #1 at Bluetooth low energy) partialy fucked up porting of your OS. And as unbiased I'm telling you how you can improve your OS documentation or function to minimize chance that ppl will port it wrongly. For nordic it would help if vTaskStepTick() is actually checking if some task needs to be actually moved into ready queue, and architecturally it seems to me as a good thing that function which adjust time also checks if time is good for some task to be moved into ready queue. But I might be wrong because I'm totally newbee with FreeRtos. There might be good reason not to do it...

Also I can not influence much Nordic to do better job, and implement port of FreeRTOS correctly. Which is possible and easy even with current state of FreeRTOS. And I admit it is more Nordic fault than yours...

Now it is up to you and Nordic. I'm in no position to tell either of you what to do. I reported to both of you what is not working I give you both working solutions how to solve it. The current situation is that port of FreeRTOS on Nordic has 1 tick idle loop every wakeup, so it is not much low power. If you are OK with it then be it. If you are not ok with it you can solve it actually only with nordic not with me :( I can do my own fix, for my own product, and I will have competitive advantage to other developers who would not apply my fix... So for me it is actually best if there is bug for others, and I have it fixed inhouse... I just wanted be good guy and improve things... I have no reason to be pushy or in stress... And like I said it is mostly Nordic shit anyway so you can be calm also. So have a nice day


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by rtel on April 11, 2017

For nordic it would help if vTaskStepTick() is actually checking if some task needs to be actually moved into ready queue,

...but it would be a logical error if it was to do that, as it is done when the scheduler is unsuspended. Even if vTaskStepTick() did do that it is called with the scheduler suspended so the switch to the new task would not occur until the scheduler was unsuspended - which is exactly what it is doing now.

Now it is up to you and Nordic. I'm in no position to tell either of you what to do. I reported to both of you what is not working I give you both working solutions how to solve it.

Please, understand, the FreeRTOS code is working. I can't comment on the Nordic code as I've not looked at it, but as I have already described the problem does NOT exist in the official FreeRTOS code.


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by bernatikv on April 18, 2017

Hello, Please understand that even FeeRTOS code is not working. As you explained me above how freertos original port works I told you that I'm afraid that there will be problem with geting xTick from ISR. And unfortunatelly I was right. I just got my hands on F767ZI which is using original FreeRTOS port for ARM M7 and the code does not work. It has correct sleep period and correct wakup time, but when you have for example interrupt from GPIO and ISR will call xTaskGetTickCountFromISR() then it will return wrong time. It will return the time when CPU went to sleep. But current time may be many hundreds of ticks different. The problem is that port.c is calling enable_irq(); before vTaskStepTick() compensate for sleep time. I'm little bit frustrated to work with such libraries :( Could you please fix your RTOS?


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by rtel on April 18, 2017

You are right of course. If you stop the tick, then read the tick count, the value you read is the value it had when you stopped it. Then, after you have stepped the value forward to account for the time the tick was stopped, when you read the tick value the value you read is the value the tick would have had if it had never been stopped. I take it from your post you now agree with me the values read are as expected. >


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by bernatikv on April 19, 2017

No - value read is not as expected. So once again try to hear me. I did simple app. It sleeps in loop for 1 second. The code can be also woken up by IRQ from GPIO. When I ask for tick in ISR triggered by GPIO toggle I get wrong time. So of course it is wrong. And it should not behave like that. I expect function get tick to give me always correct time. I do not care how you do your port and where you stop timer and where you compensate. I expect simply that kernel will works. And function for returning ticks will give me correct time - always. In your own specification is written that xTaskGetTickCountFromISR() returns: "The count of ticks since vTaskStartScheduler was called." and it does not do that! So it is very wrong and devfinitelly not correct. Do you understand now?? The fix seems to be easy to me you can just call enable_irq(); after vTaskStepTick( ulCompleteTickPeriods ); compensation.


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by rtel on April 19, 2017

No - value read is not as expected. So once again try to hear me.

This will be my last post on this thread, unless you can provide me a clear sequence of events, step by step, with no ambiguity so I know exactly the sequence you are describing, that shows there is a problem that needs investigating:

I did simple app. It sleeps in loop for 1 second. The code can be also woken up by IRQ from GPIO. When I ask for tick in ISR triggered by GPIO toggle I get wrong time.

You get the wrong time? Or you get the time at which the tick interrupt was stopped? As per my last post, if you read the tick count while it is stopped then the EXPECTED value will be the value the tick count had when you stopped it. After you have stepped the tick count forward to take into account the time it was stopped for then the value read will be as if the tick hadn't been stopped - and not before. To state again, if a value is incrementing, and you [deliberately] stop it incrementing, then read the value, the value you read will be the value the variable had at the time it stopped being updated.

So of course it is wrong. And it should not behave like that. I expect function get tick to give me always correct time.

The tick has been stopped. It doesn't change while it is stopped. It starts changing after you start it again. Otherwise what would it mean to stop it?

I do not care how you do your port and where you stop timer and where you compensate. I expect simply that kernel will works. And function for returning ticks will give me correct time - always.

Always....other than when you have stopped it.

In your own > specification is written that |xTaskGetTickCountFromISR()| returns: "The > count of ticks since vTaskStartScheduler was called."

I could update the documentation to say "unless you have done something to stop it", but I think the tickless idle documentation probably says that while the tick is not incrementing its value does not change.

and it does not do > that! So it is very wrong and devfinitelly not correct. Do you > understand now?? The fix seems to be easy to me you can just call > enable_irq(); after vTaskStepTick( ulCompleteTickPeriods ); compensation.

Please re-read all this thread. I have already stated why that would be wrong.


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by bernatikv on April 20, 2017

We shall clear one thing. I do not do anything with tick. I'm user of your FreeRTOS. I'm using your original port "FreeRTOSv9.0.0FreeRTOSSourceportableRVDSARMCM7r0p1port.c". I only wrote simple user code: ~~~ while (1) { vTaskDelayUntil( &xLastWakeTime, xFrequency ); chNum = sprintf(txt,"%drn", xTaskGetTickCount()); HALUARTTransmit(&huart2, (uint8t)txt, chNum, 1000); } void HALGPIOEXTICallback(uint16t GPIOPin) { uint32t chNum; chNum = sprintf(txt,"btn: %drn", xTaskGetTickCountFromISR( )); HALUARTTransmit(&huart2, (uint8_t)txt, chNum, 1000); } ~~~ Frequency is 1 second tick is every 1ms. When I configure my FreeRTOS to not be power saving: #define configUSE_TICKLESS_IDLE 0 and run the code my test is working well it prints time every second and then it prints time when button was pressed: 9001 10001 btn: 10611 11001 12001

I see the time when I pressed button.

When my only change is to confiogure FreeRTOS to be more power efficient and use tickless sleep #define configUSE_TICKLESS_IDLE 1 my code stops working - because I do not see whn I pressed button but I see only last time that was printed by task: 9001 10001 btn: 10001 11001 12001

You see that I do not see true time when I pressed button, but time when FreeRTOS went to sleep.

To me power saving feature shall ideally not have impact on code behavior.

I nowhere see in documentation some note about the fact that tick is not reported correctly under some system configuration - please point me to the documentation where such information is written.

I looked here: http://www.freertos.org/a00021.html#xTaskGetTickCountFromISR here: http://www.freertos.org/a00110.html#configUSETICKLESSIDLE and here: http://www.freertos.org/low-power-tickless-rtos.html and nowhere is information that xTaskGetTickCountFromISR() can under certain situation report other time than time passed since vTaskStartScheduler() was called.

If you insist on claim that this behavior is "AS EXPECTED". Then to me it sounds crazy - but we have saying: "there can not be arguing about anyone taste". I just hope that you are consistent in your opinions. I have personal question - when you go to sleep and set your alarm clock next to your bed to go off after 8 hours. Then when you wake up - do you prefer your alarm clock to show you time when you fall asleep? Or rather (as rest of the world) you like your alarm clock to show you current time? Another parallel would be - do you want your alarm clock next to your bed to show different times when you run it from power outlet and when you run it from battery? Or do you want it (as rest of the world) to show same times no mather what is the power source?


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by davedoors on April 20, 2017

This thread is boring and stopped being useful to other FreeRTOs users after a few posts - is it just trolling? Can we lock the thread?

I have a question for you. If you stop the tick, then read the value back while it is stopped, what value would you expect it to be? You seem to argue it should not be any different as if it hadnt been stopp, so then my question to you is what do you think stopping the tick does?

If you really must read the time from an interrupt when you know the tick is not running then read a time you know is running. A hardware timer is still running, only the interrupt is stopped, so read the hardware timer to work out what the time is. Another way is to just unblock a task in the interrupt, then read the time in the task. The task will not read the time until after the tick has been corrected for the sleep time.


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by bernatikv on April 20, 2017

To me stopping the tick is power saving feature. RTOS should and partially does compensate ticks after wake up. The only problem is that it enables ISR sooner befgore it does the compensation. To me it seems as just a matter of enabling ISR few instruciotn later after the time compensation is done. Why not to do that if it seems easy? When I rewrite port.c and move __enable_irq(); to the end of vPortSuppressTicksAndSleep() then everything works as expected.

You are rgiht there is multiple other ways how to solve it, but those are workaround of wrong desing.

I would have accepted that they do not want to change port.c code for some reason. But at least I would like to force them to update documentation so users know that xTaskGetTickCountFromISR() is not working well sometimes when tickless mode is enabled.

And no I'm not trolling I'm offering working solution. And I'm open to hear arguemtns why on earth first ISR shall report wrong time?


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by davedoors on April 20, 2017

Interrupts get enabled as soon as possible to maximize responsiveness. Coming out of a low power mode can take the hardware a long time and most people want the interrupt that woke the chip to execute as soon as physically possible. The latest version in SVN goes further, enabling interrupts so they can execute asap, then disabling them again while the catch up is done.


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by bernatikv on April 20, 2017

Dave thank you! now you said first reasonable response in this long and exhausting thread! If we prefer speed over correct tick reporting then it is understandable. But still we need to write in big red letters in documentation that we made this choice and that time reporting under this and that condition is not correct because we prefer speed. On my ARM M7 at 16MHz the time compensation takes around 1.5ms. Which is trully quite long... Perhaps this can be added as configurable option - if we prefer fast wake up from deep sleep or if we prefer code to work same as if tickless mode is disabled. I can imagine if some chip is anyway waking up 10ms from deep sleep the extra 1.5 ms is acceptable for user...


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by bernatikv on April 20, 2017

I also looked to nordic "portcmsissystick.c" and they enable IRQ only after tick compensation (so their code behave correctly -> same in tickless enabled or disabled). I measured that their compensation time takes only 6us (partially due to the arm is using faster clock 64MHz) but mostly due to the fact they are not dividing. Instead of systick timer they used RTC hardware and it uses prescaler to have 1 counted value same as 1 tick. So if you have free RTC HW in your ARM that has Compare register and Prescaler you can write much faster port than is generic free rtos port. The problem is that generic systick needs division operation which is very slow operation. Also RTC with Compare register does not need to be stopped so other benefit of such approach would be that there is not event small time drift in tickless mode (standard free rtos arm port is stopping for while systick counter which creates small tick drift).


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by bernatikv on April 20, 2017

Hups I made a mistake in previous measurement of original free rtos port.c. I moved __enable_irq(); at the end of vPortSuppressTicksAndSleep() but just now I noticed that ISR is enetered when portEXIT_CRITICAL(); is called. Therefore I measured too long compensation time (I added time for my long demo ISR). When I put my pin toggle before portEXIT_CRITICAL(); then I see that compensation time is not ~1.5ms but only ~18us!!! Division operation is actually fast it takes only ~2us. But that means that probably most users would prefer to delay first ISR after sleep by 18us and get consistent behavior in both modes (tickless enabled and disabled). If some user needs ISR to be run very quickly he/she probably would not use tickless mode at the first place anyway - because waking CPU up takes also some time (in my case waking Arm M7 CPU takes 5 us, but for example my nordic chip nRF52832 wakes up from sleep 43us). So back to original statement that port.c shall be changed to compensate tick before ISR is called. Or do you still think that 18us is more important that consistent behavior? (if yes then there is no point in arguing - this is up to everyone taste, just add this weird decision to documentation)


1 tick delayed task start after portSUPPRESS_TICKS_AND_SLEEP

Posted by tlafleur on April 20, 2017

If you don't understand how FreeRTOS work or don't like the way it works. You have full source code, make the changes you need and be done with it!!!

~~ _/) ~~~~ _/) ~~~~ _/) ~~~~ _/) ~~

Tom Lafleur

On Thu, Apr 20, 2017 at 7:49 AM, Vit Bernatik bernatikv@users.sf.net wrote:

I also looked to nordic "portcmsissystick.c" and they enable IRQ only after tick compensation (so their code behave correctly -> same in tickless enabled or disabled). I measured that their compensation time takes only 6us (partially due to the arm is using faster clock 64MHz) but mostly due to the fact they are not dividing. Instead of systick timer they used RTC hardware and it uses prescaler to have 1 counted value same as 1 tick. So if you have free RTC HW in your ARM that has Compare register and Prescaler you can write much faster port than is generic free rtos port. The problem is that generic systick needs division operation which is very slow operation. Also RTC with Compare register does not need to be stopped so other benefit of such approach would be that there is not event small time drift in tickless mode (standard free rtos arm port is stopping for while

systick counter which creates small tick drift).

1 tick delayed task start after portSUPPRESSTICKSAND_SLEEP

Sent from sourceforge.net because you indicated interest in https://sourceforge.net/p/freertos/discussion/382005/

To unsubscribe from further messages, please visit https://sourceforge.net/auth/subscriptions/

Attachments

alternate (2515 bytes)


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.


Free TCP/IP and file system demos for the RTOS


Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists