Description
What MCU/Processor/Board and compiler are you using?
I’m using the RP2040 microcontroller on a custom circuit board. The firmware project was created using the Raspberry Pi Pico extension on VSCode and is using the GNU arm-none-eabi toolchain in combination with CMake.
What do you want to achieve?
I’m currently trying to add the LVGL library to my firmware project, which uses the Raspberry Pico C/C++ SDK and FreeRTOS. Adding the library via CMake makes the references available, but when trying to compile, the LVGL files require the FreeRTOS.h header. This is rather weird, since the FreeRTOS library can be used in the main file…
What have you tried so far?
The project can be compiled with FreeRTOS + no LVGL, so FreeRTOS gets correctly recognized for the main project. I can’t seem to figure out how to enable the FreeRTOS library for the LVGL library.
I fiddled around with the CMake commands to try and add the files one at a time, but it didn’t really work that well (the same errors).
Code to reproduce
The CMakeLists.txt in the top directory level of the project.
# Generated Cmake Pico project file
cmake_minimum_required(VERSION 3.13)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Initialise pico_sdk from installed location
# (note this can come from environment, CMake cache etc)
# == DO NOT EDIT THE FOLLOWING LINES for the Raspberry Pi Pico VS Code Extension to work ==
if(WIN32)
set(USERHOME $ENV{USERPROFILE})
else()
set(USERHOME $ENV{HOME})
endif()
set(sdkVersion 2.2.0)
set(toolchainVersion 14_2_Rel1)
set(picotoolVersion 2.2.0)
set(picoVscode ${USERHOME}/.pico-sdk/cmake/pico-vscode.cmake)
if (EXISTS ${picoVscode})
include(${picoVscode})
endif()
# ====================================================================================
set(PICO_BOARD pico CACHE STRING "Board type")
# Pull in Raspberry Pi Pico SDK (must be before project)
include(pico_sdk_import.cmake)
set(PROJECT time-tracker-firmware)
project(${PROJECT} C CXX ASM)
# Initialise the Raspberry Pi Pico SDK
pico_sdk_init()
add_subdirectory(freertos)
set(LV_BUILD_CONF_PATH src/lv_conf.h)
option(CONFIG_LV_BUILD_EXAMPLES OFF)
option(CONFIG_LV_BUILD_DEMOS OFF)
add_subdirectory(lvgl)
# Add executable. Default name is the project name, version 0.1
add_executable(${PROJECT} src/main.cpp)
pico_set_program_name(${PROJECT} "time-tracker-firmware")
pico_set_program_version(${PROJECT} "0.1")
# Modify the below lines to enable/disable output over UART/USB
pico_enable_stdio_uart(${PROJECT} 0)
pico_enable_stdio_usb(${PROJECT} 1)
# Add the standard library to the build
target_link_libraries(${PROJECT}
pico_stdlib
)
# Add the standard include files to the build
target_include_directories(${PROJECT} PRIVATE
${CMAKE_CURRENT_LIST_DIR}
modules
)
include_directories(${PROJECT}
src
)
# Add any user requested libraries
target_link_libraries(${PROJECT}
freertos
lvgl
hardware_spi
hardware_i2c
)
pico_add_extra_outputs(${PROJECT})
Here’s the main.cpp file:
#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"
#include "message_buffer.h"
#include "queue.h"
#include "semphr.h"
#include "lvgl/lvgl.h"
#include "hardware/i2c.h"
#include "hardware/spi.h"
#include "hardware/uart.h"
#include "pico/stdlib.h"
#include "modules/nina_w13.h"
#include "modules/pcf85363.h"
#include "modules/sdcard.h"
#include "modules/st7789.h"
SemaphoreHandle_t mutex_spi;
SemaphoreHandle_t mutex_i2c;
#define RESOLUTION_HORIZONTAL_PIXEL (240)
#define RESOLUTION_VERTICAL_PIXEL (240)
/* Declare buffer for 1/10 screen size; BYTES_PER_PIXEL will be 2 for RGB565. */
#define BYTES_PER_PIXEL (LV_COLOR_FORMAT_GET_SIZE(LV_COLOR_FORMAT_RGB565))
static uint8_t buf1[RESOLUTION_HORIZONTAL_PIXEL * RESOLUTION_VERTICAL_PIXEL / 10 * BYTES_PER_PIXEL];
void put_px(uint16_t x, uint16_t y, uint16_t pixel) {
}
void my_flush_cb(lv_display_t * display, const lv_area_t * area, uint8_t * px_map)
{
/* The most simple case (also the slowest) to send all rendered pixels to the
* screen one-by-one. `put_px` is just an example. It needs to be implemented by you. */
uint16_t * buf16 = (uint16_t *)px_map; /* Let's say it's a 16 bit (RGB565) display */
int32_t x, y;
for(y = area->y1; y <= area->y2; y++) {
for(x = area->x1; x <= area->x2; x++) {
put_px(x, y, *buf16);
buf16++;
}
}
/* IMPORTANT!!!
* Inform LVGL that flushing is complete so buffer can be modified again. */
lv_display_flush_ready(display);
}
int main() {
stdio_init_all();
lv_init();
lv_tick_set_cb(xTaskGetTickCount);
lv_display_t* display = lv_display_create(RESOLUTION_HORIZONTAL_PIXEL, RESOLUTION_VERTICAL_PIXEL);
lv_display_set_buffers(display, buf1, NULL, sizeof(buf1), LV_DISPLAY_RENDER_MODE_PARTIAL);
lv_display_set_flush_cb(display, my_flush_cb);
mutex_spi = xSemaphoreCreateMutex();
mutex_i2c = xSemaphoreCreateMutex();
vTaskStartScheduler();
for(;;);
}
And lastly here’s the lv_conf.h file
Screenshot and/or video
Although it’s not a screenshot, here’s the CMake Configuration output and build output:
cmake_build_output.txt (18.6 KB)
cmake_config_output.txt (2.1 KB)
The folder structure of the project is as follows (with the folder levels reduced, the LVGL has been cloned from the official git repo):
.
├── CMakeLists.txt
├── docs [directory]
│ └── Part1PhysicalLayerSimplifiedSpecificationVer9.10Fin_20231201.pdf
├── freertos [directory]
│ ├── CMakeLists.txt
│ ├── FreeRTOSConfig.h
│ └── FreeRTOS-Kernel [directory]
├── lvgl [directory]
│ ├── CMakeLists.txt
│ ├── CMakePresets.json
│ ├── component.mk
│ ├── configs [directory]
│ ├── COPYRIGHTS.md
│ ├── demos [directory]
│ ├── docs [directory]
│ ├── env_support [directory]
│ ├── examples [directory]
│ ├── idf_component.yml
│ ├── Kconfig
│ ├── library.json
│ ├── library.properties
│ ├── libs [directory]
│ ├── LICENCE.txt
│ ├── lv_conf_template.h
│ ├── lvgl.h
│ ├── lvgl.mk
│ ├── lvgl.pc.in
│ ├── lvgl_private.h
│ ├── lv_version.h
│ ├── lv_version.h.in
│ ├── README.md
│ ├── SConscript
│ ├── scripts [directory]
│ ├── src [directory]
│ ├── tests [directory]
│ ├── xmls [directory]
│ └── zephyr [directory]
├── modules [directory]
│ ├── CMakeLists.txt
│ ├── ...
├── pico_sdk_import.cmake
├── raspberrypi-swd.cfg
├── README.md
└── src [directory]
├── lv_conf.h
└── main.cpp