Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Legato_Tasks() preemption #40

Open
ghnicolas opened this issue Jul 12, 2024 · 5 comments
Open

Legato_Tasks() preemption #40

ghnicolas opened this issue Jul 12, 2024 · 5 comments

Comments

@ghnicolas
Copy link

Hello,
I am using the library on a PIC32MZDA without OS, and trying to optimize everything I can to fulfil other real time constraints like CAN periodicity messages.
Up to here I don't, the Legato_Tasks() at the preemtion level 1 or 2 keeps the hand during more than 100 ms to paint image widget of 128x128 pixels in RGBA8888 mode. I am using the stream interface, but the time needed to stream image from external memory seems not significant in the complete drawing operation.
Looking into the code I wonder if one of the preemption define (LE_PREEMPTION_LEVEL) used to avoid blocking was correctly placed.
The one in the function _leImageWidget_Paint (legato_widget_image_skin_classic.c) seems to be useless as a deeper function is actually blocking. The deeper function blocking is the _exec function in file legato_imagedecoder_raw.c (while loop).
Is there a way to make this function not blocking ?
Regards
Nicolas

@ghnicolas
Copy link
Author

Maybe unlocking the function after the cache buffer have been completely treated (before returning back to stream a new cache bufffer from external memory) could be great. Users could tune the preemption time depending on the size of the cache buffer.

@microchip-gfx
Copy link
Contributor

To make the raw image decoder loop non-blocking, you should be able to add:

#if LE_PREEMPTION_LEVEL > 0
        return LE_SUCCESS;
#endif

to the end of the loop like so:

// any stage can set done and exit the loop
    while(_state.done == LE_FALSE)
    {
        // stages can return false if they stall
        if(_state.stages[_state.currentStage]->exec(_state.stages[_state.currentStage]) == LE_FAILURE)
            return LE_SUCCESS;

        // increment stage
        _state.currentStage++;

        if(_state.stages[_state.currentStage] == NULL)
        {
            // restart the pipeline
            _state.currentStage = 0;
        }

#if LE_PREEMPTION_LEVEL > 0
        return LE_SUCCESS;
#endif
    }

@ghnicolas
Copy link
Author

Thanks for your answer.
Based on your suggestion I return LE_SUCCESS but when the pipeline is finished (stages var is null) and if a 5 ms time limit has elapsed.
Works ok, 5 ms tolerance on TX message is ok, and UI is quite responsive.

@MCHP-MCU32DC0
Copy link

Hi Nicolas - a few things to try:

  1. Optimize your design - refer to these guides:
    UI optimization
  1. If CAN comms and tasks need higher priority over the GUI, you can consider using an RTOS (e.g., FreeRTOS) so you can prioritize the CAN application task using the RTOS scheduler.

@ghnicolas
Copy link
Author

Hello Ed,
Finally unselecting "Update on VBLANK" in the LE GLCD harmony configuration solved that problem. For people reading the thread, despite the good solution to break the image drawing preemting pipeline, I had still another ~10-15 ms preemption each time a widget image was updated.
Could you explain the difference of choosing "Update on VBLANK" or not please. What is intended by "update" ?
Looking at the code it changes the vblankSync bool to true (when set) and false (when not set), which is used in the GLCD interrupt routine GLCD_Interrupt_Handler :
if (vblankSync && PLIB_GLCD_IsVerticalBlankingActive() == true)
return;
Also as the interrupt is triggered by VSYNC, I don't understand how PLIB_GLCD_IsVerticalBlankingActive() could return false at that moment.
Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

3 participants