diff --git a/Kconfig b/Kconfig index 2632c8235f..a07ba19440 100755 --- a/Kconfig +++ b/Kconfig @@ -210,4 +210,11 @@ menu "Camera configuration" Full color range mode has a wider color range, so details in the image show more clearly. Please confirm the color range mode of the current camera sensor, incorrect color range mode may cause color difference in the final converted image. Full range mode is used by default. If this option is not selected, the format conversion function will be done using the limited range mode. + + config LCD_CAM_ISR_IRAM_SAFE + bool "Execute camera ISR from IRAM" + depends on (IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3) + default n + help + If this option is enabled, camera ISR will execute from IRAM. endmenu diff --git a/target/esp32s2/ll_cam.c b/target/esp32s2/ll_cam.c index a1a7479b9c..1c3fdb10e3 100644 --- a/target/esp32s2/ll_cam.c +++ b/target/esp32s2/ll_cam.c @@ -37,7 +37,7 @@ static const char *TAG = "s2 ll_cam"; #define I2S_ISR_ENABLE(i) {I2S0.int_clr.i = 1;I2S0.int_ena.i = 1;} #define I2S_ISR_DISABLE(i) {I2S0.int_ena.i = 0;I2S0.int_clr.i = 1;} -static void IRAM_ATTR ll_cam_vsync_isr(void *arg) +static void CAMERA_ISR_IRAM_ATTR ll_cam_vsync_isr(void *arg) { //DBG_PIN_SET(1); cam_obj_t *cam = (cam_obj_t *)arg; @@ -54,7 +54,7 @@ static void IRAM_ATTR ll_cam_vsync_isr(void *arg) //DBG_PIN_SET(0); } -static void IRAM_ATTR ll_cam_dma_isr(void *arg) +static void CAMERA_ISR_IRAM_ATTR ll_cam_dma_isr(void *arg) { cam_obj_t *cam = (cam_obj_t *)arg; BaseType_t HPTaskAwoken = pdFALSE; @@ -217,7 +217,7 @@ esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config) io_conf.pull_up_en = 1; io_conf.pull_down_en = 0; gpio_config(&io_conf); - gpio_install_isr_service(ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM); + gpio_install_isr_service(ESP_INTR_FLAG_LOWMED | CAMERA_ISR_IRAM_FLAG); gpio_isr_handler_add(config->pin_vsync, ll_cam_vsync_isr, cam); gpio_intr_disable(config->pin_vsync); @@ -255,7 +255,7 @@ esp_err_t ll_cam_set_pin(cam_obj_t *cam, const camera_config_t *config) esp_err_t ll_cam_init_isr(cam_obj_t *cam) { - return esp_intr_alloc(ETS_I2S0_INTR_SOURCE, ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM, ll_cam_dma_isr, cam, &cam->cam_intr_handle); + return esp_intr_alloc(ETS_I2S0_INTR_SOURCE, ESP_INTR_FLAG_LOWMED | CAMERA_ISR_IRAM_FLAG, ll_cam_dma_isr, cam, &cam->cam_intr_handle); } void ll_cam_do_vsync(cam_obj_t *cam) diff --git a/target/esp32s3/ll_cam.c b/target/esp32s3/ll_cam.c index 193c1821bc..c61846999e 100644 --- a/target/esp32s3/ll_cam.c +++ b/target/esp32s3/ll_cam.c @@ -20,6 +20,8 @@ #include "soc/gdma_struct.h" #include "soc/gdma_periph.h" #include "soc/gdma_reg.h" +#include "hal/clk_gate_ll.h" +#include "esp_private/gdma.h" #include "ll_cam.h" #include "cam_hal.h" #include "esp_rom_gpio.h" @@ -87,7 +89,7 @@ void ll_cam_dma_reset(cam_obj_t *cam) //GDMA.channel[cam->dma_num].in.wight.rx_weight = 7;//The weight of Rx channel 0-15 } -static void IRAM_ATTR ll_cam_vsync_isr(void *arg) +static void CAMERA_ISR_IRAM_ATTR ll_cam_vsync_isr(void *arg) { //DBG_PIN_SET(1); cam_obj_t *cam = (cam_obj_t *)arg; @@ -110,7 +112,7 @@ static void IRAM_ATTR ll_cam_vsync_isr(void *arg) //DBG_PIN_SET(0); } -static void IRAM_ATTR ll_cam_dma_isr(void *arg) +static void CAMERA_ISR_IRAM_ATTR ll_cam_dma_isr(void *arg) { cam_obj_t *cam = (cam_obj_t *)arg; BaseType_t HPTaskAwoken = pdFALSE; @@ -141,25 +143,6 @@ bool IRAM_ATTR ll_cam_stop(cam_obj_t *cam) return true; } -esp_err_t ll_cam_deinit(cam_obj_t *cam) -{ - if (cam->cam_intr_handle) { - esp_intr_free(cam->cam_intr_handle); - cam->cam_intr_handle = NULL; - } - - if (cam->dma_intr_handle) { - esp_intr_free(cam->dma_intr_handle); - cam->dma_intr_handle = NULL; - } - GDMA.channel[cam->dma_num].in.link.addr = 0x0; - - LCD_CAM.cam_ctrl1.cam_start = 0; - LCD_CAM.cam_ctrl1.cam_reset = 1; - LCD_CAM.cam_ctrl1.cam_reset = 0; - return ESP_OK; -} - bool ll_cam_start(cam_obj_t *cam, int frame_pos) { LCD_CAM.cam_ctrl1.cam_start = 0; @@ -191,27 +174,72 @@ bool ll_cam_start(cam_obj_t *cam, int frame_pos) return true; } -static esp_err_t ll_cam_dma_init(cam_obj_t *cam) +esp_err_t ll_cam_deinit(cam_obj_t *cam) { - for (int x = (SOC_GDMA_PAIRS_PER_GROUP - 1); x >= 0; x--) { - if (GDMA.channel[x].in.link.addr == 0x0) { - cam->dma_num = x; - ESP_LOGI(TAG, "DMA Channel=%d", cam->dma_num); - break; - } - if (x == 0) { - cam_deinit(); - ESP_LOGE(TAG, "Can't found available GDMA channel"); - return ESP_FAIL; - } + if (cam->cam_intr_handle) { + esp_intr_free(cam->cam_intr_handle); + cam->cam_intr_handle = NULL; } - if (REG_GET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN) == 0) { - REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN); - REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN); - REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); - REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); + if (cam->dma_intr_handle) { + esp_intr_free(cam->dma_intr_handle); + cam->dma_intr_handle = NULL; + } + gdma_disconnect(cam->dma_channel_handle); + gdma_del_channel(cam->dma_channel_handle); + cam->dma_channel_handle = NULL; + // GDMA.channel[cam->dma_num].in.link.addr = 0x0; + + LCD_CAM.cam_ctrl1.cam_start = 0; + LCD_CAM.cam_ctrl1.cam_reset = 1; + LCD_CAM.cam_ctrl1.cam_reset = 0; + return ESP_OK; +} + +static esp_err_t ll_cam_dma_init(cam_obj_t *cam) +{ + //alloc rx gdma channel + gdma_channel_alloc_config_t rx_alloc_config = { + .direction = GDMA_CHANNEL_DIRECTION_RX, + }; + esp_err_t ret = gdma_new_channel(&rx_alloc_config, &cam->dma_channel_handle); + if (ret != ESP_OK) { + cam_deinit(); + ESP_LOGE(TAG, "Can't find available GDMA channel"); + return ESP_FAIL; + } + int chan_id = -1; + ret = gdma_get_channel_id(cam->dma_channel_handle, &chan_id); + if (ret != ESP_OK) { + cam_deinit(); + ESP_LOGE(TAG, "Can't get GDMA channel number"); + return ESP_FAIL; + } + cam->dma_num = chan_id; + ESP_LOGI(TAG, "DMA Channel=%d", cam->dma_num); + // for (int x = (SOC_GDMA_PAIRS_PER_GROUP - 1); x >= 0; x--) { + // if (GDMA.channel[x].in.link.addr == 0x0) { + // cam->dma_num = x; + // ESP_LOGI(TAG, "DMA Channel=%d", cam->dma_num); + // break; + // } + // if (x == 0) { + // cam_deinit(); + // ESP_LOGE(TAG, "Can't found available GDMA channel"); + // return ESP_FAIL; + // } + // } + + if (!periph_ll_periph_enabled(PERIPH_GDMA_MODULE)) { + periph_ll_disable_clk_set_rst(PERIPH_GDMA_MODULE); + periph_ll_enable_clk_clear_rst(PERIPH_GDMA_MODULE); } + // if (REG_GET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN) == 0) { + // REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN); + // REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_DMA_CLK_EN); + // REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); + // REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); + // } ll_cam_dma_reset(cam); return ESP_OK; } @@ -267,12 +295,16 @@ static esp_err_t ll_cam_converter_config(cam_obj_t *cam, const camera_config_t * esp_err_t ll_cam_config(cam_obj_t *cam, const camera_config_t *config) { esp_err_t ret = ESP_OK; - if (REG_GET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN) == 0) { - REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN); - REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN); - REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_LCD_CAM_RST); - REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_LCD_CAM_RST); + if (!periph_ll_periph_enabled(PERIPH_LCD_CAM_MODULE)) { + periph_ll_disable_clk_set_rst(PERIPH_LCD_CAM_MODULE); + periph_ll_enable_clk_clear_rst(PERIPH_LCD_CAM_MODULE); } + // if (REG_GET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN) == 0) { + // REG_CLR_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN); + // REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_LCD_CAM_CLK_EN); + // REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_LCD_CAM_RST); + // REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_LCD_CAM_RST); + // } LCD_CAM.cam_ctrl.val = 0; @@ -369,7 +401,7 @@ esp_err_t ll_cam_init_isr(cam_obj_t *cam) { esp_err_t ret = ESP_OK; ret = esp_intr_alloc_intrstatus(gdma_periph_signals.groups[0].pairs[cam->dma_num].rx_irq_id, - ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_IRAM, + ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | CAMERA_ISR_IRAM_FLAG, (uint32_t)&GDMA.channel[cam->dma_num].in.int_st, GDMA_IN_SUC_EOF_CH0_INT_ST_M, ll_cam_dma_isr, cam, &cam->dma_intr_handle); if (ret != ESP_OK) { @@ -378,7 +410,7 @@ esp_err_t ll_cam_init_isr(cam_obj_t *cam) } ret = esp_intr_alloc_intrstatus(ETS_LCD_CAM_INTR_SOURCE, - ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_IRAM, + ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_SHARED | CAMERA_ISR_IRAM_FLAG, (uint32_t)&LCD_CAM.lc_dma_int_st.val, LCD_CAM_CAM_VSYNC_INT_ST_M, ll_cam_vsync_isr, cam, &cam->cam_intr_handle); if (ret != ESP_OK) { diff --git a/target/private_include/ll_cam.h b/target/private_include/ll_cam.h index da80a667ef..df6135f27e 100644 --- a/target/private_include/ll_cam.h +++ b/target/private_include/ll_cam.h @@ -38,6 +38,17 @@ #if __has_include("esp_private/periph_ctrl.h") # include "esp_private/periph_ctrl.h" #endif +#if __has_include("esp_private/gdma.h") +# include "esp_private/gdma.h" +#endif + +#if CONFIG_LCD_CAM_ISR_IRAM_SAFE +#define CAMERA_ISR_IRAM_FLAG ESP_INTR_FLAG_IRAM +#define CAMERA_ISR_IRAM_ATTR IRAM_ATTR +#else +#define CAMERA_ISR_IRAM_FLAG 0 +#define CAMERA_ISR_IRAM_ATTR +#endif #define CAMERA_DBG_PIN_ENABLE 0 #if CAMERA_DBG_PIN_ENABLE @@ -104,6 +115,9 @@ typedef struct { uint8_t dma_num;//ESP32-S3 intr_handle_t dma_intr_handle;//ESP32-S3 +#if SOC_GDMA_SUPPORTED + gdma_channel_handle_t dma_channel_handle;//ESP32-S3 +#endif uint8_t jpeg_mode; uint8_t vsync_pin;