ESP32-P4 --- LCD 控制
用户把需要更新的像素数据通过拷贝或者DMA搬到 frame buffer,然后刷一下CACHE
static esp_err_t dpi_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
frame buffer 的数据是通过DMA不停的发送到 DSI bridge(FIFO memory of peripheral: DSI),一帧搬完,在完成回调函数重新启动DMA
static esp_err_t dpi_panel_create_dma_link(esp_lcd_dpi_panel_t *dpi_panel)
DMA的源地址和目的地址在这里设置
完成回调函数即是场同步信号,可以在这里计数得到实际刷新频率(frame per second)
IRAM_ATTR static bool dma_trans_done_cb(dw_gdma_channel_handle_t chan, const dw_gdma_trans_done_event_data_t *event_data, void *user_data) { bool yield_needed = false; esp_lcd_dpi_panel_t *dpi_panel = (esp_lcd_dpi_panel_t *)user_data; uint8_t fb_index = dpi_panel->cur_fb_index; dw_gdma_link_list_handle_t link_list = dpi_panel->link_lists[fb_index]; // restart the DMA transfer, keep refreshing the LCD dw_gdma_block_markers_t markers = { .is_valid = true, .is_last = true, }; dw_gdma_lli_set_block_markers(dw_gdma_link_list_get_item(link_list, 0), markers); dw_gdma_channel_use_link_list(chan, link_list); dw_gdma_channel_enable_ctrl(chan, true); // 启动 DMA 搬移 // the DMA descriptor is large enough to carry a whole frame buffer, so this event can also be treated as a fake "vsync end" if (dpi_panel->on_refresh_done) { if (dpi_panel->on_refresh_done(&dpi_panel->base, NULL, dpi_panel->user_ctx)) { yield_needed = true; } } return yield_needed; }