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");
}
ESP32s3 LCD_CAM interrupt
Re: ESP32s3 LCD_CAM interrupt
Hello,
I have met the same problem. Since LCD_CAM_CAM_REC_DATA_BYTELEN has maximum 0xffff value, the alternative way to get in_suc_eof interrupt is to use LCD_CAM_CAM_VS_EOF_EN, but it doesn't work. I have tried different types of signal (inverted ot not). I think it is an ESP32-S3 issue.
The only way that I can fugire out is to catch GPIO edge interrupt on VSYNC pin. Now I don't use GDMA in_suc_eof or LCD_CAM module interrupts. In my case it works fine, I am using AR0135 image sensor in snapshot(triggered) mode with windows of different size.
Thanks to GPIO system that doesn't switch off dedicated pins from basic IO interrupts.
Yuricsson
I have met the same problem. Since LCD_CAM_CAM_REC_DATA_BYTELEN has maximum 0xffff value, the alternative way to get in_suc_eof interrupt is to use LCD_CAM_CAM_VS_EOF_EN, but it doesn't work. I have tried different types of signal (inverted ot not). I think it is an ESP32-S3 issue.
The only way that I can fugire out is to catch GPIO edge interrupt on VSYNC pin. Now I don't use GDMA in_suc_eof or LCD_CAM module interrupts. In my case it works fine, I am using AR0135 image sensor in snapshot(triggered) mode with windows of different size.
Thanks to GPIO system that doesn't switch off dedicated pins from basic IO interrupts.
Yuricsson
Who is online
Users browsing this forum: No registered users and 110 guests