Tickless/stm32/Interrupt issue

Hi, I’ve just tried to enable tickless mode, as expected it causes uart interrupts to be missed, so I redefined this: #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) if( AppWantsToEnterSleepMode() == pdTRUE ) { vPortSuppressTicksAndSleep( xExpectedIdleTime ); } My AppWantsToEnterSleepMode was set to return false, so never to allow the processor to sleep. Weirdly, the interrupts were getting lost. So in tasks.c I commented out: `#if ( configUSETICKLESSIDLE != 0 ) { TickType_t xExpectedIdleTime;
        /* It is not desirable to suspend then resume the scheduler on
        each iteration of the idle task.  Therefore, a preliminary
        test of the expected idle time is performed without the
        scheduler suspended.  The result here is not necessarily
        valid. */
        xExpectedIdleTime = prvGetExpectedIdleTime();

        if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
        {
            vTaskSuspendAll();
            {
                /* Now the scheduler is suspended, the expected idle
                time can be sampled again, and this time its value can
                be used. */
                configASSERT( xNextTaskUnblockTime >= xTickCount );
                xExpectedIdleTime = prvGetExpectedIdleTime();

                /* Define the following macro to set xExpectedIdleTime to 0
                if the application does not want
                portSUPPRESS_TICKS_AND_SLEEP() to be called. */
                configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING( xExpectedIdleTime );

                if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
                {
                    traceLOW_POWER_IDLE_BEGIN();
                    portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
                    traceLOW_POWER_IDLE_END();
                }
                else
                {
                    mtCOVERAGE_TEST_MARKER();
                }
            }
            ( void ) xTaskResumeAll();
        }
        else
        {
            mtCOVERAGE_TEST_MARKER();
        }
    }
    #endif /* configUSE_TICKLESS_IDLE */`
And ran the code and interrupts were working again, so then I just added: ~~~ vTaskSuspendAll(); xTaskResumeAll(); ~~~ And the code starts losing interrupts, any explanation for this? I see that xTaskResumeAll has a critical section and these two lines are only in play when tickless is enabled (regardless of whether you actually enter tickless) Any thoughts?

Tickless/stm32/Interrupt issue

Removing the define of portSUPPRESSTICKSAND_SLEEP and putting an “if AppWantsToEnterSleepMode() ” around the tickless idle stuff solves the problem because it’ll only go into it if the application allows it to, outside of that it wont and therefore won’t call the Suspend and Resume all. Obviously I have to patch tasks.c file every time I update.

Tickless/stm32/Interrupt issue

Not sure if I’m missing something – but the PRESLEEPPROCESSING() and POSTSLEEPPROCESSING() macros are available to enable an application abort entry to tickless mode if it wishes without needing to edit the C code. Search for the macros on this page: https://www.freertos.org/low-power-ARM-cortex-rtos.html

Tickless/stm32/Interrupt issue

the issue im seeing is that the suspend and resume that happens way before it gets anywhere near that macro are causing me to miss serial interrupts as shown by my experiment above, those two line of code are executed regardless of whether the processor actually goes into sleep mode and seem to be causing me problems.

Tickless/stm32/Interrupt issue

Some questions come to mine, because you seem to be saying that the suspend is what is causing the issue: 1) What rate are these serial interrupts happening? 2) Are you fully getting the data in the ISR, or is part of the data fetch using a pend function? If you are losing data because the ISR can’t run the task level code at each interrupt, then that is, in my opinion, an issue with program design, not FreeRTOS.

Tickless/stm32/Interrupt issue

its receiving data at 115200, not many bytes. the interrupt simply reads the register and posts the byte into a stream buffer. what im seeing is that with the suspend and resume calls in play in the code i quoted, interrupts get missed.

Tickless/stm32/Interrupt issue

Richard, any thoughts on this behaviour?

Tickless/stm32/Interrupt issue

115200 should be slow enough that critical sections used in FreeRTOS are short enough not to lose interrupts, and Suspending/Resuming the Scheduler won’t block them. The one thought I have is that you are putting the device into too low of a low power mode that actually turns off the devices, and/or takes too long to wake up from when going into tickless idle. There is also a possibility that there is some sort of hardware bug that is causing an issue, but my first guess is that your definition of ‘low powr idle’ is too low.

Tickless/stm32/Interrupt issue

I’m not going into sleep mode, I’ve commented the code out and just have: vTaskSuspendAll(); xTaskResumeAll(); Added in to replace as it’s these lines of code causing the issue, these lines are code are executed before and after (one of each) sleep mode (or the decision on when to sleep) is made. In normal (non tickless) mode of FreeRTOS these calls are not here and it works perfectly as you would expect, but the moment these calls are introduced into the equation I start losing serial interrupts.

Tickless/stm32/Interrupt issue

Richard Barry, do you have any suggestions or thoughts on what is happening here? my “fix” is as i posted in the first link, modify the code in tasks.c so that the very first check is whether tickless is currently enabled before doing anything else. (straight after the first ifdef)

Tickless/stm32/Interrupt issue

bump for Richard! (sorry)

Tickless/stm32/Interrupt issue

I’m not sure I fully understand the original question. Does this have anything to do with tickless mode, or are you just noting that calling xTaskResumeAll() causes interrupts to be missed? vTaskSuspendAll() would have little if any effect on interrupts – hence I’m ignoring that. xTaskResumeAll() does have a critical section but that would do little under normal circumstances. Are you generating an interrupt on each 115200 characters per second? If so, can you minimise the overhead using a DMA or FIFO?

Tickless/stm32/Interrupt issue

I noticed that tickless was losing interrupts regardless of whether tickless was actually being entered, so I commented out the tickless code above and ran and no interrupts were missed. I then started delving into what was causing the issue and found it was the xTaskResumeAll that was causing it. So I simply commented out the tickless code and replaced it with a simple: vTaskSuspendAll xTaskResumeAll And interrupts were getting lost, in tickless mode of operation both these lines of code are executed regardless of whether the decision to sleep is made (which with your macros happens later on in the code above). I’m using an interrupt, but I’m concerned about what this might be doing to other interrupts in the system. These particular lines of code are only “in play” when the OS is configured in tickless mode. My solution is to make the decision right at the top of the code as to whether tickless is enabled, if it is I have to accept that there will be possible issues with interrupts, but given that I’ve opted to go to sleep then it’s something I can live with., but while I don’t allow the processor to sleep I don’t have issues with interrupts. ~~~ #if ( configUSETICKLESSIDLE != 0 ) if (configALLOWSLEEPMODE()) { TickType_t xExpectedIdleTime;
        /* It is not desirable to suspend then resume the scheduler on
        each iteration of the idle task.  Therefore, a preliminary
        test of the expected idle time is performed without the
        scheduler suspended.  The result here is not necessarily
        valid. */
        xExpectedIdleTime = prvGetExpectedIdleTime();

        if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
~~~

Tickless/stm32/Interrupt issue

Hence you can’t use the pre and post sleep macros to abort entering low power mode as they are in the section that executes with the scheduler suspended. The tickless entry/exit actually has to be done with the scheduler suspended to allow the kernel to know what the situation is on exiting sleep mode. Likewise to give the pre/post sleep macros a known execution state. First, if the UART interrupt can be implemented without using any FreeRTOS API calls then you can set its priority above configMAXSYSCALLINTERRUPT_PRIORIY (which on a Cortex-M means a low numeric priority value, 0 being the highest priority). Other than that it is a curious situation. My thought process was that suspending the scheduler is very fast and doesn’t have any critical sections. Resuming the scheduler does however have a critical section – and that if all your idle task is doing is calling xTaskResumeAll() over and over again very rapidly then it will spend a good proportion of its time in that function – however likewise as it is being called rapidly the amount of time spent inside any single call of the function should be extremely short. I’m afraid I don’t really have any other thoughts at this point.

Tickless/stm32/Interrupt issue

Hi Richard, at this point with tasks.c as it stands the behavior tickless mode is (as far as i can tell) broken (i understand we may have opposing views on this! im trying to be as subjective asni can) the critical section there kills interrupts which it shouldnt, any chance of implementing the “fix” as i have described above into the freertos code, by default the default defined value could be 1 so that it operates as it did, but allows tickless to be enabled with no extra overhead with the critical section. although it doesnt fix it with regards to lost interrupts whrn tickless mode is allowed, it does fix it when sleep is not allowed. i was very surprised by this behaviour, especially when i implemented it as suggested and told it not to allow sleep, i didnt expect to see lost interrupts.

Tickless/stm32/Interrupt issue

Yes, if a critical section cause interrupts to be lost like this, then something is broken. It is NOT the fault of the critical section though, as that is done exactly as the ARM architecture says it should be done. My first guess is that somehow your ISR is written wrong, or the interrupt is configured wrong.