Bitmap is only allowed for use with 1 interrupt

Description

hi
I’m having trouble trying to use one interrupt for the uart and one for the counter, at first I thought it was due to priorities but after many tests I noticed that when I turned off one of the two interrupts above the picture My bitmap is working normally again. I need an explanation.

thank you

What MCU/Processor/Board and compiler are you using?

stm32f750 -disco

What LVGL version are you using?

v8.3

What do you want to achieve?

Use multiple interrupts with lvgl.

What have you tried so far?

I kept changing the priorities and didn’t know what else to do.

Code to reproduce

The code block(s) should be formatted like:

/*You code here*/
```void test_BMP(void) {
	lv_obj_t *img = lv_img_create(lv_scr_act());
	lv_img_set_src(img, "S:noel.bmp");

	lv_obj_align(img, LV_ALIGN_CENTER, 0, 0);
	lv_obj_set_size(img, 480, 272);
}

## Screenshot and/or video
![Screenshot 2023-12-15 092316|690x124](upload://wk5LoOjfCjVFS7QsReNQ3YGZZCI.png)
simple test

![Screenshot 2023-12-15 092354|690x388](upload://6ziL1iHb71Ft8n0NMIgoNiMBm1M.png)
main function and while

![Screenshot 2023-12-15 092421|690x267](upload://kwwGauVYx2GwMBpmrIt5FAyhhal.png)
priority

You ask on lvgl with OOT problem corrupt S: drive func when other hw peripheral doing job.
Maybe better is ask on ST forum.
Otherwise lvgl part of your trouble is BMP. Why you use it?? Most uneffective storage format.

Because I’m still not sure if it’s a hardware problem, or maybe I did something wrong somewhere in my code. everything works great but bitmaps only upload very little. but when I turn off any interrupt it runs perfectly.

As for why I use bitmaps instead of other formats, it’s because the paint tool can convert all images in other formats to bitmaps or vice versa and lvgl bitmap conversion library works very well.

Do you have any experience or any solution that can be used instead of interrupts?

Show your interrupt callback codes and …

here it’s



This is when I turn both on

You dont show all, but primary try change

while(1) {
lv_task_handler();
HAL_Delay(5);
if(update) update_Realtime();

seems you update_Realtime() use lv functions to show somethink. This is bad choice …

if (htim->Instance == TIM5) update = true;
1 Like

you need to copy and past the code into the forum in its entirety. not screen shots of the code.

use ``` before and ``` after you coded so the code keeps it’s formatting


like this

```
code goes here
```

One of the things with interrupts is you cannot allocate any memory inside of them. if you are attempting to render a bitmap from inside of an interrupt that is not going to work. I cannot tell if you are doing this from your screen shots which is the reason why I am asking for the complete code. A minimum example that causes the issue you are having is fine.

hello

sorry for the delay, but maybe I solved my problem without using interrupts, I used lv_timer_t * instead of interrupts to work with bitmaps and maybe it worked fine . Anyway still want to perfect using interrupts with lvgl…

I seem to be a stubborn person :)))) here my code https://drive.google.com/file/d/15aJgrBc_dvcCNEhCYThhM3EPPHdyyfTq/view?usp=drive_link

I tried to compress it as small as possible

The only thing you can do in LVGL from inside of an interrupt is to set a flag so that your main loop can execute whatever code you want to have run in LVGL. About the only thing you can directly call from inside the interrupt is lv_tick_inc. and in all honesty you really don’t want to execute a large amount of code from inside of an interrupt anyhow. Best practice is to set some kind of a marker/flag that your main loop will see and let the main loop code handle it.

like what Marian_M said above, right?

Hard to tell. It sounds like that is what they were getting at. Here is an example.

bool do_task = False;

void some_interrupt() {
    if (condition) {
        do_task = True;
    }
}

void loop() {
    if (do_task) {
        do_task = False;
        // LVGL code here
    }
}

no allocation occurs inside of the interrupt this way. do_task has been allocated already and you are only changing its value. Once the interrupt exits and the main loop starts running again it is going to see the new value for do_task and it will run whatever code you wanted to run inside of the interrupt but without it being run from inside of the interrupt.

Now that being said. If you already loaded the bitmap and you have already created an lv_img object to hold that bitmap you can add the hidden flag and remove the hidden flag and no allocation would occur so long as you don’t call lv_task_handler from inside of the interrupt. Since the object has already been made and all you are doing is changing the flag to hide it no memory allocation is going to occur. The downside of doing this is memory use. even when it is not visible it is still going to be consuming memory.

Not sure but maybe you guys have helped me understand a little.

As I understand it, hardware interrupts should only work with simple variables and handler functions should be in the main loop, right?

functions like lv_tick_inc can run on interrupts but lv_task_handler() cannot or at least it is a bad choice.

like this , right?

uint8_t change =0;

void main() {
//...
timer_init();
}

void loop() {

lv_task_handler() ;
delay(5);

if (changer == 1) {

handle_something();
changer = 0;
}
}

void timer_init() {
if ( timer ) {
changer = 1;
}
}

I don’t know if interrupts are the same or equivalent to tasks but I took a look at Operating system and interrupts — LVGL documentation and noticed when lvgl’s functions are run it surrounded by mutex that seem like they don’t want to be bothered by others.

What LVGL means by an operating system is something like freeRTOS, NuttX and Zephyr. These OS’s are actually task managers more than they really should be considered an operating system. They handle when tasks get run. The interrupts they use are software based and not hardware based. Software based interrupts you can allocate memory in because the CPU state data has not changed.

With a hardware interrupt that interrupts the processor so it literally stops running the code it is processing. saves the state of what it was doing and then processes new code given to it by the interrupt. Once the interrupt code is finished running the CPU then loads the saves state from the last process is was running and starts running it where it left off. The new running code has no clue about any new memory being allocated from inside of the interrupt. the changing of what is already allocated is simply changing what is stored in memory so when accessed it is going to see there is a change. New allocations it will not have any clue about and not know what to do with them because they are new. There is no information about it available. it will not even know how to access the memory location for the new allocation…

See what I am getting at? There are things that can be done to mitigate that problem like creating an integer variable where the memory address can be put and the length of the data that is stored. since these would be integers those can be sued to be able to access the data created in an interrupt. It is a lot of additional boiler plate code that is really not needed when running on a microcontroller because you can accomplish the same thing by using a flag/marker and the code gets run from the main loop outside of an interrupt.

interrupts are there for the purpose of being able to stop the processor from doing what it is doing. The code that runs in an interrupts should be really simple and as short as possible. Using interrupts is not an ideal way to run user code. The reason why is it takes time for the CPU to stop, save its state, load the interrupt code, run the interrupt code, and then load the saved state and start processing again. There are a lot of additional steps in there and those steps take time to do. The more often it happens the less time gets spent running actual user code. Interrupts are a way of telling an application that some hardware event has taken place without having to poll the hardware to see if something has changed.

1 Like

No HW int can do anythink what is reqiured ,but in lvgl context , cant call lv func! (exception in docu)

And your example is waste of hw timer because for time managed updates exist more effective code.

Sorry for the late reply, when you said I was wasting the hardware timer, I re-read the lvgl 8 documentation and found an alternative using lv_timer.
Now my program is at least working fine. thanks everyone.
love you, mmar22. :33

static void appmain_event(lv_event_t *e) {

	lv_event_code_t code = lv_event_get_code(e);
//	lv_obj_t *obj = lv_event_get_target(e);
	if (code == LV_EVENT_SCREEN_LOADED) {
		appmain_timer = lv_timer_create((lv_timer_cb_t) appmain_function, 10,
		NULL);

	}
	if (code == LV_EVENT_SCREEN_UNLOADED) {
		lv_timer_del(appmain_timer);

	}
}
static void appmain_function(void) {
	char update_rtc[50] = { 0 };

	sprintf(update_rtc, "%02d/%02d/%04d", rtc_time.date, rtc_time.month,
			rtc_time.year);
	lv_label_set_text(lab_today, update_rtc);

	sprintf(update_rtc, "%02d:%02d", rtc_time.hour, rtc_time.minute);
	lv_label_set_text(lab_clock, update_rtc);

}

Yes perfecto and your code and nature will thank you if you don’t update the date 100 times per second, which doesn’t change all day,
I think that several power plants on the planet already run only on these useless instructions in the code