How to port LVGL to MAX78000?

 Here’s a practical, battle-tested path to get LVGL running on MAX78000 / MAX78000FTHR (Cortex-M4F @ 100 MHz).




0) What you need

  • MSDK (Maxim/ADI SDK) installed + board support for MAX78000 (projects build with makefile/VS Code or Eclipse). 

  • MAX78000 User Guide / datasheet handy (clocks, SPI, DMA, cache). 

  • A SPI TFT (e.g., ILI9341 240×320 or ST7789 240×240) and—if it’s a touch panel—an I²C/SPI touch controller. Examples/projects using MAX78000 with SPI TFTs exist and are a good reference. 

  • LVGL docs (use v9 porting guide if you’re on LVGL 9.x). 


1) Create a minimal LVGL “port” layer

LVGL needs 3 things from your MCU side:

  1. Ticks – call lv_tick_inc(ms) periodically

  2. Handler – call lv_timer_handler() in your main loop (or a 1–5 ms task)

  3. Drivers – display flush_cb (+ optional input device)

1.1 Ticks

Use a hardware timer or SysTick at 1 kHz:

// in 1ms timer ISR void SysTick_Handler(void) { lv_tick_inc(1); }

Configure the timer using MSDK HAL (clock tree per UG). 

1.2 Main loop

int main(void) { system_clock_init(); // per MAX78000 UG bsp_init(); // GPIO/SPI/DMA/IRQ lv_init(); lv_port_disp_init(); // you write this (see below) lv_port_indev_init(); // optional touch while(1) { lv_timer_handler(); // every ~5 ms is fine MXC_Delay(MXC_DELAY_MSEC(5)); } }

2) Implement the display driver (SPI + DMA)

Most MAX78000 designs will talk to the TFT via SPI (modes 0/3 supported). Use DMA for throughput; LVGL’s flush callback is where you start your SPI transfer.

static void disp_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *px_map) { // Set TFT GRAM window to [x1..x2, y1..y2] (via ILI9341/ST7789 cmds) tft_set_window(area->x1, area->y1, area->x2, area->y2); // Kick SPI DMA transfer of the color buffer (RGB565) spi_dma_write((uint8_t*)px_map, (area->x2 - area->x1 + 1) * (area->y2 - area->y1 + 1) * 2); // In DMA completion IRQ: // lv_disp_flush_ready(drv); }

Hook this up in your lv_port_disp_init() with a draw buffer:

static lv_color_t buf1[LV_HOR_RES_MAX * 40]; // 40-line stripe static lv_color_t buf2[LV_HOR_RES_MAX * 40]; void lv_port_disp_init(void) { static lv_disp_draw_buf_t draw_buf; lv_disp_draw_buf_init(&draw_buf, buf1, buf2, LV_HOR_RES_MAX * 40); static lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.flush_cb = disp_flush; disp_drv.draw_buf = &draw_buf; disp_drv.hor_res = 240; // set to your panel disp_drv.ver_res = 320; // set to your panel lv_disp_drv_register(&disp_drv); }
  • MAX78000 SPI supports the needed modes; use DMA for the pixel stream and keep CPU free. 

  • The MSDK repo/eval examples include TFT demos; mine them for init sequences, DC/CS pins, and SPI/DMA setup. 

  • A community project shows ILI9341 over SPI with MAX78000FTHR—use as reference for wiring and init sequence. 


3) (Optional) Touch input driver

Register an input device (indev) that reads your touch controller each poll:

static void touch_read(lv_indev_drv_t *drv, lv_indev_data_t *data) { bool touched; uint16_t x, y; if(touch_get(&x,&y,&touched)) { data->state = touched ? LV_INDEV_STATE_PRESSED : LV_INDEV_STATE_RELEASED; data->point.x = x; data->point.y = y; } }

4) LVGL config (lv_conf.h) tips for MAX78000

  • Color format: #define LV_COLOR_DEPTH 16 (RGB565)

  • If colors look swapped, set LV_COLOR_16_SWAP 1 (panel-specific).

  • Buffers: Use 1–2 stripe buffers (e.g., 40–80 lines) to fit SRAM.

  • Tick: LV_TICK_CUSTOM 1 if you provide your own tick source.

  • Start with software rendering; add optimizations later. LVGL’s v9 porting page explains all required hooks. 


5) Performance checklist (MAX78000 specifics)

  • Enable a higher SPI baud (tens of MHz if the TFT allows; check panel datasheet). MAX78000 SPI and DMA can handle it; keep CPU out of the hot path. 

  • Use partial refresh (LVGL invalidation) and double buffering for smooth scrolling. 

  • If using caches or tightly coupled SRAM regions, follow the MSDK/User Guide notes (align DMA buffers; avoid cache lines if applicable). 

  • Place the TFT init + command macros in a thin HAL (e.g., tft_ll.c) so LVGL code stays portable.

  • For larger UIs, turn on LV_IMG_CACHE and keep fonts small.


6) Bring-up order that works

  1. Blink + SPI loopback ⇒ verify clocks/pins.

  2. Initialize TFT and draw a solid color rectangle (no LVGL yet).

  3. Drop in LVGL, set disp_flush to call the same SPI-DMA write.

  4. Show lv_label or lv_demo_widgets.

  5. Add touch driver.


7) Known good references

  • MSDK User Guide + MAX78000 UG (peripheral setup, SPI/DMA usage, examples). 

  • MSDK examples/TFT demo for MAX78000 (panel init and pins). 

  • ILI9341 on MAX78000FTHR community project (wiring + code ideas). 

  • LVGL porting guide (v9) for required callbacks and configuration.


Quick wiring (ILI9341 over SPI, typical)

  • SPI SCK/MOSI/MISO → TFT SCK/MOSI/MISO

  • CS → TFT CS

  • DC (D/C) → TFT D/C

  • RST → TFT RESET

  • BL → GPIO (PWM dimming optional)

  • Touch (if XPT2046): separate SPI or share bus with a different CS; if FT6206: I²C + INT

(Use the board’s pinout and MSDK BSP for the exact pins—evaluate kit/Feather pin names and examples cover this.) 

评论

此博客中的热门博文

How To Connect Stm32 To PC?

What are the common HDL languages used in FPGA design?

How do you set up ADC (Analog-to-Digital Converter) in STM32?