Hi,
Many questions and few answers from espressif hardware people.
Below is a video i made.
The video start with esp32-s3 turned off, and then i power on the esp.
https://www.youtube.com/watch?v=zvBkQVX1PFY
oscilloscope yellow channel 1 = LCD_CAM clock signal
oscilloscope blue channel 2 = LCD_CAM data 0 signal
Sometimes 8 clock pulses appear, sometimes 9 clock pulses appear.
At the beginning of the video, data 0 = 0 (NOK).
After 7 or 8 "print" to the io, appear 8 or 9 clock pulses and data 0 go to 1(ok).
label:
After that, data 0 = 1 for 7 or 8 prints and again appear 8 or 9 clock pulses with data 0 = 1.
And the cycle repeats.
goto label;
Code: Select all
#define my_led_io_13 13
void app_main(void)
{
gpio_set_direction( (gpio_num_t)my_led_io_13, (gpio_mode_t)GPIO_MODE_OUTPUT );
gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[my_led_io_13], PIN_FUNC_GPIO);
gpio_set_level( (gpio_num_t)my_led_io_13, 0 );
esp_err_t r = hw_lcd_init();
printf("r = %s\n\n", esp_err_to_name(r));
while(1)
{
hw_lcd_write_data( 0x01 );
vTaskDelay( pdMS_TO_TICKS(500) );
gpio_set_level( (gpio_num_t)my_led_io_13, 0 );
vTaskDelay( pdMS_TO_TICKS(500) );
/*
hw_lcd_write_data( 0x00 );
vTaskDelay( pdMS_TO_TICKS(500) );
gpio_set_level( (gpio_num_t)my_led_io_13, 0 );
vTaskDelay( pdMS_TO_TICKS(500) );
*/
}
}
inline void hw_lcd_write_data( uint32_t data )
{
hw_lcd_clear_transfer_end_interrupt_status(); // LCD_CAM.lc_dma_int_clr.lcd_trans_done_int_clr = 1; interrupcao esta desabilitada.
LCD_CAM.lcd_user.lcd_cmd = 0; // R/W; bitpos: [26]; default: 0. 1: Be able to send command in LCD sequence when LCD starts. 0: Disable.
LCD_CAM.lcd_user.lcd_dout = 1; // R/W; bitpos: [24]; default: 0. 1: Be able to send data out in LCD sequence when LCD starts. 0: Disable.
// LCD_CAM.lcd_cmd_val.lcd_cmd_value = 0x01; // R/W; bitpos: [31:0]; default: 0. The LCD write command value.
hw_lcd_dma_tx_push_data( 0, data );
LCD_CAM.lcd_user.lcd_update = 1; // R/W; bitpos: [20]; default: 0. 1: Update LCD registers, will be cleared by hardware. 0 : Not care. Update parameters before start transaction.
LCD_CAM.lcd_user.lcd_start = 1; // R/W; bitpos: [27]; default: 0. LCD start sending data enable signal, valid in high level.
while( hw_lcd_transfer_done_status() ); // !LCD_CAM.lc_dma_int_raw.lcd_trans_done_int_raw; interrupcao esta desabilitada. polling flag.
}
inline void hw_lcd_dma_tx_push_data( uint32_t channel, uint32_t data )
{
// GDMA.channel[channel].out.conf0.out_rst = 1; // This bit is used to reset DMA channel 0 Tx FSM and Tx FIFO pointer.
// GDMA.channel[channel].out.conf0.out_rst = 0;
printf("dma tx idle: %s\n", hw_lcd_dma_tx_idle(0) ? "IDLE" : "BUSY" );
printf("L1_fifo: %s\n", hw_lcd_dma_L1_fifo_empty(0) ? "EMPTY" : "NOT_EMPTY" );
printf("L1_fifo: %s\n", hw_lcd_dma_L1_fifo_full(0) ? "FULL" : "NOT_FULL" );
printf("L1_count: %u\n\n", hw_lcd_dma_L1_fifo_count(0) );
printf("L2_fifo: %s\n", hw_lcd_dma_L2_fifo_empty(0) ? "EMPTY" : "NOT_EMPTY" );
printf("L2_fifo: %s\n", hw_lcd_dma_L2_fifo_full(0) ? "FULL" : "NOT_FULL" );
printf("L2_count: %u\n\n", hw_lcd_dma_L2_fifo_count(0) );
printf("L3_fifo: %s\n", hw_lcd_dma_L3_fifo_empty(0) ? "EMPTY" : "NOT_EMPTY" );
printf("L3_fifo: %s\n", hw_lcd_dma_L3_fifo_full(0) ? "FULL" : "NOT_FULL" );
printf("L3_count: %u\n\n\n", hw_lcd_dma_L3_fifo_count(0) );
printf("ovf_l1: %s\n", GDMA.channel[channel].out.int_raw.outfifo_ovf_l1 ? "OVERFLOW" : "NOT_OVERFLOW" );
printf("ovf_l3: %s\n", GDMA.channel[channel].out.int_raw.outfifo_ovf_l3 ? "OVERFLOW" : "NOT_OVERFLOW" );
printf("udf_l1: %s\n", GDMA.channel[channel].out.int_raw.outfifo_udf_l1 ? "UNDERLOW" : "NOT_UNDERFLOW" );
printf("udf_l3: %s\n\n\n", GDMA.channel[channel].out.int_raw.outfifo_udf_l3 ? "UNDERLOW" : "NOT_UNDERFLOW" );
GDMA.channel[channel].out.push.outfifo_wdata = data; // This register stores the data that need to be pushed into DMA FIFO.
GDMA.channel[channel].out.push.outfifo_push = 1; // Set this bit to push data into DMA FIFO.
}
ESP-IDF MONITOR:
Code: Select all
I (686) HW_LCD_DMA: GDMA HW Version: 0x02101180
I (693) HW_LCD: HW_LCD Information:
I (698) HW_LCD: LCD_CAM HW Version: 33566752
I (703) HW_LCD: HW_LCD_FREQ_HZ = 20 MHz
I (709) HW_LCD: WR io num = 4
I (714) HW_LCD: DC io num = 5
I (718) HW_LCD: CS io num = 6
I (723) HW_LCD: HW_LCD BUS Data Width = 8
I (728) HW_LCD: Data[0] = 7
I (733) HW_LCD: Data[1] = 15
I (737) HW_LCD: Data[2] = 16
I (742) HW_LCD: Data[3] = 17
I (746) HW_LCD: Data[4] = 18
I (751) HW_LCD: Data[5] = 8
I (755) HW_LCD: Data[6] = 3
I (760) HW_LCD: Data[7] = 46
r = ESP_OK
dma tx idle: IDLE
L1_fifo: EMPTY
L1_fifo: NOT_FULL
L1_count: 0
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 1
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 2
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 3
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 4
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 5
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 6
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 7
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: EMPTY
L1_fifo: NOT_FULL
L1_count: 0
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 1
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 2
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 3
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 4
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 5
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 6
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 7
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: EMPTY
L1_fifo: NOT_FULL
L1_count: 0
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 1
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 2
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 3
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 4
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 5
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 6
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: NOT_EMPTY
L1_fifo: NOT_FULL
L1_count: 7
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
dma tx idle: IDLE
L1_fifo: EMPTY
L1_fifo: NOT_FULL
L1_count: 0
L2_fifo: EMPTY
L2_fifo: NOT_FULL
L2_count: 0
L3_fifo: EMPTY
L3_fifo: NOT_FULL
L3_count: 0
ovf_l1: NOT_OVERFLOW
ovf_l3: NOT_OVERFLOW
udf_l1: NOT_UNDERFLOW
udf_l3: NOT_UNDERFLOW
If a reset GDMA "This bit is used to reset DMA channel 0 Tx FSM and Tx FIFO pointer", the io clock are ok but no data appear on data 0 pin.
Code: Select all
inline void hw_lcd_dma_tx_push_data( uint32_t channel, uint32_t data )
{
GDMA.channel[channel].out.conf0.out_rst = 1; // This bit is used to reset DMA channel 0 Tx FSM and Tx FIFO pointer.
GDMA.channel[channel].out.conf0.out_rst = 0;
printf("dma tx idle: %s\n", hw_lcd_dma_tx_idle(0) ? "IDLE" : "BUSY" );
printf("L1_fifo: %s\n", hw_lcd_dma_L1_fifo_empty(0) ? "EMPTY" : "NOT_EMPTY" );
printf("L1_fifo: %s\n", hw_lcd_dma_L1_fifo_full(0) ? "FULL" : "NOT_FULL" );
printf("L1_count: %u\n\n", hw_lcd_dma_L1_fifo_count(0) );
printf("L2_fifo: %s\n", hw_lcd_dma_L2_fifo_empty(0) ? "EMPTY" : "NOT_EMPTY" );
printf("L2_fifo: %s\n", hw_lcd_dma_L2_fifo_full(0) ? "FULL" : "NOT_FULL" );
printf("L2_count: %u\n\n", hw_lcd_dma_L2_fifo_count(0) );
printf("L3_fifo: %s\n", hw_lcd_dma_L3_fifo_empty(0) ? "EMPTY" : "NOT_EMPTY" );
printf("L3_fifo: %s\n", hw_lcd_dma_L3_fifo_full(0) ? "FULL" : "NOT_FULL" );
printf("L3_count: %u\n\n", hw_lcd_dma_L3_fifo_count(0) );
printf("ovf_l1: %s\n", GDMA.channel[channel].out.int_raw.outfifo_ovf_l1 ? "OVERFLOW" : "NOT_OVERFLOW" );
printf("ovf_l3: %s\n", GDMA.channel[channel].out.int_raw.outfifo_ovf_l3 ? "OVERFLOW" : "NOT_OVERFLOW" );
printf("udf_l1: %s\n", GDMA.channel[channel].out.int_raw.outfifo_udf_l1 ? "UNDERLOW" : "NOT_UNDERFLOW" );
printf("udf_l3: %s\n\n\n", GDMA.channel[channel].out.int_raw.outfifo_udf_l3 ? "UNDERLOW" : "NOT_UNDERFLOW" );
GDMA.channel[channel].out.push.outfifo_wdata = data; // This register stores the data that need to be pushed into DMA FIFO.
GDMA.channel[channel].out.push.outfifo_push = 1; // Set this bit to push data into DMA FIFO.
}
If i reset lcd peripheral and lcd_afifo does not change the behavior at all
Code: Select all
inline void hw_lcd_write_data( uint32_t data )
{
// reset hw_lcd peripheral
LCD_CAM.lcd_user.lcd_reset = 1;
LCD_CAM.lcd_user.lcd_reset = 0;
// reset hw_lcd FIFO
LCD_CAM.lcd_misc.lcd_afifo_reset = 1;
LCD_CAM.lcd_misc.lcd_afifo_reset = 0;
hw_lcd_clear_transfer_end_interrupt_status(); // LCD_CAM.lc_dma_int_clr.lcd_trans_done_int_clr = 1; interrupcao esta desabilitada.
LCD_CAM.lcd_user.lcd_cmd = 0; // R/W; bitpos: [26]; default: 0. 1: Be able to send command in LCD sequence when LCD starts. 0: Disable.
LCD_CAM.lcd_user.lcd_dout = 1; // R/W; bitpos: [24]; default: 0. 1: Be able to send data out in LCD sequence when LCD starts. 0: Disable.
// LCD_CAM.lcd_cmd_val.lcd_cmd_value = 0x01; // R/W; bitpos: [31:0]; default: 0. The LCD write command value.
hw_lcd_dma_tx_push_data( 0, data );
LCD_CAM.lcd_user.lcd_update = 1; // R/W; bitpos: [20]; default: 0. 1: Update LCD registers, will be cleared by hardware. 0 : Not care. Update parameters before start transaction.
LCD_CAM.lcd_user.lcd_start = 1; // R/W; bitpos: [27]; default: 0. LCD start sending data enable signal, valid in high level.
while( hw_lcd_transfer_done_status() ); // !LCD_CAM.lc_dma_int_raw.lcd_trans_done_int_raw; interrupcao esta desabilitada. polling flag.
}
Why does this happen ?
How should i program the gdma fifo with lcd_cam ?
Thank's.