fix(rlcd): fix ST7305 DMA fragmentation and lockup bug
- Moved temporary draw buffer allocation to the initialization phase and made it persistent in the driver struct. - Resolved severe heap fragmentation caused by allocating and freeing 15KB per UI frame. - Fixed a use-after-free corruption where the SPI DMA would read from a freed temporary buffer. - Fixed WDT timeout caused by OOM failure in esp_lcd_panel_draw_bitmap that left LVGL hanging in wait_for_flushing. - Added explicit RAM clear command to boot sequence to wipe lingering hardware freeze artifacts.
This commit is contained in:
@@ -40,6 +40,7 @@ typedef struct {
|
||||
uint8_t madctl_val;
|
||||
const st7305_lcd_init_cmd_t *init_cmds;
|
||||
uint16_t init_cmds_size;
|
||||
uint8_t *draw_buffer;
|
||||
} st7305_panel_t;
|
||||
|
||||
static const st7305_lcd_init_cmd_t st7305_init_cmds[] = {
|
||||
@@ -103,6 +104,10 @@ esp_err_t esp_lcd_new_panel_st7305(const esp_lcd_panel_io_handle_t io, const esp
|
||||
st7305->init_cmds = st7305_init_cmds;
|
||||
st7305->init_cmds_size = sizeof(st7305_init_cmds) / sizeof(st7305_lcd_init_cmd_t);
|
||||
}
|
||||
|
||||
st7305->draw_buffer = heap_caps_malloc(15000, MALLOC_CAP_DMA);
|
||||
ESP_GOTO_ON_FALSE(st7305->draw_buffer, ESP_ERR_NO_MEM, err, TAG, "no mem for st7305 draw buffer");
|
||||
memset(st7305->draw_buffer, 0, 15000);
|
||||
st7305->base.del = panel_st7305_del;
|
||||
st7305->base.reset = panel_st7305_reset;
|
||||
st7305->base.init = panel_st7305_init;
|
||||
@@ -126,6 +131,9 @@ err:
|
||||
if (panel_dev_config->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(panel_dev_config->reset_gpio_num);
|
||||
}
|
||||
if (st7305->draw_buffer) {
|
||||
free(st7305->draw_buffer);
|
||||
}
|
||||
free(st7305);
|
||||
}
|
||||
return ret;
|
||||
@@ -137,6 +145,9 @@ static esp_err_t panel_st7305_del(esp_lcd_panel_t *panel)
|
||||
if (st7305->reset_gpio_num >= 0) {
|
||||
gpio_reset_pin(st7305->reset_gpio_num);
|
||||
}
|
||||
if (st7305->draw_buffer) {
|
||||
free(st7305->draw_buffer);
|
||||
}
|
||||
free(st7305);
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -172,6 +183,18 @@ static esp_err_t panel_st7305_init(esp_lcd_panel_t *panel)
|
||||
vTaskDelay(pdMS_TO_TICKS(st7305->init_cmds[i].delay_ms));
|
||||
}
|
||||
}
|
||||
|
||||
// Explicitly clear display RAM to white
|
||||
if (st7305->draw_buffer) {
|
||||
memset(st7305->draw_buffer, 0xFF, 15000); // 0xFF is White
|
||||
uint8_t caset[] = {0x12, 0x2A};
|
||||
uint8_t raset[] = {0x00, 0xC7};
|
||||
esp_lcd_panel_io_tx_param(io, ST7305_CMD_CASET, caset, sizeof(caset));
|
||||
esp_lcd_panel_io_tx_param(io, ST7305_CMD_RASET, raset, sizeof(raset));
|
||||
esp_lcd_panel_io_tx_color(io, ST7305_CMD_RAMWR, st7305->draw_buffer, 15000);
|
||||
vTaskDelay(pdMS_TO_TICKS(50));
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -180,14 +203,6 @@ static esp_err_t panel_st7305_draw_bitmap(esp_lcd_panel_t *panel, int x_start, i
|
||||
st7305_panel_t *st7305 = __containerof(panel, st7305_panel_t, base);
|
||||
esp_lcd_panel_io_handle_t io = st7305->io;
|
||||
|
||||
// Output buffer size is 15000 bytes (400 * 300 / 8)
|
||||
size_t lcd_buf_size = 15000;
|
||||
uint8_t *temp_buffer = heap_caps_malloc(lcd_buf_size, MALLOC_CAP_DMA);
|
||||
if (!temp_buffer) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
memset(temp_buffer, 0, lcd_buf_size);
|
||||
|
||||
const uint8_t *src = (const uint8_t *)color_data;
|
||||
|
||||
// Convert from vertical-page format (SSD1306-style) to ST7305 landscape 2x4 block format
|
||||
@@ -218,9 +233,9 @@ static esp_err_t panel_st7305_draw_bitmap(esp_lcd_panel_t *panel, int x_start, i
|
||||
// In ST7305 display RAM, White/Light is 1, Black/Dark is 0.
|
||||
// So we write: 1 (White) if is_pixel_set is false (light), and 0 (Black) if is_pixel_set is true (dark).
|
||||
if (!is_pixel_set) {
|
||||
temp_buffer[dest_byte_idx] |= (1 << dest_bit_pos);
|
||||
st7305->draw_buffer[dest_byte_idx] |= (1 << dest_bit_pos);
|
||||
} else {
|
||||
temp_buffer[dest_byte_idx] &= ~(1 << dest_bit_pos);
|
||||
st7305->draw_buffer[dest_byte_idx] &= ~(1 << dest_bit_pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -230,9 +245,8 @@ static esp_err_t panel_st7305_draw_bitmap(esp_lcd_panel_t *panel, int x_start, i
|
||||
|
||||
esp_lcd_panel_io_tx_param(io, ST7305_CMD_CASET, caset, sizeof(caset));
|
||||
esp_lcd_panel_io_tx_param(io, ST7305_CMD_RASET, raset, sizeof(raset));
|
||||
esp_lcd_panel_io_tx_color(io, ST7305_CMD_RAMWR, temp_buffer, lcd_buf_size);
|
||||
esp_lcd_panel_io_tx_color(io, ST7305_CMD_RAMWR, st7305->draw_buffer, 15000);
|
||||
|
||||
free(temp_buffer);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user