Adding LVGL to STM32 Makefile

Description

Hi all!

I’m building a radio with lcd. For interface I’d like to use LVGL.

I’ve generated the makefile for STM32F103C8T6 via Stm32CubeIde, now I’d like to add LVGL to the project.

I’ve cloned the library, according to the porting gyde, added the next lines to the almost top of my makefile:


LVGL_DIR_NAME ?= lvgl #The name of the lvgl folder (change this if you have renamed it)

LVGL_DIR ?= ${shell pwd} #The path where the lvgl folder is

include $(LVGL_DIR)/$(LVGL_DIR_NAME)/lvgl.mk

To the main file I’ve added lv_init() and lv_tick_inc() functions, but unfortunately I’ve met the next error while trying to build:


/opt/gcc-arm-none-eabi-10-2020-q4-major/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld: build/main.o: in function `main':

/mnt/d/Work/radiodevice/Src/main.c:29: undefined reference to `lv_init'

/opt/gcc-arm-none-eabi-10-2020-q4-major/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld: /mnt/d/Work/radiodevice/Src/main.c:33: undefined reference to `lv_tick_inc'

collect2: error: ld returned 1 exit status

make: *** [Makefile:131: build/radiodevice.elf] Error 1

Does anyone tried to add LVGL to the makefile and tried to build it? Maybe, any workaround?

Could anyone help with advise, or etc.?

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

STM32F103C8T6

arm-none-eabi-gcc (GNU Arm Embedded Toolchain 10-2020-q4-major) 10.2.1 20201103 (release)

Copyright (C) 2020 Free Software Foundation, Inc.

This is free software; see the source for copying conditions. There is NO

warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

What do you want to achieve?

Successfully ported LVGL to my project.

What have you tried so far?

I’ve tried to look forum for similar answers,

direct building of lvgl and then adding it to project (no success for stm, but seems like work-able workaround for Linux.),

Tried to find similar projects on Github (but no makefile projects found :frowning: )

Code to reproduce

My project has the next structure:

/Drivers - HAL and CMSIS folder;

/Inc - Headers;

/Src - Source files;

/lvgl - lvgl library, checked branches v8.3 and master;

/lv_conf.h;

/Makefile.

My main.c:


#include "main.h"

#include "stm32f1xx_hal.h"

#include "i2c.h"

#include "spi.h"

#include "gpio.h"

#include "gc9a01.h"

#include "lvgl.h"

int _write(int file, char *ptr, int len)

{

/* Implement your write code here, this is used by puts and printf for example */

int i=0;

for(i=0 ; i<len ; i++)

ITM_SendChar((*ptr++));

return len;

}

//void SystemClock_Config(void);

int main(void)

{

HAL_Init();

SystemClock_Config();

//GPIO_Init();

//I2C2_Init();

// SPI1_Init();

//GC9A01_Init();

lv_init();

while (1)

{

HAL_Delay(10);

lv_tick_inc(10);

}

}

My makefile:


TARGET = radiodevice

DEBUG = 1

OPT = -Og

LVGL_DIR_NAME ?= lvgl

LVGL_DIR ?= ${shell pwd}

include $(LVGL_DIR)/$(LVGL_DIR_NAME)/lvgl.mk

# Build path

BUILD_DIR = build

# C sources

C_SOURCES = \

Src/main.c \

Src/stm32f1xx_it.c \

Src/stm32f1xx_hal_msp.c \

Src/system_stm32f1xx.c \

Src/gpio.c \

Src/i2c.c \

Src/spi.c \

Src/gc9a01.c \

Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c \

Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c \

Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c \

Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c \

Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c \

Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c \

Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c \

Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c \

Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c \

Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c \

Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c \

Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c \

Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi.c \

Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c \

Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c

# ASM sources

ASM_SOURCES = \

startup_stm32f103xb.s

#######################################

# binaries

#######################################

PREFIX = arm-none-eabi-

# The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx)

# either it can be added to the PATH environment variable.

ifdef GCC_PATH

CC = $(GCC_PATH)/$(PREFIX)gcc

AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp

CP = $(GCC_PATH)/$(PREFIX)objcopy

SZ = $(GCC_PATH)/$(PREFIX)size

else

CC = $(PREFIX)gcc

AS = $(PREFIX)gcc -x assembler-with-cpp

CP = $(PREFIX)objcopy

SZ = $(PREFIX)size

endif

HEX = $(CP) -O ihex

BIN = $(CP) -O binary -S

#######################################

# CFLAGS

#######################################

# cpu

CPU = -mcpu=cortex-m3

MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)

# C defines

C_DEFS = \

-DUSE_HAL_DRIVER \

-DSTM32F103xB

# C includes

C_INCLUDES = \

-IInc \

-Ilvgl \

-IDrivers/STM32F1xx_HAL_Driver/Inc \

-IDrivers/STM32F1xx_HAL_Driver/Inc/Legacy \

-IDrivers/CMSIS/Device/ST/STM32F1xx/Include \

-IDrivers/CMSIS/Include

# compile gcc flags

ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections

CFLAGS += $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections

ifeq ($(DEBUG), 1)

CFLAGS += -g -gdwarf-2

endif

# Generate dependency information

CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"

# link script

LDSCRIPT = STM32F103C8Tx_FLASH.ld

# libraries

LIBS = -lc -lm -lnosys

LIBDIR =

LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections

# default action: build all

all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin

#######################################

# build the application

#######################################

# list of objects

OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))

LVGL_OBS=$(CSRCS:.c=.o)

vpath %.c $(sort $(dir $(C_SOURCES)))

# list of ASM program objects

OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))

vpath %.s $(sort $(dir $(ASM_SOURCES)))

$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)

$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@

$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)

$(AS) -c $(CFLAGS) $< -o $@

$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile

$(CC) $(OBJECTS) $(LDFLAGS) -o $@

$(SZ) $@

$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)

$(HEX) $< $@

$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)

$(BIN) $< $@

$(BUILD_DIR):

mkdir $@

clean:

-rm -fR $(BUILD_DIR)

-include $(wildcard $(BUILD_DIR)/*.d)

Screenshot and/or video

If possible, add screenshots and/or videos about the current state.

Sorry, I resolved the issue.

My makefile now is:

TARGET = radiodevice

DEBUG = 0
OPT = -O3

LVGL_DIR_NAME ?= lvgl
LVGL_DIR ?= ${shell pwd}
LVGL_PATH = $(LVGL_DIR)/$(LVGL_DIR_NAME)
include $(LVGL_DIR)/$(LVGL_DIR_NAME)/lvgl.mk

# Build path
BUILD_DIR = build

# C sources
C_SOURCES =  \
Src/main.c \
Src/stm32f1xx_it.c \
Src/stm32f1xx_hal_msp.c \
Src/system_stm32f1xx.c \
Src/gpio.c \
Src/i2c.c \
Src/spi.c \
Src/gc9a01.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_spi.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c

C_SOURCES += $(CSRCS)

# ASM sources
ASM_SOURCES =  \
startup_stm32f103xb.s


#######################################
# binaries
#######################################
PREFIX = arm-none-eabi-
# The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx)
# either it can be added to the PATH environment variable.
ifdef GCC_PATH
CC = $(GCC_PATH)/$(PREFIX)gcc
AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp
CP = $(GCC_PATH)/$(PREFIX)objcopy
SZ = $(GCC_PATH)/$(PREFIX)size
else
CC = $(PREFIX)gcc
AS = $(PREFIX)gcc -x assembler-with-cpp
CP = $(PREFIX)objcopy
SZ = $(PREFIX)size
endif
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S
 
#######################################
# CFLAGS
#######################################
# cpu
CPU = -mcpu=cortex-m3

MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)

# C defines
C_DEFS =  \
-DUSE_HAL_DRIVER \
-DSTM32F103xB

# C includes
C_INCLUDES =  \
-IInc \
-Ilvgl \
-IDrivers/STM32F1xx_HAL_Driver/Inc \
-IDrivers/STM32F1xx_HAL_Driver/Inc/Legacy \
-IDrivers/CMSIS/Device/ST/STM32F1xx/Include \
-IDrivers/CMSIS/Include

# compile gcc flags
ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections

CFLAGS += $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections -flto

ifeq ($(DEBUG), 1)
CFLAGS += -g -gdwarf-2
endif


# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"

# link script
LDSCRIPT = STM32F103C8Tx_FLASH.ld

# libraries
LIBS = -lc -lm -lnosys 
LIBDIR = 
LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections


# default action: build all
all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin

#######################################
# build the application
#######################################
# list of objects
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))

vpath %.c $(sort $(dir $(C_SOURCES)))

# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
vpath %.s $(sort $(dir $(ASM_SOURCES)))

$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) 
	$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@

$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
	$(AS) -c $(CFLAGS) $< -o $@

$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
	$(CC) $(OBJECTS) $(LDFLAGS) -o $@
	$(SZ) $@

$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
	$(HEX) $< $@
	
$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
	$(BIN) $< $@

$(BUILD_DIR):
	mkdir $@

clean:
	-rm -fR $(BUILD_DIR)

-include $(wildcard $(BUILD_DIR)/*.d)

Please, note that C_SOURCES += $(CSRCS) is added. In my case it adds all .c source files, compiles them and places to the build folder.

Anyway build fails with the next issue:
lto-wrapper: warning: Options to Xassembler do not match: -alms=build/main.lst, -alms=build/stm32f1xx_it.lst, dropping all -Xassembler and -Wa options.
/opt/gcc-arm-none-eabi-10-2020-q4-major/bin/…/lib/gcc/arm-none-eabi/10.2.1/…/…/…/…/arm-none-eabi/bin/ld: build/radiodevice.elf section .text' will not fit in region FLASH’
/opt/gcc-arm-none-eabi-10-2020-q4-major/bin/…/lib/gcc/arm-none-eabi/10.2.1/…/…/…/…/arm-none-eabi/bin/ld: build/radiodevice.elf section .bss' will not fit in region RAM’
/opt/gcc-arm-none-eabi-10-2020-q4-major/bin/…/lib/gcc/arm-none-eabi/10.2.1/…/…/…/…/arm-none-eabi/bin/ld: region RAM' overflowed by 243968 bytes /opt/gcc-arm-none-eabi-10-2020-q4-major/bin/../lib/gcc/arm-none-eabi/10.2.1/../../../../arm-none-eabi/bin/ld: region FLASH’ overflowed by 53584 bytes
collect2: error: ld returned 1 exit status

But I have everything enabled in lvgl_conf.h file, and I use stm32f103c8t6 with only 64 kB flash and 20 kb ram, so this fail was expected and my config needs to be fixed.