lvgl: lv_task_handler() hangs on first call - porting to Arduino, Teensy 3.6 & Adafruit 2.4" LCD
Greetings,
Since discovering the existence of LittlevGL I’ve been working to port it to my project. I’m using the Arduino IDE with a Teensy 3.6 & Adafruit 2.4" LCD touchscreen. I’ve been using the lvgl_test.ino template in order to get things working, but haven’t managed success quite yet.
My display’s startup code works without issue, printing the debugging confirmations of setup completion to the screen. However as soon as loop() starts, lv_task_handler() is called but never returns. I know this because on the serial output I only get this debug output:
0: Start Task
I have tried my code with and without the debug printing with the same result.
If anyone could lend me some assistance in working through this issue, I’d appreciate it 😀
More details: I’m using the Arduino IDE version 1.8.5, and commit 5c1a1d6e944728d093442da8f48dc0ea863e5fc8 from “dev-5.2” branch
Here’s my edited code for lvgl_test.ino
:
`#include <SPI.h>
#include “ILI9341_t3.h”
#include <lvgl.h>
// ------------------ PINS -------------------- /* LCD Display */ #define TFT_CS 10 // Chip Select #define TFT_DC 9 // Data/Command #define TFT_LITE 8 // Backlight brightness control - PWM Output #define TFT_RESET 7 // Reset LCD - Output
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC, TFT_RESET); // Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
void my_disp_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2, const lv_color_t *color_array) {
/TODO copy ‘color_array’ to the specifed coordinates of your display./ // Serial.println(“disp_flush(%d, %d, %d, %d, buffer) called”); tft.writeRect(x1,y1, 1+x2-x1, 1+y2-y1, (const uint16_t *) color_array);
/Tell the flushing is ready/ lv_flush_ready(); }
bool my_tp_read(lv_indev_data_t *data) { bool tp_is_pressed = false; /TODO read here the state of touch pad/ int16_t last_x = 0; int16_t last_y = 0;
if (tp_is_pressed)
{
/Touch pad is being pressed now/
last_x = 0; /TODO save the current X coordinate/
last_y = 0; /TODO save the current Y coordinate/
}
data->point.x = last_x; data->point.y = last_y; data->state = tp_is_pressed ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
return false; /Return false because no more to be read/ }
void hal_init(void) { /Initialize the display/ lv_disp_drv_t disp_drv; disp_drv.disp_flush = my_disp_flush; lv_disp_drv_register(&disp_drv);
/*Initialize the touch pad*/
lv_indev_drv_t indev_drv;
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read = my_tp_read;
lv_indev_drv_register(&indev_drv);
/*Initialize the graphics library's tick*/
/*In a Timer call 'lv_tick_inc(1)' in every milliseconds, or if no other option just call it loop() */
}
void setup() { // Set display pins before startup move SCK signal CORE_PIN13_CONFIG = PORT_PCR_MUX(0); CORE_PIN14_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);
tft.begin();
CORE_PIN13_CONFIG = PORT_PCR_MUX(0); CORE_PIN14_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2); pinMode(13, OUTPUT);
tft.fillScreen(ILI9341_BLUE);
int16_t width_px = tft.width(), height_px = tft.height(); float x_frac, y_frac, rad_frac; uint16_t screen_buffer[height_px][width_px];
// Draw color gradients with writeRect() to confirm functionality for (uint16_t x = 0; x < width_px; x++) { x_frac = (float)x / width_px;
for (uint16_t y = 0; y < height_px; y++)
{
y_frac = (float)y/height_px;
rad_frac = sqrt(pow(x_frac,2) + pow(y_frac,2));
screen_buffer[y][x] = tft.color565(255 * x_frac, 255 * y_frac, 255 * (1-(rad_frac / 1.414)));
}
}
tft.writeRect(0,0, width_px, height_px, (const uint16_t *) screen_buffer);
tft.setCursor(0, 0); tft.setTextColor(ILI9341_WHITE); tft.setTextSize(1); tft.println(“Hello World!”);
lv_init(); tft.println(“lv_init() complete”);
hal_init(); tft.println(“hal_init() complete”);
lv_obj_t *label = lv_label_create(lv_scr_act(), NULL); lv_label_set_text(label, “Hello Arduino!”); lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, 0); tft.println(“prep stuff complete. Exiting Setup”); }
void loop() { static unsigned int counter = 0; // put your main code here, to run repeatedly: Serial.printf(“%d: Start Task”, counter); lv_task_handler(); Serial.println(" - Finished"); /If ‘lv_tick_inc(5)’ is not called in a Timer then call it here/ Serial.print(“Start Tick”); lv_tick_inc(5); Serial.println(" - Finished"); delay(5); /Wait a little/ }`
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Comments: 26 (6 by maintainers)
Probably the same issue was here too: https://github.com/littlevgl/arduino/issues/2#issuecomment-466004502
Oh, really I forget that it’s not simple in Arduino.
You can also do this:
Serial.printf("design_func: %d\n", obj->design_func);
Hi,
Sorry, I couldn’t answer yesterday but I followed the discussion.
@PalantirWielder Thank you for figuring out these very valuable thinks. I tried to compile the code with lto on PC but “unfortunately” it worked. You said the program halts on
lv_refr_obj
. A few things came to my mind:lv_refr_area_part_vdb
(lv_refr.c)?LV_MEM_SIZE (16*1024)
. Maybe you got a stack overflow.printf
is not supported in your system you need to register a print function the see the log of LittlevGL. You can use this function to do it:lv_log_register_print
. In this case setLV_LOG_PRINTF 0
@epikao LittelvGL is not thread-safe by default so if you run
lv_task_handler
in the loop then you can’t create objects in interrupts. I agree with PalantirWielder, you should disable whilelv_task_handler
is running.