Найти тему
Project A.L.T.

Ошибка при компиляции проекта dram0.bss will not fit in region dram0_0_seg. Что это и как с этим бороться?

Лого
Лого

Начал делать для дисплея Sunton ESP32 большой LVGL проект и через какое -то время столкнулся с такой вот ошибкой компилятора:

dram0.bss' will not fit in region dram0_0_seg

В целом понятно. Размер блока данных (BSS) или dram0.bss превышает размер доступной памяти (region), в данном случае - dram0_0_seg.

LVGL библиотека большая. Подозреваю, что за время своего существования обросла множеством костылей и оптимизация там явно не самая лучшая. Если для различных демок и прочего ресурсов еще хватает, то в сложных проектах, с подключением различных дополнительных библиотек, которые не факт, что тоже идеально оптимизированы вполне может возникнуть такая ошибка. Памяти на все попросту не хватает.

Напрашивается логичное решение. Либо увеличить доступную память, либо изменить размеры сегментов памяти, чтобы вместить в них нужные данные. Ну или вручную раскидать данные по сегментам, исходя из их размеров.

В Arduino проектах выделением памяти занимается стандартная функция maloc(), являющаяся частью библиотеки <stdlib.h>

В LVGL вместо неё используется встроенная функция lv_mem_alloc().

В целом для решения проблемы можно перенести часть данных в PSRAM память, с которой lv_mem_aloc() работать не умеет.

Поэтому будем использовать функцию распределения памяти из ядра ESP32 для Arduino IDE. Для этого в lv_conf.h необходимо внести следующие изменения:

/*=========================
MEMORY SETTINGS
*=========================*/
/*1: 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 (128U * 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 1 /*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 == 1
#define LV_MEM_POOL_INCLUDE <esp32-hal-psram.h>
#define LV_MEM_POOL_ALLOC ps_malloc
#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*/

В целом этого вполне достаточно для решения проблемы, но моя версия дисплея Sunton не имеет PSRAM памяти.

Также можно поиграться с этим параметром.

#define LV_MEM_SIZE (328U * 1024U)          /*[bytes]*/

Меняем первую цифру на объем DRAM памяти ESP32 в кб. Он равен 328 кб так что его и пишем вместо первой цифры.

Или можно просто доверить работу с памятью стандартному maloc() из stdlib.h, который с этим справляется немного лучше.

В этом случае в lv_conf.h меняем один параметр:

#define LV_MEM_CUSTOM 1

В этом случае все работает без каких либо проблем.