lcd: support rgb lcd interupt iram safe

This commit is contained in:
morris
2022-03-07 18:04:02 +08:00
parent f06a13ad82
commit 7112009473
14 changed files with 218 additions and 57 deletions

View File

@@ -3,3 +3,16 @@ cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
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()

View File

@@ -1,7 +1,6 @@
set(srcs "test_app_main.c"
"test_rgb_panel.c")
idf_component_register(SRCS ${srcs}
PRIV_REQUIRES esp_lcd unity)
idf_component_register(SRCS ${srcs})
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u test_app_include_rgb_lcd")

View File

@@ -9,7 +9,7 @@
#include "esp_heap_caps.h"
// 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_32bit;

View File

@@ -5,22 +5,30 @@
*/
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "unity.h"
#include "esp_lcd_panel_rgb.h"
#include "esp_lcd_panel_ops.h"
#include "esp_random.h"
#include "esp_attr.h"
#include "nvs_flash.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)
{
}
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_rgb_panel_config_t panel_config = {
.data_width = 16,
@@ -59,27 +67,117 @@ TEST_CASE("lcd_rgb_lcd_panel", "[lcd]")
.vsync_back_porch = 18,
.vsync_front_porch = 4,
.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.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_panel_reset(panel_handle));
TEST_ESP_OK(esp_lcd_panel_init(panel_handle));
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);
}
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_init(panel_handle));
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
}
free(img);
#undef TEST_IMG_SIZE
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++) {
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("delete RGB panel\r\n");
TEST_ESP_OK(esp_lcd_panel_del(panel_handle));
free(img);
}
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

View File

@@ -10,6 +10,7 @@ from pytest_embedded import Dut
@pytest.mark.parametrize(
'config',
[
'iram_safe',
'release',
],
indirect=True,

View File

@@ -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

View File

@@ -1,3 +1,4 @@
CONFIG_ESP32S3_SPIRAM_SUPPORT=y
CONFIG_ESPTOOLPY_OCT_FLASH=y
CONFIG_SPIRAM_MODE_OCT=y
CONFIG_SPIRAM_SPEED_80M=y