ESP32-S3 LCD and I2S FULL documentation

Baldhead
Posts: 468
Joined: Sun Mar 31, 2019 5:16 am

Re: ESP32-S3 LCD and I2S FULL documentation

Postby Baldhead » Fri Dec 10, 2021 9:44 pm

Hi,

I am not able to write anything to the esp32-s3 lcd port.
Could someone from espressif give me a suggestion of code to write a single byte to the lcd port ?

I already initialized the LCD peripheral.

Example:

Code: Select all

inline void hw_lcd_write_command( uint32_t command )      
{
    LCD_CAM.lcd_user.lcd_cmd = 1;  // 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 = 0;    
    LCD_CAM.lcd_cmd_val.lcd_cmd_value = command;  // lcd_cmd_value : R/W; bitpos: [31:0]; default: 0. The LCD write command value. 
        
    LCD_CAM.lcd_user.lcd_start = 1;  // R/W; bitpos: [27]; default: 0. LCD start sending data enable signal, valid in high level.
    //LCD_CAM.lcd_user.lcd_update = 1;   // update parameters before start transaction
    //LCD_CAM.lcd_user.lcd_start = 1;
}
Thank's.

stuartiannaylor
Posts: 17
Joined: Wed Dec 02, 2020 6:02 pm

Re: ESP32-S3 LCD and I2S FULL documentation

Postby stuartiannaylor » Sat Dec 11, 2021 12:23 am

Best I can do is have a look at the esp32-s3-box code as there is a working example there.

https://github.com/espressif/esp-box

Baldhead
Posts: 468
Joined: Sun Mar 31, 2019 5:16 am

Re: ESP32-S3 LCD and I2S FULL documentation

Postby Baldhead » Sun Dec 12, 2021 12:58 am

Hi @stuartiannaylor,

esp32-s3-box use spi to drive an external lcd:
https://github.com/espressif/esp-box/bl ... 211011.pdf

I want to use the lcd peripheral of esp32-s3 in parallel 8 bits mode(intel 8080 like).

Baldhead
Posts: 468
Joined: Sun Mar 31, 2019 5:16 am

Re: ESP32-S3 LCD and I2S FULL documentation

Postby Baldhead » Mon Dec 13, 2021 6:10 am

Baldhead wrote:
Fri Dec 10, 2021 9:44 pm
Hi,

I am not able to write anything to the esp32-s3 lcd port.
Could someone from espressif give me a suggestion of code to write a single byte to the lcd port ?

I already initialized the LCD peripheral.

Example:

Code: Select all

inline void hw_lcd_write_command( uint32_t command )      
{
    LCD_CAM.lcd_user.lcd_cmd = 1;  // 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 = 0;    
    LCD_CAM.lcd_cmd_val.lcd_cmd_value = command;  // lcd_cmd_value : R/W; bitpos: [31:0]; default: 0. The LCD write command value. 
        
    LCD_CAM.lcd_user.lcd_start = 1;  // R/W; bitpos: [27]; default: 0. LCD start sending data enable signal, valid in high level.
    //LCD_CAM.lcd_user.lcd_update = 1;   // update parameters before start transaction
    //LCD_CAM.lcd_user.lcd_start = 1;
}
Thank's.
@ESP_Sprite

Baldhead
Posts: 468
Joined: Sun Mar 31, 2019 5:16 am

Re: ESP32-S3 LCD and I2S FULL documentation

Postby Baldhead » Mon Dec 13, 2021 11:44 pm

Hi @ESP_Sprite,

Apparently it's working to send a command:
* Clock io = OK
* data/command io = 0 (ok).
* chip select io: always 0.
* data 0.....7 = ok.

Code: Select all

inline void hw_lcd_write_command( uint32_t command )      
{
    LCD_CAM.lcd_user.lcd_cmd = 1;   // 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 = 0;  // 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 = command;  // lcd_cmd_value : R/W; bitpos: [31:0]; default: 0. The LCD write command value. 
        
    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.
}

But to send a parameter, it's not working:
* Clock io = OK i think ( "2 clock cycles with LCD_CAM.lcd_user.lcd_always_out_en = 0" , and 1 clock cycle with LCD_CAM.lcd_user.lcd_always_out_en = 1" ).
* data/command io = 1 (ok).
* chip select io: always 0.
* data 0.....7 = NOT OK, no output data.

Code: Select all

inline void hw_lcd_write_data( uint32_t data )      
{
    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 = data;  // R/W; bitpos: [31:0]; default: 0. The LCD write command value. 
      
    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.
}
Thank's for the help.

Baldhead
Posts: 468
Joined: Sun Mar 31, 2019 5:16 am

Re: ESP32-S3 LCD and I2S FULL documentation

Postby Baldhead » Wed Dec 15, 2021 10:59 pm

ESP_Sprite wrote:
Fri Dec 03, 2021 2:14 am
Those 'variables' are created in the linker script; they always point to the hardware registers of those peripherals.

For tx_idle, you can probably use the LCD_CAM_LCD_TRANS_DONE_INT interrupt. If you want to poll it, I think it's enough simply to not enable the interrupt and use the status register to see if it's done. Make sure to clear it before you start a new transaction.
@ESP_Sprite,

When i enable LCD_CAM interrupt "LCD_CAM.lc_dma_int_ena.lcd_trans_done_int_ena = 1", the LCD_CAM.lc_dma_int_st.lcd_trans_done_int_st change state and the interrupt is called after an i/o transfer, but when i dont enable LCD_CAM interrupt "LCD_CAM.lc_dma_int_ena.lcd_trans_done_int_ena = 0" because i want to polling the "LCD_CAM.lc_dma_int_st.lcd_trans_done_int_st" bit, the state of "LCD_CAM.lc_dma_int_st.lcd_trans_done_int_st" dont change after an i/o transfer.

Could you tell me why ?

Thank's.

ESP_Sprite
Posts: 9766
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32-S3 LCD and I2S FULL documentation

Postby ESP_Sprite » Thu Dec 16, 2021 1:51 am

I think bit like lcd_trans_done_int_st are masked by lcd_trans_done_int_ena... can you check lcd_trans_done_int_raw instead? Those bits should not be masked, iirc.

Baldhead
Posts: 468
Joined: Sun Mar 31, 2019 5:16 am

Re: ESP32-S3 LCD and I2S FULL documentation

Postby Baldhead » Thu Dec 16, 2021 6:51 pm

ESP_Sprite wrote:
Thu Dec 16, 2021 1:51 am
I think bit like lcd_trans_done_int_st are masked by lcd_trans_done_int_ena... can you check lcd_trans_done_int_raw instead? Those bits should not be masked, iirc.
Apparently it worked.

Baldhead
Posts: 468
Joined: Sun Mar 31, 2019 5:16 am

Re: ESP32-S3 LCD and I2S FULL documentation

Postby Baldhead » Sat Dec 18, 2021 12:08 am

ESP_Sprite wrote:
Tue Dec 07, 2021 10:04 am
From what I can tell, LCD_CAM_LCD_2BYTE_EN selects between 16 and 8-bit modes. (Suggest you look at components/soc/esp32s3/include/soc/lcd_cam_reg.h if you're looking for data like that, the file has comments.) I don't think we have a FIFO you can manually put bytes into.
@ESP_Sprite,

I dont know if LCD_CAM peripheral have fifo or not.

From what i have researched and tested, i am thinking that the esp32-s3 chip design migrated the fifo from some peripherals to the gdma peripheral.

Example: Here i can verify if the fifo are empty, full or know the number of bytes inside the fifo.

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;    
    
    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.
}

inline bool hw_lcd_dma_L1_fifo_empty( uint32_t channel )
{
    return ( GDMA.channel[channel].out.outfifo_status.outfifo_empty_l1 ); 
}

inline bool hw_lcd_dma_L2_fifo_empty( uint32_t channel )
{
    return ( GDMA.channel[channel].out.outfifo_status.outfifo_empty_l2 ); 
}

inline bool hw_lcd_dma_L3_fifo_empty( uint32_t channel )
{
    return ( GDMA.channel[channel].out.outfifo_status.outfifo_empty_l3 ); 
}

inline bool hw_lcd_dma_L1_fifo_full( uint32_t channel )
{
    return ( GDMA.channel[channel].out.outfifo_status.outfifo_full_l1 ); 
}

inline bool hw_lcd_dma_L2_fifo_full( uint32_t channel )
{
    return ( GDMA.channel[channel].out.outfifo_status.outfifo_full_l2 ); 
}

inline bool hw_lcd_dma_L3_fifo_full( uint32_t channel )
{
    return ( GDMA.channel[channel].out.outfifo_status.outfifo_full_l3 ); 
}

inline uint32_t hw_lcd_dma_L1_fifo_count( uint32_t channel )
{
    return ( GDMA.channel[channel].out.outfifo_status.outfifo_cnt_l1 ); 
}

inline uint32_t hw_lcd_dma_L2_fifo_count( uint32_t channel )
{
    return ( GDMA.channel[channel].out.outfifo_status.outfifo_cnt_l2 ); 
}

inline uint32_t hw_lcd_dma_L3_fifo_count( uint32_t channel )
{
    return ( GDMA.channel[channel].out.outfifo_status.outfifo_cnt_l3 ); 
}

The code below is already putting something in the io but the data is not correct yet.
Here, the GDMA 0 output channel is linked to the LCD_CAM peripheral.

Code: Select all

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;   LCD_CAM interrupt disabled.    

    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 = data;  // 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;  LCD_CAM interrupt disabled. 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;    
    
    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.
}

Baldhead
Posts: 468
Joined: Sun Mar 31, 2019 5:16 am

Re: ESP32-S3 LCD and I2S FULL documentation

Postby Baldhead » Tue Dec 21, 2021 12:17 am

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.

Who is online

Users browsing this forum: No registered users and 6 guests