You can use lv_task
lv_task_create(time_refresh, 1000, LV_TASK_PRIO_MID, (void *)(clock));
You can use lv_task
lv_task_create(time_refresh, 1000, LV_TASK_PRIO_MID, (void *)(clock));
I face a memory leak problem
Are you calling lv_label_create
each time as well? Normally, lv_label_set_text
shouldn’t cause memory leaks.
call periodicity in a timer
You must never call LittlevGL functions from an interrupt or another thread unless you guarantee lv_task_handler
is not executing at the same time. The only exception to that rule is lv_tick_inc
, which is designed to handle the concurrency.
HI, I use the demo from github esp32_ili9341
To make a diagnosis of memory consumption, I add memory print periodically.
I enable LV_MEM_CUSTOM, and define a function lv_malloc alloc memory from external RAM.
Then I create a timer to deal lv_task_handler every 5 ms but it’s weird when lv_task_handler was called 2 times later, the memory will consume 100K ram too much.
Don’t know where that 100k+ memory were alloced.
void app_main()
{
print_memory();
lv_init();
print_memory();
disp_spi_init();
ili9341_init();
print_memory();
lv_disp_drv_t disp;
lv_disp_drv_init(&disp);
disp.disp_flush = ili9341_flush;
disp.disp_fill = ili9341_fill;
lv_disp_drv_register(&disp);
print_memory();
esp_register_freertos_tick_hook(lv_tick_task);
print_memory();
helloworld();
print_memory();
lv_timer_init();
print_memory();
vTaskDelete(NULL);
}
static void helloworld(void)
{
lv_obj_t * label1 = lv_label_create(lv_scr_act(), NULL);
lv_label_set_text(label1, "Hello world!");
lv_obj_align(label1, NULL, LV_ALIGN_CENTER, 0, 0);
}
static void print_memory(void)
{
printf("Memory,total:%d, inter:%d, spram:%d, Dram:%d, %d\r\n", esp_get_free_heap_size(),
heap_caps_get_free_size(MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT),
heap_caps_get_free_size(MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT),
heap_caps_get_free_size(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT), print_cnt++);
}
Can you print the allocated sizes in your lv_malloc
?
sure, every malloc I have print the size, address.
Memory,total:4399060, inter:366984, spram:4116888, Dram:295740, 0
lv_mem_alloc, size:76, addr:3f812e60
lv_mem_alloc, size:28, addr:3f812eb4
lv_mem_alloc, size:28, addr:3f812ed8
lv_mem_alloc, size:68, addr:3f812efc
Info: Screen create ready (/workshop/audio/experiment/esp32_ili9341/lvgl/lv_core/lv_obj.c #196)
lv_mem_alloc, size:68, addr:3f812f48
Info: Screen create ready (/workshop/audio/experiment/esp32_ili9341/lvgl/lv_core/lv_obj.c #196)
lv_mem_alloc, size:68, addr:3f812f94
Info: Screen create ready (/workshop/audio/experiment/esp32_ili9341/lvgl/lv_core/lv_obj.c #196)
Info: lv_init ready (/workshop/audio/experiment/esp32_ili9341/lvgl/lv_core/lv_obj.c #115)
Memory,total:4398500, inter:366808, spram:4116504, Dram:295564, 1
ILI9341 initialization.
Enable backlight.
Memory,total:4398136, inter:367296, spram:4116504, Dram:296052, 2
lv_mem_alloc, size:28, addr:3f812fe0
Memory,total:4398100, inter:367296, spram:4116468, Dram:296052, 3
Memory,total:4398100, inter:367296, spram:4116468, Dram:296052, 4
lv_mem_alloc, size:68, addr:3f813004
lv_mem_alloc, size:28, addr:3f813050
lv_mem_alloc, size:8, addr:3f813074
Info: label created (/workshop/audio/experiment/esp32_ili9341/lvgl/lv_objx/lv_label.c #133)
lv_mem_alloc, size:16, addr:3f813074
Memory,total:4397964, inter:367296, spram:4116332, Dram:296052, 5
Memory,total:4244312, inter:213644, spram:4116332, Dram:142400, 6
Memory,total:4244312, inter:213644, spram:4116332, Dram:142400, 7
Memory,total:4244312, inter:213644, spram:4116332, Dram:142400, 8
Memory,total:4244312, inter:213644, spram:4116332, Dram:142400, 9
Memory,total:4244312, inter:213644, spram:4116332, Dram:142400, 10
total 484 = 76+28+28+68+68+68+28+68+28+8+16
This does not match the memory which were alloced, I want to trace them. Only display hellworld could not need that huge memory.
PS,I use double vdb bufer.
#define LV_VDB_ADR 0X3FBED400
#define LV_VDB2_ADR 0X3FBF6A00
I also add print at lv_mem_alloc.c , here.
#if LV_ENABLE_GC == 1 /*gc must not include header*/
alloc = LV_MEM_CUSTOM_ALLOC(size);
#else /* LV_ENABLE_GC */
/*Allocate a header too to store the size*/
alloc = LV_MEM_CUSTOM_ALLOC(size + sizeof(lv_mem_header_t));
if (alloc != NULL) {
((lv_mem_ent_t *) alloc)->header.d_size = size;
((lv_mem_ent_t *) alloc)->header.used = 1;
alloc = &((lv_mem_ent_t *) alloc)->first_data;
}
printf("%s, size:%d, addr:%x\r\n", __func__, size, (uint32_t)alloc);
#endif /* LV_ENABLE_GC */
#endif /* LV_MEM_CUSTOM */
The problem is I can’t trace the memory here in the picture. It not malloc from my function(lv_mem) , please give a advice.
Please ignore above two post, here is real.
my_lv_malloc is my malloc function.
lv_mem_alloc is the lvgl malloc function.
Memory,total:4399060, inter:366984, spram:4116888, Dram:295740, 0
my_lv_malloc, size:80, addr:3f812e5c
lv_mem_alloc, size:76, addr:3f812e60
my_lv_malloc, size:32, addr:3f812eb0
lv_mem_alloc, size:28, addr:3f812eb4
my_lv_malloc, size:32, addr:3f812ed4
lv_mem_alloc, size:28, addr:3f812ed8
my_lv_malloc, size:72, addr:3f812ef8
lv_mem_alloc, size:68, addr:3f812efc
Info: Screen create ready (/workshop/audio/experiment/esp32_ili9341/lvgl/lv_core/lv_obj.c #196)
my_lv_malloc, size:72, addr:3f812f44
lv_mem_alloc, size:68, addr:3f812f48
Info: Screen create ready (/workshop/audio/experiment/esp32_ili9341/lvgl/lv_core/lv_obj.c #196)
my_lv_malloc, size:72, addr:3f812f90
lv_mem_alloc, size:68, addr:3f812f94
Info: Screen create ready (/workshop/audio/experiment/esp32_ili9341/lvgl/lv_core/lv_obj.c #196)
Info: lv_init ready (/workshop/audio/experiment/esp32_ili9341/lvgl/lv_core/lv_obj.c #115)
Memory,total:4398500, inter:366808, spram:4116504, Dram:295564, 1
ILI9341 initialization.
Enable backlight.
Memory,total:4398136, inter:367296, spram:4116504, Dram:296052, 2
my_lv_malloc, size:32, addr:3f812fdc
lv_mem_alloc, size:28, addr:3f812fe0
Memory,total:4398100, inter:367296, spram:4116468, Dram:296052, 3
Memory,total:4398100, inter:367296, spram:4116468, Dram:296052, 4
my_lv_malloc, size:72, addr:3f813000
lv_mem_alloc, size:68, addr:3f813004
my_lv_malloc, size:32, addr:3f81304c
lv_mem_alloc, size:28, addr:3f813050
my_lv_malloc, size:12, addr:3f813070
lv_mem_alloc, size:8, addr:3f813074
Info: label created (/workshop/audio/experiment/esp32_ili9341/lvgl/lv_objx/lv_label.c #133)
my_lv_malloc, size:20, addr:3f813070
lv_mem_alloc, size:16, addr:3f813074
Memory,total:4397964, inter:367296, spram:4116332, Dram:296052, 5
Memory,total:4244312, inter:213644, spram:4116332, Dram:142400, 6
Memory,total:4244312, inter:213644, spram:4116332, Dram:142400, 7
Memory,total:4244312, inter:213644, spram:4116332, Dram:142400, 8
Memory,total:4244312, inter:213644, spram:4116332, Dram:142400, 9
Memory,total:4244312, inter:213644, spram:4116332, Dram:142400, 10
I find when call lv_task_handler(); in a timer,after twice , then memory droped.
here is:
Memory,total:4397964, inter:367296, spram:4116332, Dram:296052, 5
Memory,total:4244312, inter:213644, spram:4116332, Dram:142400, 6
If annotation lv_task_handler , then memory print result is good.
Memory,total:4399076, inter:367004, spram:4116888, Dram:295756, 0
lv_mem_alloc, size:76, addr:3f812e60
lv_mem_alloc, size:28, addr:3f812eb4
lv_mem_alloc, size:28, addr:3f812ed8
lv_mem_alloc, size:68, addr:3f812efc
Info: Screen create ready (/workshop/audio/experiment/esp32_ili9341/lvgl/lv_core/lv_obj.c #196)
lv_mem_alloc, size:68, addr:3f812f48
Info: Screen create ready (/workshop/audio/experiment/esp32_ili9341/lvgl/lv_core/lv_obj.c #196)
lv_mem_alloc, size:68, addr:3f812f94
Info: Screen create ready (/workshop/audio/experiment/esp32_ili9341/lvgl/lv_core/lv_obj.c #196)
Info: lv_init ready (/workshop/audio/experiment/esp32_ili9341/lvgl/lv_core/lv_obj.c #115)
Memory,total:4398516, inter:366828, spram:4116504, Dram:295580, 1
ILI9341 initialization.
Enable backlight.
Memory,total:4398152, inter:367316, spram:4116504, Dram:296068, 2
lv_mem_alloc, size:28, addr:3f812fe0
Memory,total:4398116, inter:367316, spram:4116468, Dram:296068, 3
Memory,total:4398116, inter:367316, spram:4116468, Dram:296068, 4
lv_mem_alloc, size:68, addr:3f813004
lv_mem_alloc, size:28, addr:3f813050
lv_mem_alloc, size:8, addr:3f813074
Info: label created (/workshop/audio/experiment/esp32_ili9341/lvgl/lv_objx/lv_label.c #133)
lv_mem_alloc, size:16, addr:3f813074
Memory,total:4397980, inter:367316, spram:4116332, Dram:296068, 5
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 6
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 7
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 8
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 9
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 10
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 11
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 12
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 13
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 14
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 15
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 16
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 17
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 18
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 19
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 20
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 21
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 22
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 23
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 24
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 25
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 26
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 27
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 28
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 29
Memory,total:4397944, inter:367280, spram:4116332, Dram:296032, 30
Is there anything else that uses the external RAM? Maybe something overwrites dynamic memory area.
What if you call lv_task_handler
in a task? BTW, why do you need to do it in a timer?
I think lv_task_handler() should be called periodicity,so I set it into a timer, anyway or it in a task while(1) loop is the same. right?
while(1) {
vTaskDelay(1);
lv_task_handler();
}
Please make sure you are not calling lv_task_handler
concurrently with any function besides lv_tick_inc
.
What does that means? My code is simple it’s the github demo( littlevgl/ esp32_ili9341), Do we have test the external RAM usage?
You means do not call lv_task_handler & lv_tick_inc function at the same time?
You cannot call them in the same loop:
/* WRONG */
while(1)
{
lv_task_handler();
lv_tick_inc(10);
sleep_ms(10);
}
But you can use an interrupt/timer/different thread:
void timer_interrupt(void)
{
lv_tick_inc(10); /* if the timer fires every 10 milliseconds */
}
. . .
while(1)
{
lv_task_handler();
sleep_ms(10);
}
I remember we already have found that several times that it can cause issues but I don’t know why. Do you have any ideas? It can mess up timing but should work in theory.
I can’t remember the exact symptoms either. I think it had something to do with input not being received.
Hmm, that would make sense. However, it shouldn’t cause crash.
It should be fine.
I’ve never tried lv_task_handler()
with a timer but tried with a task. They should be same but who knows… So at the end of app_main
please try:
while(1)
{
lv_task_handler();
vTaskDelay(1);
}
I have find the reason, here.
spi_bus_config_t buscfg = {
.miso_io_num = -1,
.mosi_io_num = DISP_SPI_MOSI,
.sclk_io_num = DISP_SPI_CLK,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = LV_VDB_SIZE * 2,
};
.max_transfer_sz = LV_VDB_SIZE * 2,
When first call spi_device_queue_trans(), It will malloc TX & RX DMA buffer(size = max_transfer_sz), will cost 150K internal DRAM.
Ah, glad to hear that you found it!