Hello,
I am using LVGL v8.4.
So far I had been able to use external memory and LVGL simultaeousely, for example maintaining images in external memory and addressing the LVGL to use the buffer in external memory for display.
The point I was wondering is that how can I use LVGL making it use external memory as main memory, for example to load widgets from external memory, not the main memory of processor.
Any news? Any response?
Hi,
In v8 you can set set any custom address for LVGL’s memory here:lvgl/lv_conf_template.h at release/v8.4 · lvgl/lvgl · GitHub
How should v9.1 be configured?
It seems that there is no LV_MEM_CUSTOM_ALLOC
like in v.8.x.
Thank you.
If you are using STM32, you can use memory mapped mode to run your application from the external flash.
First, you need to build external loader to flash the external flash.
I have used this code
/*: use custom malloc/free, 0: use the built-in lv_mem_alloc() and lv_mem_free()*/
#define LV_MEM_CUSTOM 0
#if LV_MEM_CUSTOM == 0
/*Size of the memory available for lv_mem_alloc() in bytes (>= 2kB)*/
#define LV_MEM_SIZE (100U * 1024U) /*[bytes]*/
/*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
#define LV_MEM_ADR 0xD02AF800
/*0: unused*/
/*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/
#if LV_MEM_ADR == 0
#undef LV_MEM_POOL_INCLUDE
#undef LV_MEM_POOL_ALLOC
#endif
#else /*LV_MEM_CUSTOM*/
#define LV_MEM_CUSTOM_INCLUDE <stdlib.h> /*Header for the dynamic memory function*/
#define LV_MEM_CUSTOM_ALLOC malloc
#define LV_MEM_CUSTOM_FREE free
#define LV_MEM_CUSTOM_REALLOC realloc
#endif /*LV_MEM_CUSTOM*/
But this code doesn’t work. I can access those address, by different methods like,
HAL_SDRAM_Write_8b(hsdram, pAddress, pSrcBuffer, BufferSize);
or
uint8_t* test = (uint8_t *)0xD02AF800;
*test = 0xff;
Please try a more intensive test. E.g.
uint32_t * adr = pAddress;
//In loop fill the RAM with 1, 2, 3, 4, ...
//Read back the result in a loop
Tested that and that’s working, this is what I check in the beginning of the project creation.
Can you try this?
lv_init();
uint8_t *p = lv_malloc(4);
p[0] = 0;
p[1] = 1;
p[2] = 2;
p[3] = 3;
if(p[0] == 0 && p[1] == 1 && p[2] == 2 && p[3] = 3) printf("ok\n");
This part returned ok to me, but the first object creation, with external memory, that is
window->screen = lv_obj_create(NULL);
result in hardfault error
Here is the log I get
[Info] (0.000, +0) lv_init: begin (in lv_obj.c line #106)
[Info] (0.000, +0) lv_obj_create: begin (in lv_obj.c line #215)
[Info] (0.000, +0) lv_obj_create: begin (in lv_obj.c line #215)
[Info] (0.000, +0) lv_obj_create: begin (in lv_obj.c line #215)
ok
[Info] (0.021, +21) lv_obj_update_layout: Layout update begin (in lv_obj_pos.c line #314)
[Info] (0.022, +1) lv_obj_update_layout: Layout update begin (in lv_obj_pos.c line #314)
[Info] (0.023, +1) lv_obj_update_layout: Layout update begin (in lv_obj_pos.c line #314)
[Info] (0.032, +9) lv_obj_create: begin (in lv_obj.c line #215)
[Info] (0.037, +5) lv_img_create: begin (in lv_img.c line #60)
[Info] (0.040, +3) lv_label_create: begin (in lv_label.c line #75)
[Info] (0.045, +5) lv_label_create: begin (in lv_label.c line #75)
[Info] (0.050, +5) lv_label_create: begin (in lv_label.c line #75)
[Info] (0.052, +2) lv_obj_update_layout: Layout update begin (in lv_obj_pos.c line #314)
[HardFault]
R0 = d02afe50
R1 = d02afe50
R2 = 001ffffa
R3 = 02184210
R12 = 00000011
LR [R14] = 0802939f - Subroutine Call return address
PC [R15] = 080293ae - Program Counter
PSR = 01000000
BFAR = 001ffffe - Bus Fault SR/Address causing bus fault
CFSR = 00008200 - Config. Fault SR
HFSR = 40000000 - Hard Fault SR
:FORCED, Bus fault/Memory management fault/usage fault
DFSR = 00000000 - Debug Fault SR
MMAR = 001ffffe - Memory Manage Address R
AFSR = 00000000 - Auxilirary Fault SR
SCB->SHCSR= 00000000 - System Handler Control and State R (exception)
I’m using stm32 chips with STM32CUBEIDE and here is the workaround I have found.
uint8_t LVGL_buffer[1024*200] __attribute__((section("ExtRamSection.NOLOAD")));
#define LV_MEM_ADR 0xD011574c /*0: unused*/
Now my display is working, but for those who wants to use this workaround,
:::::::::::::::::::::::::::::::::WARNING ::::::::::::::::::::::::::::::
You’re using this workaround at the potential cost that your main display likely shares the same external RAM, and now your LVGL widget RAM is also in that same memory. This increases complexity due to the RAM’s access time.
It’s great that you have found a solution! Thanks for sharing it!