ESP32s3 LCD_CAM interrupt
Posted: Sat Jan 27, 2024 2:06 am
I am developing ESP32s3 with ArduinoIDE Ver1.8.19.
ArduinoIDE ESP32 board library version is 2.0.14
When registering LCD_CAM module interrupts, I use "esp_intr_alloc" to register the interrupt handler function as shown below, but the LCD_CAM module interrupt does not occur even when VSYNC is received from CIS.
*Since the LCD_CAM module's register settings are set to "LCD_CAM.lc_dma_int_ena.cam_vsync_int_ena = 1;", an interrupt is generated when the LCD_CAM module receives CIS VSYNC?
//◇LCD_CAM_LC_DMA_INT_ENA
LCD_CAM.lc_dma_int_ena.lcd_vsync_int_ena = 0;
LCD_CAM.lc_dma_int_ena.lcd_trans_done_int_ena = 0;
LCD_CAM.lc_dma_int_ena.cam_vsync_int_ena = 1;
LCD_CAM.lc_dma_int_ena.cam_hs_int_ena = 0;
// Allocate LCD_CAM interrupt, keep it disabled
esp_intr_alloc(ETS_LCD_CAM_INTR_SOURCE,
ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_IRAM,
&VSYNCHandler, NULL, &lcd_cam_intr_handle);
esp_intr_enable(lcd_cam_intr_handle);
How can I generate an LCD_CAM module interrupt?
Thank you.
This is the entire related source code
void ESP32CAM_Init(ESP32CAM_PIN *param , uint16_t horizon_size , uint16_t vertical_size)
{
dma_buf_size = horizon_size;
periph_module_enable(PERIPH_LCD_CAM_MODULE); // Enable LCD_CAM
periph_module_reset(PERIPH_LCD_CAM_MODULE); // Reset LCD_CAM
// Reset CAM bus
LCD_CAM.cam_ctrl1.cam_reset = 1;
//① CAM_CLK setting (register setting)
// CAM module registers configuration
//◇LCD_CAM_CAM_CTRL
LCD_CAM.cam_ctrl.cam_stop_en = 0;
LCD_CAM.cam_ctrl.cam_vsync_filter_thres = 0;
LCD_CAM.cam_ctrl.cam_byte_order = 0;
LCD_CAM.cam_ctrl.cam_bit_order = 0;
LCD_CAM.cam_ctrl.cam_line_int_en = 1;
LCD_CAM.cam_ctrl.cam_vs_eof_en = 1;
LCD_CAM.cam_ctrl.cam_clkm_div_num = 2; // CAM_CLK_IDX = 20MHz
LCD_CAM.cam_ctrl.cam_clkm_div_b = 0;
LCD_CAM.cam_ctrl.cam_clkm_div_a = 0;
LCD_CAM.cam_ctrl.cam_clk_sel = 1; // XTAL_CLK source (40MHz)
//◇LCD_CAM_CAM_CTRL1
LCD_CAM.cam_ctrl1.cam_rec_data_bytelen = horizon_size;
LCD_CAM.cam_ctrl1.cam_line_int_num = 0; // Number of hsyncs that generate hs interrupts
LCD_CAM.cam_ctrl1.cam_clk_inv = 0;
LCD_CAM.cam_ctrl1.cam_vsync_filter_en = 1;
LCD_CAM.cam_ctrl1.cam_2byte_en = 0;
LCD_CAM.cam_ctrl1.cam_de_inv = 0;
LCD_CAM.cam_ctrl1.cam_hsync_inv = 0;
LCD_CAM.cam_ctrl1.cam_vsync_inv = 0;
//◇LCD_CAM_CAM_RGB_YUV
LCD_CAM.cam_rgb_yuv.cam_conv_8bits_data_inv = 0;
LCD_CAM.cam_rgb_yuv.cam_conv_yuv2yuv_mode = 0;
LCD_CAM.cam_rgb_yuv.cam_conv_yuv_mode = 0;
LCD_CAM.cam_rgb_yuv.cam_conv_protocol_mode = 0;
LCD_CAM.cam_rgb_yuv.cam_conv_data_out_mode = 1;
LCD_CAM.cam_rgb_yuv.cam_conv_data_in_mode = 1;
LCD_CAM.cam_rgb_yuv.cam_conv_mode_8bits_on = 1;
LCD_CAM.cam_rgb_yuv.cam_conv_trans_mode = 0;
LCD_CAM.cam_rgb_yuv.cam_conv_bypass = 0;
//②Pin setting (set which pin is the data line of the camera module)
// Route CAM signals to GPIO pins
const struct
{
uint32_t pin;
uint8_t signal;
} mux[] = {
{ param->d0_pin, CAM_DATA_IN0_IDX }, // Connect CAM_DATA_IN0 to d0_pin
{ param->d1_pin, CAM_DATA_IN1_IDX }, // Connect CAM_DATA_IN1 to d1_pin
{ param->d2_pin, CAM_DATA_IN2_IDX }, // Connect CAM_DATA_IN2 to d2_pin
{ param->d3_pin, CAM_DATA_IN3_IDX }, // Connect CAM_DATA_IN3 to d3_pin
{ param->d4_pin, CAM_DATA_IN4_IDX }, // Connect CAM_DATA_IN4 to d4_pin
{ param->d5_pin, CAM_DATA_IN5_IDX }, // Connect CAM_DATA_IN5 to d5_pin
{ param->d6_pin, CAM_DATA_IN6_IDX }, // Connect CAM_DATA_IN6 to d6_pin
{ param->d7_pin, CAM_DATA_IN7_IDX }, // Connect CAM_DATA_IN7 to d7_pin
{ param->pclk_pin, CAM_PCLK_IDX }, // Connect CAM_PCLK to pclk_pin
{ param->href_pin, CAM_H_ENABLE_IDX }, // Connect CAM_H_ENABLE to href_pin
{ param->vsync_pin, CAM_V_SYNC_IDX }, // Connect CAM_V_SYNC_IDX to vsync_pin
{ GPIO_MATRIX_CONST_ONE_INPUT, CAM_H_SYNC_IDX }, // Connect CAM_H_SYNC to GPIO_MATRIX_CONST_ONE_INPUT
{ GPIO_MATRIX_CONST_ONE_INPUT, CAM_V_SYNC_IDX } // Connect CAM_V_SYNC to GPIO_MATRIX_CONST_ONE_INPUT
};
for (int i = 0; i < 13; i++)
{
if (mux.pin != GPIO_MATRIX_CONST_ONE_INPUT)
{
esp_rom_gpio_pad_select_gpio(mux.pin);
}
esp_rom_gpio_connect_in_signal(mux.pin, mux.signal, false);
}
esp_rom_gpio_pad_select_gpio(param->xclk_pin);
esp_rom_gpio_pad_set_drv(param->xclk_pin, 0); //Set drive length (- 0: 5mA - 1: 10mA - 2: 20mA - 3: 40mA)
esp_rom_gpio_connect_out_signal(param->xclk_pin, CAM_CLK_IDX, false, false);
//③Set the value of LCD_CAM_CAM_VH_DE_MODE_EN according to HSYNC.
LCD_CAM.cam_ctrl1.cam_vh_de_mode_en = 1;
//Set the value of ④LCD_CAM_CAM_UPDATE.
LCD_CAM.cam_ctrl.cam_update = 1; // Update registers
//⑤Reset
LCD_CAM.cam_ctrl1.cam_reset = 0; //Camera module reset signal
LCD_CAM.cam_ctrl1.cam_afifo_reset = 0; //Async Rx FIFO reset signal
//⑥Interrupt settings
//◇LCD_CAM_LC_DMA_INT_ENA
LCD_CAM.lc_dma_int_ena.lcd_vsync_int_ena = 0;
LCD_CAM.lc_dma_int_ena.lcd_trans_done_int_ena = 0;
LCD_CAM.lc_dma_int_ena.cam_vsync_int_ena = 1;
LCD_CAM.lc_dma_int_ena.cam_hs_int_ena = 0;
// Allocate LCD_CAM interrupt, keep it disabled
esp_intr_alloc(ETS_LCD_CAM_INTR_SOURCE,
ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_IRAM,
&VSYNCHandler, NULL, &lcd_cam_intr_handle);
esp_intr_enable(lcd_cam_intr_handle);
//◇LCD_CAM_LC_DMA_INT_RAW_REG(Read Only)
//LCD_CAM_LCD_VSYNC_INT_RAW
//LCD_CAM_LCD_TRANS_DONE_INT_RAW
//LCD_CAM_CAM_VSYNC_INT_RAW
//LCD_CAM_CAM_HS_INT_RAW
//◇LCD_CAM_LC_DMA_INT_ST(Read Only)
//LCD_CAM_LCD_VSYNC_INT_ST
//LCD_CAM_LCD_TRANS_DONE_INT_ST
//LCD_CAM_CAM_VSYNC_INT_ST
//LCD_CAM_CAM_HS_INT_ST
//◇LCD_CAM_LC_DMA_INT_CLR(Write Only)
//LCD_CAM_LCD_VSYNC_INT_CLR
//LCD_CAM_LCD_TRANS_DONE_INT_CLR
//LCD_CAM_CAM_VSYNC_INT_CLR
//LCD_CAM_CAM_HS_INT_CLR
//◇LCD_CAM_LC_REG_DATE //*I don't know if it's necessary Is it a register to include timer.h and set the date and time?
//LCD_CAM_LC_DATE = ;
//⑦GDMA settings (register settings)
//■SYSTEM
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); //1,Set SYSTEM_DMA_CLK_E in the SYSTEM_PERIP_CLK_EN1_REG register to enable the DMA clock.
REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); //2,Set SYSTEM_DMA_RST in the SYSTEM_PERIP_RST_EN1_REG register and reset the DMA.
REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);
}
//■DMA
//Initialize GDMA channel
GDMA.channel[cam_dma_num].in.int_clr.val = ~0;
GDMA.channel[cam_dma_num].in.int_ena.val = 0;
//◇GDMA_IN_CONF0_CHn_REG
GDMA.channel[cam_dma_num].in.conf0.indscr_burst_en = 0;
GDMA.channel[cam_dma_num].in.conf0.in_data_burst_en = 0;
GDMA.channel[cam_dma_num].in.conf0.mem_trans_en = 1;
//◇GDMA_IN_LINK_CHn_REG
GDMA.channel[cam_dma_num].in.link.auto_ret = 1;
GDMA.channel[cam_dma_num].in.link.stop = 0;
GDMA.channel[cam_dma_num].in.link.restart = 0;
//3, To reset the GDMA receive channel and FIFO pointer state machine, first set GDMA_IN_RST_CHn in the GDMA_IN_CONF0_CHx_REG register to 1 and then to 0.
GDMA.channel[cam_dma_num].in.conf0.in_rst = 1;
GDMA.channel[cam_dma_num].in.conf0.in_rst = 0;
err = initDMAdesc();
if (err != ESP_OK) {
//Serial.println("Failed to initialize I2S and DMA");
Serial.println("Failed to initialize DMA");
}
//4, Load inlink and configure GDMA_IN_LINK_ADDR_CHn in the GDMA_IN_LINK_CHn_REG register with the address of the first receive descriptor.
GDMA.channel[cam_dma_num].in.link.addr = ((uint32_t)dma_desc) & 0xfffff;
//Check channel owner
GDMA.channel[cam_dma_num].in.conf1.in_check_owner = 0;
//◇GDMA_IN_PERI_SEL_CHn_REG
//5,Set GDMA_PERI_IN_SEL_CHn in the GDMA_IN_PERI_SEL_CHn_REG register to LCD_CAM.
GDMA.channel[cam_dma_num].in.peri_sel.sel = 5;
//6,Set GDMA_INLINK_START_CHn in the GDMA_IN_LINK_CHn_REG register to enable the GDMA receive channel for data transfer.
GDMA.channel[cam_dma_num].in.link.start = 1;
//7,Wait for the GDMA_IN_SUC_EOF_CHn_INT interrupt indicating that a data frame or packet has been received.
GDMA.channel[cam_dma_num].in.int_clr.in_suc_eof = 1; //Clear interrupt flag
GDMA.channel[cam_dma_num].in.int_ena.in_suc_eof = 1; //EOF interrupt enable
// Allocate GMDA interrupt, keep it disabled
esp_intr_alloc(ETS_DMA_IN_CH0_INTR_SOURCE,
ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_LEVEL2 | ESP_INTR_FLAG_IRAM,
&ReceiveHandler, NULL, &gdma_intr_handle);
esp_intr_enable(gdma_intr_handle);
//Set the value of ④LCD_CAM_CAM_UPDATE.
LCD_CAM.cam_ctrl.cam_update = 1; // Update registers
//⑤Reset
LCD_CAM.cam_ctrl1.cam_reset = 0; //Camera module reset signal
LCD_CAM.cam_ctrl1.cam_afifo_reset = 0; //Async Rx FIFO reset signal
Serial.println("initialize LCD_CAM & DMA");
}
ArduinoIDE ESP32 board library version is 2.0.14
When registering LCD_CAM module interrupts, I use "esp_intr_alloc" to register the interrupt handler function as shown below, but the LCD_CAM module interrupt does not occur even when VSYNC is received from CIS.
*Since the LCD_CAM module's register settings are set to "LCD_CAM.lc_dma_int_ena.cam_vsync_int_ena = 1;", an interrupt is generated when the LCD_CAM module receives CIS VSYNC?
//◇LCD_CAM_LC_DMA_INT_ENA
LCD_CAM.lc_dma_int_ena.lcd_vsync_int_ena = 0;
LCD_CAM.lc_dma_int_ena.lcd_trans_done_int_ena = 0;
LCD_CAM.lc_dma_int_ena.cam_vsync_int_ena = 1;
LCD_CAM.lc_dma_int_ena.cam_hs_int_ena = 0;
// Allocate LCD_CAM interrupt, keep it disabled
esp_intr_alloc(ETS_LCD_CAM_INTR_SOURCE,
ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_IRAM,
&VSYNCHandler, NULL, &lcd_cam_intr_handle);
esp_intr_enable(lcd_cam_intr_handle);
How can I generate an LCD_CAM module interrupt?
Thank you.
This is the entire related source code
void ESP32CAM_Init(ESP32CAM_PIN *param , uint16_t horizon_size , uint16_t vertical_size)
{
dma_buf_size = horizon_size;
periph_module_enable(PERIPH_LCD_CAM_MODULE); // Enable LCD_CAM
periph_module_reset(PERIPH_LCD_CAM_MODULE); // Reset LCD_CAM
// Reset CAM bus
LCD_CAM.cam_ctrl1.cam_reset = 1;
//① CAM_CLK setting (register setting)
// CAM module registers configuration
//◇LCD_CAM_CAM_CTRL
LCD_CAM.cam_ctrl.cam_stop_en = 0;
LCD_CAM.cam_ctrl.cam_vsync_filter_thres = 0;
LCD_CAM.cam_ctrl.cam_byte_order = 0;
LCD_CAM.cam_ctrl.cam_bit_order = 0;
LCD_CAM.cam_ctrl.cam_line_int_en = 1;
LCD_CAM.cam_ctrl.cam_vs_eof_en = 1;
LCD_CAM.cam_ctrl.cam_clkm_div_num = 2; // CAM_CLK_IDX = 20MHz
LCD_CAM.cam_ctrl.cam_clkm_div_b = 0;
LCD_CAM.cam_ctrl.cam_clkm_div_a = 0;
LCD_CAM.cam_ctrl.cam_clk_sel = 1; // XTAL_CLK source (40MHz)
//◇LCD_CAM_CAM_CTRL1
LCD_CAM.cam_ctrl1.cam_rec_data_bytelen = horizon_size;
LCD_CAM.cam_ctrl1.cam_line_int_num = 0; // Number of hsyncs that generate hs interrupts
LCD_CAM.cam_ctrl1.cam_clk_inv = 0;
LCD_CAM.cam_ctrl1.cam_vsync_filter_en = 1;
LCD_CAM.cam_ctrl1.cam_2byte_en = 0;
LCD_CAM.cam_ctrl1.cam_de_inv = 0;
LCD_CAM.cam_ctrl1.cam_hsync_inv = 0;
LCD_CAM.cam_ctrl1.cam_vsync_inv = 0;
//◇LCD_CAM_CAM_RGB_YUV
LCD_CAM.cam_rgb_yuv.cam_conv_8bits_data_inv = 0;
LCD_CAM.cam_rgb_yuv.cam_conv_yuv2yuv_mode = 0;
LCD_CAM.cam_rgb_yuv.cam_conv_yuv_mode = 0;
LCD_CAM.cam_rgb_yuv.cam_conv_protocol_mode = 0;
LCD_CAM.cam_rgb_yuv.cam_conv_data_out_mode = 1;
LCD_CAM.cam_rgb_yuv.cam_conv_data_in_mode = 1;
LCD_CAM.cam_rgb_yuv.cam_conv_mode_8bits_on = 1;
LCD_CAM.cam_rgb_yuv.cam_conv_trans_mode = 0;
LCD_CAM.cam_rgb_yuv.cam_conv_bypass = 0;
//②Pin setting (set which pin is the data line of the camera module)
// Route CAM signals to GPIO pins
const struct
{
uint32_t pin;
uint8_t signal;
} mux[] = {
{ param->d0_pin, CAM_DATA_IN0_IDX }, // Connect CAM_DATA_IN0 to d0_pin
{ param->d1_pin, CAM_DATA_IN1_IDX }, // Connect CAM_DATA_IN1 to d1_pin
{ param->d2_pin, CAM_DATA_IN2_IDX }, // Connect CAM_DATA_IN2 to d2_pin
{ param->d3_pin, CAM_DATA_IN3_IDX }, // Connect CAM_DATA_IN3 to d3_pin
{ param->d4_pin, CAM_DATA_IN4_IDX }, // Connect CAM_DATA_IN4 to d4_pin
{ param->d5_pin, CAM_DATA_IN5_IDX }, // Connect CAM_DATA_IN5 to d5_pin
{ param->d6_pin, CAM_DATA_IN6_IDX }, // Connect CAM_DATA_IN6 to d6_pin
{ param->d7_pin, CAM_DATA_IN7_IDX }, // Connect CAM_DATA_IN7 to d7_pin
{ param->pclk_pin, CAM_PCLK_IDX }, // Connect CAM_PCLK to pclk_pin
{ param->href_pin, CAM_H_ENABLE_IDX }, // Connect CAM_H_ENABLE to href_pin
{ param->vsync_pin, CAM_V_SYNC_IDX }, // Connect CAM_V_SYNC_IDX to vsync_pin
{ GPIO_MATRIX_CONST_ONE_INPUT, CAM_H_SYNC_IDX }, // Connect CAM_H_SYNC to GPIO_MATRIX_CONST_ONE_INPUT
{ GPIO_MATRIX_CONST_ONE_INPUT, CAM_V_SYNC_IDX } // Connect CAM_V_SYNC to GPIO_MATRIX_CONST_ONE_INPUT
};
for (int i = 0; i < 13; i++)
{
if (mux.pin != GPIO_MATRIX_CONST_ONE_INPUT)
{
esp_rom_gpio_pad_select_gpio(mux.pin);
}
esp_rom_gpio_connect_in_signal(mux.pin, mux.signal, false);
}
esp_rom_gpio_pad_select_gpio(param->xclk_pin);
esp_rom_gpio_pad_set_drv(param->xclk_pin, 0); //Set drive length (- 0: 5mA - 1: 10mA - 2: 20mA - 3: 40mA)
esp_rom_gpio_connect_out_signal(param->xclk_pin, CAM_CLK_IDX, false, false);
//③Set the value of LCD_CAM_CAM_VH_DE_MODE_EN according to HSYNC.
LCD_CAM.cam_ctrl1.cam_vh_de_mode_en = 1;
//Set the value of ④LCD_CAM_CAM_UPDATE.
LCD_CAM.cam_ctrl.cam_update = 1; // Update registers
//⑤Reset
LCD_CAM.cam_ctrl1.cam_reset = 0; //Camera module reset signal
LCD_CAM.cam_ctrl1.cam_afifo_reset = 0; //Async Rx FIFO reset signal
//⑥Interrupt settings
//◇LCD_CAM_LC_DMA_INT_ENA
LCD_CAM.lc_dma_int_ena.lcd_vsync_int_ena = 0;
LCD_CAM.lc_dma_int_ena.lcd_trans_done_int_ena = 0;
LCD_CAM.lc_dma_int_ena.cam_vsync_int_ena = 1;
LCD_CAM.lc_dma_int_ena.cam_hs_int_ena = 0;
// Allocate LCD_CAM interrupt, keep it disabled
esp_intr_alloc(ETS_LCD_CAM_INTR_SOURCE,
ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_LEVEL1 | ESP_INTR_FLAG_IRAM,
&VSYNCHandler, NULL, &lcd_cam_intr_handle);
esp_intr_enable(lcd_cam_intr_handle);
//◇LCD_CAM_LC_DMA_INT_RAW_REG(Read Only)
//LCD_CAM_LCD_VSYNC_INT_RAW
//LCD_CAM_LCD_TRANS_DONE_INT_RAW
//LCD_CAM_CAM_VSYNC_INT_RAW
//LCD_CAM_CAM_HS_INT_RAW
//◇LCD_CAM_LC_DMA_INT_ST(Read Only)
//LCD_CAM_LCD_VSYNC_INT_ST
//LCD_CAM_LCD_TRANS_DONE_INT_ST
//LCD_CAM_CAM_VSYNC_INT_ST
//LCD_CAM_CAM_HS_INT_ST
//◇LCD_CAM_LC_DMA_INT_CLR(Write Only)
//LCD_CAM_LCD_VSYNC_INT_CLR
//LCD_CAM_LCD_TRANS_DONE_INT_CLR
//LCD_CAM_CAM_VSYNC_INT_CLR
//LCD_CAM_CAM_HS_INT_CLR
//◇LCD_CAM_LC_REG_DATE //*I don't know if it's necessary Is it a register to include timer.h and set the date and time?
//LCD_CAM_LC_DATE = ;
//⑦GDMA settings (register settings)
//■SYSTEM
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); //1,Set SYSTEM_DMA_CLK_E in the SYSTEM_PERIP_CLK_EN1_REG register to enable the DMA clock.
REG_SET_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST); //2,Set SYSTEM_DMA_RST in the SYSTEM_PERIP_RST_EN1_REG register and reset the DMA.
REG_CLR_BIT(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST);
}
//■DMA
//Initialize GDMA channel
GDMA.channel[cam_dma_num].in.int_clr.val = ~0;
GDMA.channel[cam_dma_num].in.int_ena.val = 0;
//◇GDMA_IN_CONF0_CHn_REG
GDMA.channel[cam_dma_num].in.conf0.indscr_burst_en = 0;
GDMA.channel[cam_dma_num].in.conf0.in_data_burst_en = 0;
GDMA.channel[cam_dma_num].in.conf0.mem_trans_en = 1;
//◇GDMA_IN_LINK_CHn_REG
GDMA.channel[cam_dma_num].in.link.auto_ret = 1;
GDMA.channel[cam_dma_num].in.link.stop = 0;
GDMA.channel[cam_dma_num].in.link.restart = 0;
//3, To reset the GDMA receive channel and FIFO pointer state machine, first set GDMA_IN_RST_CHn in the GDMA_IN_CONF0_CHx_REG register to 1 and then to 0.
GDMA.channel[cam_dma_num].in.conf0.in_rst = 1;
GDMA.channel[cam_dma_num].in.conf0.in_rst = 0;
err = initDMAdesc();
if (err != ESP_OK) {
//Serial.println("Failed to initialize I2S and DMA");
Serial.println("Failed to initialize DMA");
}
//4, Load inlink and configure GDMA_IN_LINK_ADDR_CHn in the GDMA_IN_LINK_CHn_REG register with the address of the first receive descriptor.
GDMA.channel[cam_dma_num].in.link.addr = ((uint32_t)dma_desc) & 0xfffff;
//Check channel owner
GDMA.channel[cam_dma_num].in.conf1.in_check_owner = 0;
//◇GDMA_IN_PERI_SEL_CHn_REG
//5,Set GDMA_PERI_IN_SEL_CHn in the GDMA_IN_PERI_SEL_CHn_REG register to LCD_CAM.
GDMA.channel[cam_dma_num].in.peri_sel.sel = 5;
//6,Set GDMA_INLINK_START_CHn in the GDMA_IN_LINK_CHn_REG register to enable the GDMA receive channel for data transfer.
GDMA.channel[cam_dma_num].in.link.start = 1;
//7,Wait for the GDMA_IN_SUC_EOF_CHn_INT interrupt indicating that a data frame or packet has been received.
GDMA.channel[cam_dma_num].in.int_clr.in_suc_eof = 1; //Clear interrupt flag
GDMA.channel[cam_dma_num].in.int_ena.in_suc_eof = 1; //EOF interrupt enable
// Allocate GMDA interrupt, keep it disabled
esp_intr_alloc(ETS_DMA_IN_CH0_INTR_SOURCE,
ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_LEVEL2 | ESP_INTR_FLAG_IRAM,
&ReceiveHandler, NULL, &gdma_intr_handle);
esp_intr_enable(gdma_intr_handle);
//Set the value of ④LCD_CAM_CAM_UPDATE.
LCD_CAM.cam_ctrl.cam_update = 1; // Update registers
//⑤Reset
LCD_CAM.cam_ctrl1.cam_reset = 0; //Camera module reset signal
LCD_CAM.cam_ctrl1.cam_afifo_reset = 0; //Async Rx FIFO reset signal
Serial.println("initialize LCD_CAM & DMA");
}