Skip to content

Commit 49aaac0

Browse files
committed
feat(mipi_dsi): support isr iram safe
1 parent d910ca7 commit 49aaac0

File tree

11 files changed

+200
-6
lines changed

11 files changed

+200
-6
lines changed

components/esp_hw_support/dma/Kconfig.dma

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ menu "GDMA Configurations"
1919
bool "Enable debug log"
2020
default n
2121
help
22-
Wether to enable the debug log message for GDMA driver.
22+
Whether to enable the debug log message for GDMA driver.
2323
Note that, this option only controls the GDMA driver log, won't affect other drivers.
2424
endmenu # GDMA Configurations
2525

@@ -40,6 +40,13 @@ menu "DW_GDMA Configurations"
4040
Place DW_GDMA setter functions (e.g. dw_gdma_channel_set_block_markers) into IRAM,
4141
so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.
4242

43+
config DW_GDMA_GETTER_FUNC_IN_IRAM
44+
bool
45+
default n
46+
help
47+
Place DW_GDMA getter functions (e.g. dw_gdma_link_list_get_item) into IRAM,
48+
so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.
49+
4350
config DW_GDMA_ISR_IRAM_SAFE
4451
bool
4552
default n
@@ -52,7 +59,7 @@ menu "DW_GDMA Configurations"
5259
bool "Enable debug log"
5360
default n
5461
help
55-
Wether to enable the debug log message for DW_GDMA driver.
62+
Whether to enable the debug log message for DW_GDMA driver.
5663
Note that, this option only controls the DW_GDMA driver log, won't affect other drivers.
5764
endmenu # DW_GDMA Configurations
5865

components/esp_hw_support/dma/linker.lf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,15 @@ entries:
7878
# put DW_GDMA control functions in IRAM
7979
if DW_GDMA_CTRL_FUNC_IN_IRAM = y:
8080
dw_gdma: dw_gdma_channel_continue (noflash)
81+
dw_gdma: dw_gdma_channel_enable_ctrl (noflash)
8182

8283
if DW_GDMA_SETTER_FUNC_IN_IRAM = y:
8384
dw_gdma: dw_gdma_channel_set_block_markers (noflash)
8485
dw_gdma: dw_gdma_lli_set_block_markers (noflash)
86+
dw_gdma: dw_gdma_channel_use_link_list (noflash)
87+
88+
if DW_GDMA_GETTER_FUNC_IN_IRAM = y:
89+
dw_gdma: dw_gdma_link_list_get_item (noflash)
8590

8691
[mapping:dma2d_driver]
8792
archive: libesp_hw_support.a

components/esp_lcd/Kconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,20 @@ menu "LCD and Touch Panel"
3636
Only need to enable it when in your application, the DMA can't deliver data
3737
as fast as the LCD consumes it.
3838
endif # SOC_LCD_RGB_SUPPORTED
39+
40+
if SOC_MIPI_DSI_SUPPORTED
41+
config LCD_DSI_ISR_IRAM_SAFE
42+
bool "DSI LCD ISR IRAM-Safe"
43+
default n
44+
select DW_GDMA_ISR_IRAM_SAFE
45+
select DW_GDMA_CTRL_FUNC_IN_IRAM
46+
select DW_GDMA_SETTER_FUNC_IN_IRAM
47+
select DW_GDMA_GETTER_FUNC_IN_IRAM
48+
help
49+
Ensure the LCD interrupt is IRAM-Safe by allowing the interrupt handler to be
50+
executable when the cache is disabled (e.g. SPI Flash write).
51+
If you want the LCD driver to keep flushing the screen even when cache ops disabled,
52+
you can enable this option. Note, this will also increase the IRAM usage.
53+
endif # SOC_MIPI_DSI_SUPPORTED
3954
endmenu
4055
endmenu

components/esp_lcd/dsi/esp_lcd_panel_dpi.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "esp_cache.h"
1515
#include "mipi_dsi_priv.h"
1616
#include "esp_async_fbcpy.h"
17+
#include "esp_memory_utils.h"
1718
#include "esp_private/dw_gdma.h"
1819
#include "hal/cache_hal.h"
1920
#include "hal/cache_ll.h"
@@ -528,6 +529,17 @@ esp_err_t esp_lcd_dpi_panel_register_event_callbacks(esp_lcd_panel_handle_t pane
528529
{
529530
ESP_RETURN_ON_FALSE(panel && cbs, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
530531
esp_lcd_dpi_panel_t *dpi_panel = __containerof(panel, esp_lcd_dpi_panel_t, base);
532+
#if CONFIG_LCD_DSI_ISR_IRAM_SAFE
533+
if (cbs->on_color_trans_done) {
534+
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_color_trans_done), ESP_ERR_INVALID_ARG, TAG, "on_color_trans_done callback not in IRAM");
535+
}
536+
if (cbs->on_refresh_done) {
537+
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_refresh_done), ESP_ERR_INVALID_ARG, TAG, "on_refresh_done callback not in IRAM");
538+
}
539+
if (user_ctx) {
540+
ESP_RETURN_ON_FALSE(esp_ptr_internal(user_ctx), ESP_ERR_INVALID_ARG, TAG, "user context not in internal RAM");
541+
}
542+
#endif // CONFIG_LCD_RGB_ISR_IRAM_SAFE
531543
dpi_panel->on_color_trans_done = cbs->on_color_trans_done;
532544
dpi_panel->on_refresh_done = cbs->on_refresh_done;
533545
dpi_panel->user_ctx = user_ctx;

components/esp_lcd/dsi/mipi_dsi_priv.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@
2323
#define DSI_RCC_ATOMIC()
2424
#endif
2525

26-
#define DSI_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
26+
#if CONFIG_LCD_DSI_ISR_IRAM_SAFE
27+
#define DSI_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
28+
#else
29+
#define DSI_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
30+
#endif
2731

2832
#define DPI_PANEL_MAX_FB_NUM 3 // maximum number of supported frame buffers for DPI panel
2933

components/esp_lcd/test_apps/.build-test-rules.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ components/esp_lcd/test_apps/mipi_dsi_lcd:
3838
disable_test:
3939
- if: IDF_TARGET == "esp32p4"
4040
temporary: true
41-
reason: lack of runners
41+
reason: lack of runners, DSI can't work without an LCD connected
4242

4343
components/esp_lcd/test_apps/rgb_lcd:
4444
depends_components:

components/esp_lcd/test_apps/mipi_dsi_lcd/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,16 @@ set(COMPONENTS main)
66

77
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
88
project(mipi_dsi_lcd_panel_test)
9+
10+
if(CONFIG_COMPILER_DUMP_RTL_FILES)
11+
add_custom_target(check_test_app_sections ALL
12+
COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py
13+
--rtl-dirs ${CMAKE_BINARY_DIR}/esp-idf/esp_lcd/,${CMAKE_BINARY_DIR}/esp-idf/hal/
14+
--elf-file ${CMAKE_BINARY_DIR}/mipi_dsi_lcd_panel_test.elf
15+
find-refs
16+
--from-sections=.iram0.text
17+
--to-sections=.flash.text,.flash.rodata
18+
--exit-code
19+
DEPENDS ${elf}
20+
)
21+
endif()

components/esp_lcd/test_apps/mipi_dsi_lcd/main/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ set(srcs "test_app_main.c"
22
"test_mipi_dsi_board.c"
33
"test_mipi_dsi_panel.c")
44

5+
if(CONFIG_LCD_DSI_ISR_IRAM_SAFE)
6+
list(APPEND srcs "test_mipi_dsi_iram.c")
7+
endif()
8+
59
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
610
# the component can be registered as WHOLE_ARCHIVE
711
idf_component_register(SRCS ${srcs}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
#include <stdio.h>
7+
#include <string.h>
8+
#include <inttypes.h>
9+
#include "freertos/FreeRTOS.h"
10+
#include "freertos/task.h"
11+
#include "unity.h"
12+
#include "unity_test_utils.h"
13+
#include "esp_lcd_mipi_dsi.h"
14+
#include "esp_lcd_panel_ops.h"
15+
#include "esp_lcd_panel_io.h"
16+
#include "esp_random.h"
17+
#include "esp_attr.h"
18+
#include "test_mipi_dsi_board.h"
19+
#include "esp_lcd_ili9881c.h"
20+
21+
IRAM_ATTR static bool test_rgb_panel_count_in_callback(esp_lcd_panel_handle_t panel, esp_lcd_dpi_panel_event_data_t *edata, void *user_ctx)
22+
{
23+
uint32_t *count = (uint32_t *)user_ctx;
24+
*count = *count + 1;
25+
return false;
26+
}
27+
28+
static void IRAM_ATTR test_delay_post_cache_disable(void *args)
29+
{
30+
esp_rom_delay_us(200000);
31+
}
32+
33+
#define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t))
34+
35+
TEST_CASE("MIPI DSI draw bitmap (ILI9881C) IRAM Safe", "[mipi_dsi]")
36+
{
37+
esp_lcd_dsi_bus_handle_t mipi_dsi_bus;
38+
esp_lcd_panel_io_handle_t mipi_dbi_io;
39+
esp_lcd_panel_handle_t mipi_dpi_panel;
40+
esp_lcd_panel_handle_t ili9881c_ctrl_panel;
41+
42+
test_bsp_enable_dsi_phy_power();
43+
44+
uint8_t *img = malloc(TEST_IMG_SIZE);
45+
TEST_ASSERT_NOT_NULL(img);
46+
47+
esp_lcd_dsi_bus_config_t bus_config = {
48+
.bus_id = 0,
49+
.num_data_lanes = 2,
50+
.phy_clk_src = MIPI_DSI_PHY_CLK_SRC_DEFAULT,
51+
.lane_bit_rate_mbps = 1000, // 1000 Mbps
52+
};
53+
TEST_ESP_OK(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus));
54+
55+
esp_lcd_dbi_io_config_t dbi_config = {
56+
.virtual_channel = 0,
57+
.lcd_cmd_bits = 8,
58+
.lcd_param_bits = 8,
59+
};
60+
TEST_ESP_OK(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &mipi_dbi_io));
61+
62+
esp_lcd_panel_dev_config_t lcd_dev_config = {
63+
.bits_per_pixel = 16,
64+
.rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB,
65+
.reset_gpio_num = -1,
66+
};
67+
TEST_ESP_OK(esp_lcd_new_panel_ili9881c(mipi_dbi_io, &lcd_dev_config, &ili9881c_ctrl_panel));
68+
TEST_ESP_OK(esp_lcd_panel_reset(ili9881c_ctrl_panel));
69+
TEST_ESP_OK(esp_lcd_panel_init(ili9881c_ctrl_panel));
70+
// turn on display
71+
TEST_ESP_OK(esp_lcd_panel_disp_on_off(ili9881c_ctrl_panel, true));
72+
73+
esp_lcd_dpi_panel_config_t dpi_config = {
74+
.dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT,
75+
.dpi_clock_freq_mhz = MIPI_DSI_DPI_CLK_MHZ,
76+
.virtual_channel = 0,
77+
.pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565,
78+
.video_timing = {
79+
.h_size = MIPI_DSI_LCD_H_RES,
80+
.v_size = MIPI_DSI_LCD_V_RES,
81+
.hsync_back_porch = MIPI_DSI_LCD_HBP,
82+
.hsync_pulse_width = MIPI_DSI_LCD_HSYNC,
83+
.hsync_front_porch = MIPI_DSI_LCD_HFP,
84+
.vsync_back_porch = MIPI_DSI_LCD_VBP,
85+
.vsync_pulse_width = MIPI_DSI_LCD_VSYNC,
86+
.vsync_front_porch = MIPI_DSI_LCD_VFP,
87+
},
88+
};
89+
TEST_ESP_OK(esp_lcd_new_panel_dpi(mipi_dsi_bus, &dpi_config, &mipi_dpi_panel));
90+
TEST_ESP_OK(esp_lcd_panel_init(mipi_dpi_panel));
91+
uint32_t callback_calls = 0;
92+
esp_lcd_dpi_panel_event_callbacks_t cbs = {
93+
.on_refresh_done = test_rgb_panel_count_in_callback,
94+
};
95+
TEST_ESP_OK(esp_lcd_dpi_panel_register_event_callbacks(mipi_dpi_panel, &cbs, &callback_calls));
96+
97+
uint8_t color_byte = rand() & 0xFF;
98+
int x_start = rand() % (MIPI_DSI_LCD_H_RES - 100);
99+
int y_start = rand() % (MIPI_DSI_LCD_V_RES - 100);
100+
memset(img, color_byte, TEST_IMG_SIZE);
101+
esp_lcd_panel_draw_bitmap(mipi_dpi_panel, x_start, y_start, x_start + 100, y_start + 100, img);
102+
vTaskDelay(pdMS_TO_TICKS(100));
103+
104+
printf("The LCD driver should keep flushing the color block in the background\r\n");
105+
106+
// disable the cache for a while, the LCD driver should stay working
107+
printf("disable the cache for a while\r\n");
108+
unity_utils_run_cache_disable_stub(test_delay_post_cache_disable, NULL);
109+
printf("callback calls: %"PRIu32"\r\n", callback_calls);
110+
TEST_ASSERT(callback_calls > 2);
111+
112+
TEST_ESP_OK(esp_lcd_panel_del(mipi_dpi_panel));
113+
TEST_ESP_OK(esp_lcd_panel_del(ili9881c_ctrl_panel));
114+
TEST_ESP_OK(esp_lcd_panel_io_del(mipi_dbi_io));
115+
TEST_ESP_OK(esp_lcd_del_dsi_bus(mipi_dsi_bus));
116+
free(img);
117+
118+
test_bsp_disable_dsi_phy_power();
119+
}
Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
# SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
22
# SPDX-License-Identifier: CC0-1.0
3-
43
import pytest
54
from pytest_embedded import Dut
65

76

87
@pytest.mark.esp32p4
98
@pytest.mark.generic
10-
def test_rgb_lcd(dut: Dut) -> None:
9+
@pytest.mark.parametrize(
10+
'config',
11+
[
12+
'iram_safe',
13+
'release',
14+
],
15+
indirect=True,
16+
)
17+
def test_dsi_lcd(dut: Dut) -> None:
1118
dut.run_all_single_board_cases()

0 commit comments

Comments
 (0)