forked from espressif/esp-idf
lcd: support rgb lcd interupt iram safe
This commit is contained in:
@@ -26,13 +26,17 @@
|
|||||||
|
|
||||||
static const char *TAG = "gdma";
|
static const char *TAG = "gdma";
|
||||||
|
|
||||||
#if CONFIG_GDMA_ISR_IRAM_SAFE
|
#if CONFIG_GDMA_ISR_IRAM_SAFE || CONFIG_GDMA_CTRL_FUNC_IN_IRAM
|
||||||
#define GDMA_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED)
|
|
||||||
#define GDMA_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
#define GDMA_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||||
#else
|
#else
|
||||||
#define GDMA_INTR_ALLOC_FLAGS ESP_INTR_FLAG_INTRDISABLED
|
|
||||||
#define GDMA_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
#define GDMA_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||||
#endif // CONFIG_GDMA_ISR_IRAM_SAFE
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_GDMA_ISR_IRAM_SAFE
|
||||||
|
#define GDMA_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED)
|
||||||
|
#else
|
||||||
|
#define GDMA_INTR_ALLOC_FLAGS ESP_INTR_FLAG_INTRDISABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
#define GDMA_INVALID_PERIPH_TRIG (0x3F)
|
#define GDMA_INVALID_PERIPH_TRIG (0x3F)
|
||||||
#define SEARCH_REQUEST_RX_CHANNEL (1 << 0)
|
#define SEARCH_REQUEST_RX_CHANNEL (1 << 0)
|
||||||
@@ -385,9 +389,7 @@ esp_err_t gdma_register_tx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_
|
|||||||
ESP_GOTO_ON_FALSE(esp_ptr_in_iram(cbs->on_trans_eof), ESP_ERR_INVALID_ARG, err, TAG, "on_trans_eof not in IRAM");
|
ESP_GOTO_ON_FALSE(esp_ptr_in_iram(cbs->on_trans_eof), ESP_ERR_INVALID_ARG, err, TAG, "on_trans_eof not in IRAM");
|
||||||
}
|
}
|
||||||
if (user_data) {
|
if (user_data) {
|
||||||
ESP_GOTO_ON_FALSE(esp_ptr_in_dram(user_data) ||
|
ESP_GOTO_ON_FALSE(esp_ptr_internal(user_data), ESP_ERR_INVALID_ARG, err, TAG, "user context not in internal RAM");
|
||||||
esp_ptr_in_diram_dram(user_data) ||
|
|
||||||
esp_ptr_in_rtc_dram_fast(user_data), ESP_ERR_INVALID_ARG, err, TAG, "user context not in DRAM");
|
|
||||||
}
|
}
|
||||||
#endif // CONFIG_GDMA_ISR_IRAM_SAFE
|
#endif // CONFIG_GDMA_ISR_IRAM_SAFE
|
||||||
|
|
||||||
@@ -423,9 +425,7 @@ esp_err_t gdma_register_rx_event_callbacks(gdma_channel_handle_t dma_chan, gdma_
|
|||||||
ESP_GOTO_ON_FALSE(esp_ptr_in_iram(cbs->on_recv_eof), ESP_ERR_INVALID_ARG, err, TAG, "on_recv_eof not in IRAM");
|
ESP_GOTO_ON_FALSE(esp_ptr_in_iram(cbs->on_recv_eof), ESP_ERR_INVALID_ARG, err, TAG, "on_recv_eof not in IRAM");
|
||||||
}
|
}
|
||||||
if (user_data) {
|
if (user_data) {
|
||||||
ESP_GOTO_ON_FALSE(esp_ptr_in_dram(user_data) ||
|
ESP_GOTO_ON_FALSE(esp_ptr_internal(user_data), ESP_ERR_INVALID_ARG, err, TAG, "user context not in internal RAM");
|
||||||
esp_ptr_in_diram_dram(user_data) ||
|
|
||||||
esp_ptr_in_rtc_dram_fast(user_data), ESP_ERR_INVALID_ARG, err, TAG, "user context not in DRAM");
|
|
||||||
}
|
}
|
||||||
#endif // CONFIG_GDMA_ISR_IRAM_SAFE
|
#endif // CONFIG_GDMA_ISR_IRAM_SAFE
|
||||||
|
|
||||||
|
@@ -31,13 +31,17 @@
|
|||||||
|
|
||||||
// If ISR handler is allowed to run whilst cache is disabled,
|
// If ISR handler is allowed to run whilst cache is disabled,
|
||||||
// Make sure all the code and related variables used by the handler are in the SRAM
|
// Make sure all the code and related variables used by the handler are in the SRAM
|
||||||
#if CONFIG_GPTIMER_ISR_IRAM_SAFE
|
#if CONFIG_GPTIMER_ISR_IRAM_SAFE || CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM
|
||||||
#define GPTIMER_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED)
|
|
||||||
#define GPTIMER_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
#define GPTIMER_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||||
#else
|
#else
|
||||||
#define GPTIMER_INTR_ALLOC_FLAGS ESP_INTR_FLAG_INTRDISABLED
|
|
||||||
#define GPTIMER_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
#define GPTIMER_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||||
#endif //CONFIG_GPTIMER_ISR_IRAM_SAFE
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_GPTIMER_ISR_IRAM_SAFE
|
||||||
|
#define GPTIMER_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED)
|
||||||
|
#else
|
||||||
|
#define GPTIMER_INTR_ALLOC_FLAGS ESP_INTR_FLAG_INTRDISABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
#define GPTIMER_PM_LOCK_NAME_LEN_MAX 16
|
#define GPTIMER_PM_LOCK_NAME_LEN_MAX 16
|
||||||
|
|
||||||
@@ -240,9 +244,7 @@ esp_err_t gptimer_register_event_callbacks(gptimer_handle_t timer, const gptimer
|
|||||||
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_alarm), ESP_ERR_INVALID_ARG, TAG, "on_alarm callback not in IRAM");
|
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_alarm), ESP_ERR_INVALID_ARG, TAG, "on_alarm callback not in IRAM");
|
||||||
}
|
}
|
||||||
if (user_data) {
|
if (user_data) {
|
||||||
ESP_RETURN_ON_FALSE(esp_ptr_in_dram(user_data) ||
|
ESP_RETURN_ON_FALSE(esp_ptr_internal(user_data), ESP_ERR_INVALID_ARG, TAG, "user context not in internal RAM");
|
||||||
esp_ptr_in_diram_dram(user_data) ||
|
|
||||||
esp_ptr_in_rtc_dram_fast(user_data), ESP_ERR_INVALID_ARG, TAG, "user context not in DRAM");
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -32,13 +32,17 @@
|
|||||||
|
|
||||||
// If ISR handler is allowed to run whilst cache is disabled,
|
// If ISR handler is allowed to run whilst cache is disabled,
|
||||||
// Make sure all the code and related variables used by the handler are in the SRAM
|
// Make sure all the code and related variables used by the handler are in the SRAM
|
||||||
#if CONFIG_PCNT_ISR_IRAM_SAFE
|
#if CONFIG_PCNT_ISR_IRAM_SAFE || CONFIG_PCNT_CTRL_FUNC_IN_IRAM
|
||||||
#define PCNT_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED)
|
|
||||||
#define PCNT_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
#define PCNT_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
|
||||||
#else
|
#else
|
||||||
#define PCNT_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED)
|
|
||||||
#define PCNT_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
#define PCNT_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
|
||||||
#endif //CONFIG_PCNT_ISR_IRAM_SAFE
|
#endif
|
||||||
|
|
||||||
|
#if CONFIG_PCNT_ISR_IRAM_SAFE
|
||||||
|
#define PCNT_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED)
|
||||||
|
#else
|
||||||
|
#define PCNT_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_SHARED)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PCNT_PM_LOCK_NAME_LEN_MAX 16
|
#define PCNT_PM_LOCK_NAME_LEN_MAX 16
|
||||||
|
|
||||||
@@ -340,10 +344,7 @@ esp_err_t pcnt_unit_register_event_callbacks(pcnt_unit_handle_t unit, const pcnt
|
|||||||
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_reach), ESP_ERR_INVALID_ARG, TAG, "on_reach callback not in IRAM");
|
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_reach), ESP_ERR_INVALID_ARG, TAG, "on_reach callback not in IRAM");
|
||||||
}
|
}
|
||||||
if (user_data) {
|
if (user_data) {
|
||||||
ESP_RETURN_ON_FALSE(esp_ptr_in_dram(user_data) ||
|
ESP_RETURN_ON_FALSE(esp_ptr_internal(user_data), ESP_ERR_INVALID_ARG, TAG, "user context not in internal RAM");
|
||||||
esp_ptr_in_diram_dram(user_data) ||
|
|
||||||
esp_ptr_in_rtc_dram_fast(user_data),
|
|
||||||
ESP_ERR_INVALID_ARG, TAG, "user context not in DRAM");
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -1,17 +1,23 @@
|
|||||||
set(srcs "src/esp_lcd_common.c"
|
set(srcs "src/esp_lcd_common.c"
|
||||||
"src/esp_lcd_panel_io.c"
|
"src/esp_lcd_panel_io.c"
|
||||||
"src/esp_lcd_panel_io_i2c.c"
|
"src/esp_lcd_panel_io_i2c.c"
|
||||||
"src/esp_lcd_panel_io_i2s.c"
|
|
||||||
"src/esp_lcd_panel_io_spi.c"
|
"src/esp_lcd_panel_io_spi.c"
|
||||||
"src/esp_lcd_panel_io_i80.c"
|
|
||||||
"src/esp_lcd_panel_nt35510.c"
|
"src/esp_lcd_panel_nt35510.c"
|
||||||
"src/esp_lcd_panel_ssd1306.c"
|
"src/esp_lcd_panel_ssd1306.c"
|
||||||
"src/esp_lcd_panel_st7789.c"
|
"src/esp_lcd_panel_st7789.c"
|
||||||
"src/esp_lcd_panel_ops.c"
|
"src/esp_lcd_panel_ops.c")
|
||||||
"src/esp_lcd_rgb_panel.c")
|
|
||||||
set(includes "include" "interface")
|
set(includes "include" "interface")
|
||||||
set(priv_requires "driver")
|
set(priv_requires "driver")
|
||||||
|
|
||||||
|
if(CONFIG_SOC_I2S_LCD_I80_VARIANT)
|
||||||
|
list(APPEND srcs "src/esp_lcd_panel_io_i2s.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_SOC_LCDCAM_SUPPORTED)
|
||||||
|
list(APPEND srcs "src/esp_lcd_panel_io_i80.c" "src/esp_lcd_rgb_panel.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS ${srcs}
|
idf_component_register(SRCS ${srcs}
|
||||||
INCLUDE_DIRS ${includes}
|
INCLUDE_DIRS ${includes}
|
||||||
PRIV_REQUIRES ${priv_requires})
|
PRIV_REQUIRES ${priv_requires}
|
||||||
|
LDFRAGMENTS linker.lf)
|
||||||
|
@@ -6,11 +6,24 @@ menu "LCD and Touch Panel"
|
|||||||
help
|
help
|
||||||
LCD driver allocates an internal buffer to transform the data into a proper format, because of
|
LCD driver allocates an internal buffer to transform the data into a proper format, because of
|
||||||
the endian order mismatch. This option is to set the size of the buffer, in bytes.
|
the endian order mismatch. This option is to set the size of the buffer, in bytes.
|
||||||
|
|
||||||
config LCD_ENABLE_DEBUG_LOG
|
config LCD_ENABLE_DEBUG_LOG
|
||||||
bool "Enable debug log"
|
bool "Enable debug log"
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
Wether to enable the debug log message for LCD driver.
|
Wether to enable the debug log message for LCD driver.
|
||||||
Note that, this option only controls the LCD driver log, won't affect other drivers.
|
Note that, this option only controls the LCD driver log, won't affect other drivers.
|
||||||
|
|
||||||
|
if SOC_LCD_RGB_SUPPORTED
|
||||||
|
config LCD_RGB_ISR_IRAM_SAFE
|
||||||
|
bool "RGB LCD ISR IRAM-Safe"
|
||||||
|
default n
|
||||||
|
select GDMA_CTRL_FUNC_IN_IRAM # need to restart GDMA in the LCD ISR
|
||||||
|
help
|
||||||
|
Ensure the LCD interrupt is IRAM-Safe by allowing the interrupt handler to be
|
||||||
|
executable when the cache is disabled (e.g. SPI Flash write).
|
||||||
|
If you want the LCD driver to keep flushing the screen even when cache ops disabled,
|
||||||
|
you can enable this option. Note, this will also increase the IRAM usage.
|
||||||
|
endif # SOC_LCD_RGB_SUPPORTED
|
||||||
endmenu
|
endmenu
|
||||||
endmenu
|
endmenu
|
||||||
|
6
components/esp_lcd/linker.lf
Normal file
6
components/esp_lcd/linker.lf
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[mapping:esp_lcd]
|
||||||
|
archive: libesp_lcd.a
|
||||||
|
entries:
|
||||||
|
if LCD_RGB_ISR_IRAM_SAFE = y:
|
||||||
|
esp_lcd_common: lcd_com_mount_dma_data (noflash)
|
||||||
|
esp_lcd_rgb_panel: lcd_rgb_panel_start_transmission (noflash)
|
@@ -39,6 +39,12 @@
|
|||||||
#include "hal/lcd_hal.h"
|
#include "hal/lcd_hal.h"
|
||||||
#include "hal/lcd_ll.h"
|
#include "hal/lcd_ll.h"
|
||||||
|
|
||||||
|
#if CONFIG_LCD_RGB_ISR_IRAM_SAFE
|
||||||
|
#define LCD_RGB_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED)
|
||||||
|
#else
|
||||||
|
#define LCD_RGB_INTR_ALLOC_FLAGS ESP_INTR_FLAG_INTRDISABLED
|
||||||
|
#endif
|
||||||
|
|
||||||
static const char *TAG = "lcd_panel.rgb";
|
static const char *TAG = "lcd_panel.rgb";
|
||||||
|
|
||||||
typedef struct esp_rgb_panel_t esp_rgb_panel_t;
|
typedef struct esp_rgb_panel_t esp_rgb_panel_t;
|
||||||
@@ -100,6 +106,16 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
|
|||||||
ESP_GOTO_ON_FALSE(rgb_panel_config && ret_panel, ESP_ERR_INVALID_ARG, err, TAG, "invalid parameter");
|
ESP_GOTO_ON_FALSE(rgb_panel_config && ret_panel, ESP_ERR_INVALID_ARG, err, TAG, "invalid parameter");
|
||||||
ESP_GOTO_ON_FALSE(rgb_panel_config->data_width == 16, ESP_ERR_NOT_SUPPORTED, err, TAG,
|
ESP_GOTO_ON_FALSE(rgb_panel_config->data_width == 16, ESP_ERR_NOT_SUPPORTED, err, TAG,
|
||||||
"unsupported data width %d", rgb_panel_config->data_width);
|
"unsupported data width %d", rgb_panel_config->data_width);
|
||||||
|
|
||||||
|
#if CONFIG_LCD_RGB_ISR_IRAM_SAFE
|
||||||
|
if (rgb_panel_config->on_frame_trans_done) {
|
||||||
|
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(rgb_panel_config->on_frame_trans_done), ESP_ERR_INVALID_ARG, TAG, "on_frame_trans_done callback not in IRAM");
|
||||||
|
}
|
||||||
|
if (rgb_panel_config->user_ctx) {
|
||||||
|
ESP_RETURN_ON_FALSE(esp_ptr_internal(rgb_panel_config->user_ctx), ESP_ERR_INVALID_ARG, TAG, "user context not in internal RAM");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// calculate the number of DMA descriptors
|
// calculate the number of DMA descriptors
|
||||||
size_t fb_size = rgb_panel_config->timings.h_res * rgb_panel_config->timings.v_res * rgb_panel_config->data_width / 8;
|
size_t fb_size = rgb_panel_config->timings.h_res * rgb_panel_config->timings.v_res * rgb_panel_config->data_width / 8;
|
||||||
size_t num_dma_nodes = fb_size / DMA_DESCRIPTOR_BUFFER_MAX_SIZE;
|
size_t num_dma_nodes = fb_size / DMA_DESCRIPTOR_BUFFER_MAX_SIZE;
|
||||||
@@ -147,7 +163,7 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
|
|||||||
ret = lcd_rgb_panel_select_periph_clock(rgb_panel, rgb_panel_config->clk_src);
|
ret = lcd_rgb_panel_select_periph_clock(rgb_panel, rgb_panel_config->clk_src);
|
||||||
ESP_GOTO_ON_ERROR(ret, err, TAG, "select periph clock failed");
|
ESP_GOTO_ON_ERROR(ret, err, TAG, "select periph clock failed");
|
||||||
// install interrupt service, (LCD peripheral shares the interrupt source with Camera by different mask)
|
// install interrupt service, (LCD peripheral shares the interrupt source with Camera by different mask)
|
||||||
int isr_flags = LCD_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED;
|
int isr_flags = LCD_RGB_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED;
|
||||||
ret = esp_intr_alloc_intrstatus(lcd_periph_signals.panels[panel_id].irq_id, isr_flags,
|
ret = esp_intr_alloc_intrstatus(lcd_periph_signals.panels[panel_id].irq_id, isr_flags,
|
||||||
(uint32_t)lcd_ll_get_interrupt_status_reg(rgb_panel->hal.dev),
|
(uint32_t)lcd_ll_get_interrupt_status_reg(rgb_panel->hal.dev),
|
||||||
LCD_LL_EVENT_VSYNC_END, lcd_default_isr_handler, rgb_panel, &rgb_panel->intr);
|
LCD_LL_EVENT_VSYNC_END, lcd_default_isr_handler, rgb_panel, &rgb_panel->intr);
|
||||||
|
@@ -3,3 +3,16 @@ cmake_minimum_required(VERSION 3.5)
|
|||||||
|
|
||||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
project(rgb_lcd_panel_test)
|
project(rgb_lcd_panel_test)
|
||||||
|
|
||||||
|
if(CONFIG_COMPILER_DUMP_RTL_FILES)
|
||||||
|
add_custom_target(check_test_app_sections ALL
|
||||||
|
COMMAND ${PYTHON} $ENV{IDF_PATH}/tools/ci/check_callgraph.py
|
||||||
|
--rtl-dir ${CMAKE_BINARY_DIR}/esp-idf/esp_lcd/
|
||||||
|
--elf-file ${CMAKE_BINARY_DIR}/rgb_lcd_panel_test.elf
|
||||||
|
find-refs
|
||||||
|
--from-sections=.iram0.text
|
||||||
|
--to-sections=.flash.text,.flash.rodata
|
||||||
|
--exit-code
|
||||||
|
DEPENDS ${elf}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
set(srcs "test_app_main.c"
|
set(srcs "test_app_main.c"
|
||||||
"test_rgb_panel.c")
|
"test_rgb_panel.c")
|
||||||
|
|
||||||
idf_component_register(SRCS ${srcs}
|
idf_component_register(SRCS ${srcs})
|
||||||
PRIV_REQUIRES esp_lcd unity)
|
|
||||||
|
|
||||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u test_app_include_rgb_lcd")
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u test_app_include_rgb_lcd")
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
#include "esp_heap_caps.h"
|
#include "esp_heap_caps.h"
|
||||||
|
|
||||||
// Some resources are lazy allocated in LCD driver, the threadhold is left for that case
|
// Some resources are lazy allocated in LCD driver, the threadhold is left for that case
|
||||||
#define TEST_MEMORY_LEAK_THRESHOLD (-300)
|
#define TEST_MEMORY_LEAK_THRESHOLD (-500)
|
||||||
|
|
||||||
static size_t before_free_8bit;
|
static size_t before_free_8bit;
|
||||||
static size_t before_free_32bit;
|
static size_t before_free_32bit;
|
||||||
|
@@ -5,22 +5,30 @@
|
|||||||
*/
|
*/
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "esp_lcd_panel_rgb.h"
|
#include "esp_lcd_panel_rgb.h"
|
||||||
#include "esp_lcd_panel_ops.h"
|
#include "esp_lcd_panel_ops.h"
|
||||||
#include "esp_random.h"
|
#include "esp_random.h"
|
||||||
|
#include "esp_attr.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
#include "test_rgb_board.h"
|
#include "test_rgb_board.h"
|
||||||
|
|
||||||
|
#if CONFIG_LCD_RGB_ISR_IRAM_SAFE
|
||||||
|
#define TEST_LCD_CALLBACK_ATTR IRAM_ATTR
|
||||||
|
#else
|
||||||
|
#define TEST_LCD_CALLBACK_ATTR
|
||||||
|
#endif // CONFIG_LCD_RGB_ISR_IRAM_SAFE
|
||||||
|
|
||||||
|
#define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t))
|
||||||
|
|
||||||
void test_app_include_rgb_lcd(void)
|
void test_app_include_rgb_lcd(void)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("lcd_rgb_lcd_panel", "[lcd]")
|
static esp_lcd_panel_handle_t test_rgb_panel_initialization(bool stream_mode, esp_lcd_rgb_panel_frame_trans_done_cb_t cb, void *user_data)
|
||||||
{
|
{
|
||||||
#define TEST_IMG_SIZE (100 * 100 * sizeof(uint16_t))
|
|
||||||
uint8_t *img = malloc(TEST_IMG_SIZE);
|
|
||||||
TEST_ASSERT_NOT_NULL(img);
|
|
||||||
|
|
||||||
esp_lcd_panel_handle_t panel_handle = NULL;
|
esp_lcd_panel_handle_t panel_handle = NULL;
|
||||||
esp_lcd_rgb_panel_config_t panel_config = {
|
esp_lcd_rgb_panel_config_t panel_config = {
|
||||||
.data_width = 16,
|
.data_width = 16,
|
||||||
@@ -59,17 +67,28 @@ TEST_CASE("lcd_rgb_lcd_panel", "[lcd]")
|
|||||||
.vsync_back_porch = 18,
|
.vsync_back_porch = 18,
|
||||||
.vsync_front_porch = 4,
|
.vsync_front_porch = 4,
|
||||||
.vsync_pulse_width = 1,
|
.vsync_pulse_width = 1,
|
||||||
.flags.pclk_active_neg = 1, // RGB data is clocked out on falling edge
|
|
||||||
},
|
},
|
||||||
|
.on_frame_trans_done = cb,
|
||||||
|
.user_ctx = user_data,
|
||||||
.flags.fb_in_psram = 1, // allocate frame buffer in PSRAM
|
.flags.fb_in_psram = 1, // allocate frame buffer in PSRAM
|
||||||
|
.flags.relax_on_idle = !stream_mode,
|
||||||
};
|
};
|
||||||
// Test stream mode and one-off mode
|
|
||||||
for (int i = 0; i < 2; i++) {
|
|
||||||
panel_config.flags.relax_on_idle = i;
|
|
||||||
TEST_ESP_OK(esp_lcd_new_rgb_panel(&panel_config, &panel_handle));
|
TEST_ESP_OK(esp_lcd_new_rgb_panel(&panel_config, &panel_handle));
|
||||||
TEST_ESP_OK(esp_lcd_panel_reset(panel_handle));
|
TEST_ESP_OK(esp_lcd_panel_reset(panel_handle));
|
||||||
TEST_ESP_OK(esp_lcd_panel_init(panel_handle));
|
TEST_ESP_OK(esp_lcd_panel_init(panel_handle));
|
||||||
|
|
||||||
|
return panel_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("lcd_rgb_panel_stream_mode", "[lcd]")
|
||||||
|
{
|
||||||
|
uint8_t *img = malloc(TEST_IMG_SIZE);
|
||||||
|
TEST_ASSERT_NOT_NULL(img);
|
||||||
|
|
||||||
|
printf("initialize RGB panel with stream mode\r\n");
|
||||||
|
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(true, NULL, NULL);
|
||||||
|
printf("flush random color block\r\n");
|
||||||
for (int i = 0; i < 200; i++) {
|
for (int i = 0; i < 200; i++) {
|
||||||
uint8_t color_byte = esp_random() & 0xFF;
|
uint8_t color_byte = esp_random() & 0xFF;
|
||||||
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
|
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
|
||||||
@@ -77,9 +96,88 @@ TEST_CASE("lcd_rgb_lcd_panel", "[lcd]")
|
|||||||
memset(img, color_byte, TEST_IMG_SIZE);
|
memset(img, color_byte, TEST_IMG_SIZE);
|
||||||
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
||||||
}
|
}
|
||||||
|
printf("delete RGB panel\r\n");
|
||||||
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
|
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
|
||||||
}
|
|
||||||
free(img);
|
free(img);
|
||||||
#undef TEST_IMG_SIZE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_LCD_CALLBACK_ATTR static bool test_rgb_panel_trans_done(esp_lcd_panel_handle_t panel, esp_lcd_rgb_panel_event_data_t *edata, void *user_ctx)
|
||||||
|
{
|
||||||
|
TaskHandle_t task_to_notify = (TaskHandle_t)user_ctx;
|
||||||
|
BaseType_t high_task_wakeup;
|
||||||
|
vTaskNotifyGiveFromISR(task_to_notify, &high_task_wakeup);
|
||||||
|
return high_task_wakeup == pdTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("lcd_rgb_panel_one_shot_mode", "[lcd]")
|
||||||
|
{
|
||||||
|
uint8_t *img = malloc(TEST_IMG_SIZE);
|
||||||
|
TEST_ASSERT_NOT_NULL(img);
|
||||||
|
TaskHandle_t cur_task = xTaskGetCurrentTaskHandle();
|
||||||
|
|
||||||
|
printf("initialize RGB panel with ont-shot mode\r\n");
|
||||||
|
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(false, test_rgb_panel_trans_done, cur_task);
|
||||||
|
printf("flush random color block\r\n");
|
||||||
|
for (int i = 0; i < 200; i++) {
|
||||||
|
uint8_t color_byte = esp_random() & 0xFF;
|
||||||
|
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
|
||||||
|
int y_start = esp_random() % (TEST_LCD_V_RES - 100);
|
||||||
|
memset(img, color_byte, TEST_IMG_SIZE);
|
||||||
|
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
||||||
|
// wait for flush done
|
||||||
|
TEST_ASSERT_NOT_EQUAL(0, ulTaskNotifyTake(pdFALSE, pdMS_TO_TICKS(1000)));
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("delete RGB panel\r\n");
|
||||||
|
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
|
||||||
|
free(img);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_LCD_RGB_ISR_IRAM_SAFE
|
||||||
|
TEST_CASE("lcd_rgb_panel_with_nvs_read_write", "[lcd]")
|
||||||
|
{
|
||||||
|
uint8_t *img = malloc(TEST_IMG_SIZE);
|
||||||
|
TEST_ASSERT_NOT_NULL(img);
|
||||||
|
|
||||||
|
printf("initialize RGB panel with stream mode\r\n");
|
||||||
|
esp_lcd_panel_handle_t panel_handle = test_rgb_panel_initialization(true, NULL, NULL);
|
||||||
|
printf("flush one clock block to the LCD\r\n");
|
||||||
|
uint8_t color_byte = esp_random() & 0xFF;
|
||||||
|
int x_start = esp_random() % (TEST_LCD_H_RES - 100);
|
||||||
|
int y_start = esp_random() % (TEST_LCD_V_RES - 100);
|
||||||
|
memset(img, color_byte, TEST_IMG_SIZE);
|
||||||
|
esp_lcd_panel_draw_bitmap(panel_handle, x_start, y_start, x_start + 100, y_start + 100, img);
|
||||||
|
printf("The LCD driver should keep flushing the color block in the background (as it's in stream mode)\r\n");
|
||||||
|
|
||||||
|
// read/write the SPI Flash by NVS APIs, the LCD driver should stay work
|
||||||
|
printf("initialize NVS flash\r\n");
|
||||||
|
esp_err_t err = nvs_flash_init();
|
||||||
|
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||||
|
// NVS partition was truncated and needs to be erased
|
||||||
|
TEST_ESP_OK(nvs_flash_erase());
|
||||||
|
// Retry nvs_flash_init
|
||||||
|
err = nvs_flash_init();
|
||||||
|
}
|
||||||
|
TEST_ESP_OK(err);
|
||||||
|
printf("open NVS storage\r\n");
|
||||||
|
nvs_handle_t my_handle;
|
||||||
|
TEST_ESP_OK(nvs_open("storage", NVS_READWRITE, &my_handle));
|
||||||
|
TEST_ESP_OK(nvs_erase_all(my_handle));
|
||||||
|
int test_count;
|
||||||
|
for (int i = 0; i < 50; i++) {
|
||||||
|
printf("write %d to NVS partition\r\n", i);
|
||||||
|
TEST_ESP_OK(nvs_set_i32(my_handle, "test_count", i));
|
||||||
|
TEST_ESP_OK(nvs_commit(my_handle));
|
||||||
|
TEST_ESP_OK(nvs_get_i32(my_handle, "test_count", &test_count));
|
||||||
|
TEST_ASSERT_EQUAL(i, test_count);
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(50));
|
||||||
|
}
|
||||||
|
printf("close NVS storage\r\n");
|
||||||
|
nvs_close(my_handle);
|
||||||
|
TEST_ESP_OK(nvs_flash_deinit());
|
||||||
|
|
||||||
|
printf("delete RGB panel\r\n");
|
||||||
|
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
|
||||||
|
free(img);
|
||||||
|
}
|
||||||
|
#endif // CONFIG_LCD_RGB_ISR_IRAM_SAFE
|
||||||
|
@@ -10,6 +10,7 @@ from pytest_embedded import Dut
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config',
|
||||||
[
|
[
|
||||||
|
'iram_safe',
|
||||||
'release',
|
'release',
|
||||||
],
|
],
|
||||||
indirect=True,
|
indirect=True,
|
||||||
|
@@ -0,0 +1,5 @@
|
|||||||
|
CONFIG_COMPILER_DUMP_RTL_FILES=y
|
||||||
|
CONFIG_LCD_RGB_ISR_IRAM_SAFE=y
|
||||||
|
|
||||||
|
# silent the error check, as the error string are stored in rodata, causing RTL check failure
|
||||||
|
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
@@ -1,3 +1,4 @@
|
|||||||
CONFIG_ESP32S3_SPIRAM_SUPPORT=y
|
CONFIG_ESP32S3_SPIRAM_SUPPORT=y
|
||||||
|
CONFIG_ESPTOOLPY_OCT_FLASH=y
|
||||||
CONFIG_SPIRAM_MODE_OCT=y
|
CONFIG_SPIRAM_MODE_OCT=y
|
||||||
CONFIG_SPIRAM_SPEED_80M=y
|
CONFIG_SPIRAM_SPEED_80M=y
|
||||||
|
Reference in New Issue
Block a user