Description
I’m trying to use LVGL with the Raspberry Pi Pico but with no luck. I’m using a ER-TFTM050A2-3-3661 display from EastRising, the display is 800x480 with a RA8875 controller driven via SPI. I wrote a custom driver using the Adafruit one as a template; my initialization process works fine, however when I try to run LVGL, it gets stuck on the malloc process of creating a display and the pico launches a SIGTRAP signal,when i debug it, see the attached screenshot. It seems like a memory related problem.
What MCU/Processor/Board and compiler are you using?
I’m using pico-sdk latest version 2.0.0 on PopOS, Pi pico is version 1, the one with RP2040 chip. I’m using the latest LVGL version 9.2.2.
What do you want to achieve?
What have you tried so far?
I’ve tried to reduce the display buffer size, change the avaible memory for lv_malloc.
I’m using a 32kB size of size avaible to malloc and a 19kB single buffer for the display.
Code to reproduce
#include <stdio.h>
#include "pico/stdlib.h"
#include "RA8875.h"
#include "GSL1680.h"
#include "lvgl.h"
#include "hardware/spi.h"
#include "pico/rand.h"
#define PIN_CS 26
#define PIN_RST 20
#define PIN_CTP_WAKE 21
#define PIN_CTP_INT 22
#define TICK_MS 5
#define HOR_RES 800
#define VER_RES 480
static GSL1680 touch = GSL1680(true);
static RA8875 tft = RA8875(PIN_CS,PIN_RST);
static lv_draw_buf_t *draw_buf1;
static lv_display_t * display1 = lv_display_create(HOR_RES, VER_RES);
static lv_indev_t * indev = lv_indev_create();
bool repeating_tick_inc(__unused struct repeating_timer *t) {
lv_tick_inc(TICK_MS);
return true;
}
static uint32_t get_elapsed_ms(){
return to_ms_since_boot(get_absolute_time());
}
void raio_display_flush(lv_display_t * display, const lv_area_t * area, uint8_t * px_map){
uint16_t * buf16 = (uint16_t *)px_map;
uint32_t w = (area->x2 - area->x1 +1);
uint32_t h = (area->y2 - area->y1 +1);
tft.setActiveWindow(area->x1, area->x2, area->y1, area->y2);
tft.writeCommand(RA8875_MRWC);
gpio_put(PIN_CS,0);
uint8_t cmd = RA8875_DATAWRITE;
spi_write_blocking(spi0,&cmd,1);
for(uint32_t i = 0; i < w*h; i++){
tft.pushColor(*buf16);
buf16++;
}
gpio_put(PIN_CS,1);
lv_disp_flush_ready(display1);
}
void touchpad_read(lv_indev_t * indev, lv_indev_data_t * data){
static uint16_t last_x = 0, last_y = 0;
bool valid = false;
uint16_t touchX = last_x, touchY = last_y;
uint8_t touched = touch.data_read();
touchX = touch.readFingerX(1);
touchY = touch.readFingerY(1);
if(touched){
valid = true;
last_x = touchX;
last_y = touchY;
}
data->point.x = touchX;
data->point.y = touchY;
data->state = valid == false ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR;
}
static void btn_event_cb(lv_event_t * e)
{
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * btn = static_cast<lv_obj_t *>(lv_event_get_target(e));
if(code == LV_EVENT_CLICKED) {
static uint8_t cnt = 0;
cnt++;
lv_obj_t * label = lv_obj_get_child(btn, 0);
lv_label_set_text_fmt(label, "Button: %d", cnt);
}
}
int main()
{
struct repeating_timer timer;
stdio_init_all();
add_repeating_timer_ms(5,repeating_tick_inc, nullptr,&timer);
gpio_init(PICO_DEFAULT_LED_PIN);
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
gpio_put(PICO_DEFAULT_LED_PIN,1);
tft.begin();
tft.displayOn(true);
touch.begin(PIN_CTP_WAKE,PIN_CTP_INT);
tft.fillScreen(RA8875_BLACK);
tft.graphicsMode();
//LVGL INIT
lv_display_set_default(display1);
draw_buf1 = lv_draw_buf_create(RA8875_WIDTH / 2, RA8875_HEIGHT / 10 , LV_COLOR_FORMAT_RGB565, LV_STRIDE_AUTO);
lv_display_set_draw_buffers(display1, draw_buf1, NULL);
lv_tick_set_cb(get_elapsed_ms);
lv_display_set_flush_cb(display1, raio_display_flush);
// Create and set up at least one display before you register any input devices.
lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER); // Touch pad is a pointer-like device.
lv_indev_set_read_cb(indev, touchpad_read); // Set driver function.
const char* s = "Hello World!";
lv_obj_t *label1 = lv_label_create(lv_scr_act());
lv_label_set_text(label1, s);
lv_obj_align(label1, LV_ALIGN_CENTER, 0, 0);
lv_obj_t * btn = lv_btn_create(lv_scr_act());
lv_obj_set_pos(btn, 10, 10);
lv_obj_set_size(btn, 120, 50);
lv_obj_add_event_cb(btn, btn_event_cb, LV_EVENT_ALL, NULL);
lv_obj_t * label = lv_label_create(btn);
lv_label_set_text(label, "Button");
lv_obj_center(label);
while (1) {
sleep_ms(10);
lv_task_handler();
}
}