Help with Memory Allocation - Teensy 4.1 + LVGL + SquareLine Studio

macardoso

Well-known member
TL : DR: How to move image source code from .c files from RAM1 to PROGMEM/FLASH?

Problem Statement: I need to move a number of static images (189kB) out of RAM1 to avoid over-allocating memory on my project. The images are for on-screen buttons in an LVGL project where the displays are built and exported by SquareLine Studio. Images are .c files where "DMAMEM" and "PROGMEM" are undefined symbols.

Environment:
  • Teensy 4.1
  • Arduino IDE 2.3.8
  • Teensyduino 1.6
  • Teensy Loader 1.6
  • LVGL 9.2.2
  • SquareLine Studio 1.6.0
  • ILI9341_T4 Display driver library 1.6.4
  • Windows 10
Description: Working on a control theory / motion control project using a Teensy as the real time controller. The project is a fusion of high speed motion control, FreeRTOS, analog signal generation, encoder interfaces, RS485 serial comms, and a IPS touchscreen display based on the ILI9341 chipset. I'm using LVGL to display a multi-screen interactive display (think along the lines of a touchscreen on a printer).

I use SquareLine Studio to design, layout, and export the screen LVGL code. SquareLine Studio is configured to export images (used for buttons) as Source Code and each image is exported as raw RGB656 data in a .c file to be included in the arduino sketch folder. I have 13 buttons, each having an image for released and pressed, which totals 189kB of memory use. When I compile, the images are placed in RAM1 as they are exported as "static".

My RAM1 is 43kB overallocated and I need to move this images to (preferably) PROGMEM / Flash or RAM2. Unfortunately SquareLine Studio exports these images as .c (C code) and the keyword symbols "DMAMEM" and "PROGMEM" are undefined in the C language and throw compiler errors. Note, it is highly preferable to not edit the exported files directly as this breaks the SquareLine Studio workflow where you can make a small change and re-export all the files. Any edits to the files will be lost and will need to be made anew each time the files are re-exported. I'll do this if absolutely necessary but I don't want to if at all possible.

SquareLine Studio exports the images with the symbol LV_ATTRIBUTE_MEM_ALIGN which is defined but not set to any value in the LVGL configuration file.

Image Code Example:
C:
// This file was generated by SquareLine Studio
// SquareLine Studio version: SquareLine Studio 1.6.0
// LVGL version: 9.1.0
// Project name: Main Implementation Core

#include "ui.h"

#ifndef LV_ATTRIBUTE_MEM_ALIGN
    #define LV_ATTRIBUTE_MEM_ALIGN
#endif

// IMAGE DATA: assets/ButtonNavRun_UP.png
const LV_ATTRIBUTE_MEM_ALIGN uint8_t ui_img_buttonnavrun_up_png_data[]  = {
    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xAF,0x73,0x75,0xAD,0x18,0xC6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x38,0xC6,0xF4,0x9C,0x8E,0x73,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x00,0x00,0x55,0xAD,0x79,0xCE,0xDB,0xDE,0xFB,0xDE,0xFB,0xDE,0xFB,0xDE,0xDB,0xDE,0xBA,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x9A,0xD6,0x79,0xCE,0x38,0xC6,0xF7,0xBD,0xB6,0xB5,0x75,0xAD,0x34,0xA5,0xD3,0x9C,0x10,0x84,0x00,0x00,0x00,0x00,0x00,0x00,
    0x00,0x00,0x00,0x00,0x96,0xB5,0x38,0xC6,0xBA,..... Data continues here

What I've Tried:
  • Manually added PROGMEM to each image .c file
    • Generated compiler errors as PROGMEM is not defined in C code
  • Manually added DMAMEM to each image .c file
    • Generated compiler errors as DMAMEM is not defined in C code
  • Defined LV_ATTRIBUTE_MEM_ALIGN as PROGMEM in LVGL configuration
    • Generated compiler errors as PROGMEM is not defined in C code
  • Defined LV_ATTRIBUTE_MEM_ALIGN as __attribute__((section(".rodata"))) in LVGL configuration
    • Compiles but images placed in RAM 1
  • Looked into seeing if SquareLine Studio can export as C++ instead of C
    • Have not been successful in finding this as an option
My Ask: How do I move these images to PROGMEM with minimal interference with the SquareLine Studio raw export.

Thanks so much for your thoughts!
 
Try simply renaming your ".c" files to ".cpp" in addition to manually adding PROGMEM or DMAMEM.

C++ is a superset of C, so in most cases C files can simply be named to be C++ file.
 
  • Defined LV_ATTRIBUTE_MEM_ALIGN as __attribute__((section(".rodata"))) in LVGL configuration
    • Compiles but images placed in RAM 1
You had the right idea here, but it should be __attribute__((section(".progmem"))) instead.
Otherwise just #include <avr/pgmspace.h> to make the PROGMEM keyword work.
 
You had the right idea here, but it should be __attribute__((section(".progmem"))) instead.
Otherwise just #include <avr/pgmspace.h> to make the PROGMEM keyword work.
Whew! God bless you. That was it. This lets me keep the Squareline export completely unmodified. Everything compiled and didn’t crash at runtime with dynamic allocation. Only have 44k left to play with in RAM1.
 
The online LVGL image converter adds more attributes to large constant arrays:
C:
#ifndef LV_ATTRIBUTE_IMAGE_IMG_NAME
#define LV_ATTRIBUTE_IMAGE_IMG_NAME
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMAGE_IMG_NAME uint8_t image_name_map[] = {
    ...
        
    }

LV_ATTRIBUTE_LARGE_CONST can be defined in lv_conf.h as __attribute__((section(".progmem"))) and will be automatically added to all converted image files or large font arrays.
 
The online LVGL image converter adds more attributes to large constant arrays:
C:
#ifndef LV_ATTRIBUTE_IMAGE_IMG_NAME
#define LV_ATTRIBUTE_IMAGE_IMG_NAME
#endif
const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMAGE_IMG_NAME uint8_t image_name_map[] = {
    ...
       
    }

LV_ATTRIBUTE_LARGE_CONST can be defined in lv_conf.h as __attribute__((section(".progmem"))) and will be automatically added to all converted image files or large font arrays.
Didn't know that existed - thank you. Brand new to LVGL. Big learning curve but it is very cool to see my project working and interactive on a touchscreen.
 
Back
Top