Page 2 of 3

Re: i2s parallel only works with one dma descriptor

Posted: Wed Nov 27, 2019 3:15 am
by Baldhead
Hi,

However the i2s module is still sending twice as long.

It looks like the i2s module is sending the descriptor twice.

The D0 channel appears that weird data do not exist anymore.

Apparently the data is correct, the only problem is that data is being sent twice.

Re: i2s parallel only works with one dma descriptor

Posted: Wed Nov 27, 2019 4:19 am
by Baldhead
Hi,

The first burst of dma descriptor seems to be correct. 7680 bytes / 10 000 000 = 768 us.

After first burst of dma descriptor the 7680 bytes / 10 000 000 = 1536 us.


I filled the buffer with 0xFF00.

buffer_a are uint16_t.

Code: Select all

for ( uint32_t i = 0 ; i < 15360 ; i++ )
{        
    buffer_a[i].full = 0xFF00;  // FF byte more significant.  00 byte less significant.
}
The byte order of the first burst of dma descriptor(768 us) seems to be correct( ie: first clock rising edge = 0 and second clock rising edge = 1 ).

The byte order after first burst of dma descriptor(1536 us) seems to be reversed( ie: first clock rising edge = 1 and second clock rising edge = 0 ).

Re: i2s parallel only works with one dma descriptor

Posted: Thu Nov 28, 2019 1:47 am
by Baldhead
Hi,

Please Espressif team.

I've been trying for a long time to make this i2s module work.

I am using the clock source APLL_CLK.
When i enable clock PLL_D2_CLK, only firt burst work and i2s module freezes.

There are a lot of bugs in one single place.

I opened a technical inquire and i dont know if espressif will return to me.

Give me a light, please.


Thank's for the help.

Re: i2s parallel only works with one dma descriptor

Posted: Thu Nov 28, 2019 10:30 pm
by Baldhead
Hi,

Now i put "dma_tx_reset( )" after this instruction:

I2SX.fifo_conf.dscr_en = 0; // Set this bit to disable I2S DMA mode. (R/W).

example:
I2SX.fifo_conf.dscr_en = 0; // Set this bit to disable I2S DMA mode. (R/W).
dma_tx_reset( );

Code: Select all

static void dma_tx_reset( )
{   
    I2SX.lc_conf.out_rst = 1;    // Set this bit to reset out DMA FSM. (R/W)
    I2SX.lc_conf.out_rst = 0;    // FSM = Finite State Machine.
}

The first burst is apparently ok ( 768 us ) and data are ok.

All bursts after first burst now they have 768 us, but the first two bytes are inverted. The rest of bytes seem to be correct.

Example:

Code: Select all

uint16_t buffer_a[15360];  // the correct buffer size value is 3840 uint16_t, but this has no influence beyond memory waste.

for ( uint32_t i = 0 ; i < 15360 ; i++ )
{        
    buffer_a[i] = 0xFF00;  // FF most significant byte. 00 least significant byte.
}    
The first two bytes are inverted:
buffer_a[ 0 ].low = 0xFF;
buffer_a[ 0 ].high = 0x00;

The correct way:
buffer_a[ 0 ].low = 0x00;
buffer_a[ 0 ].high = 0xFF;

Re: i2s parallel only works with one dma descriptor

Posted: Fri Nov 29, 2019 6:31 am
by ESP_houwenxiang
Hi,

I think it's no use to reset the tx fifo, can you try resetting the tx module with the following code?

Code: Select all

void i2s_reset(void)
{
        I2SX.conf.tx_reset = 1;
        I2SX.conf.tx_reset = 0;
}

Re: i2s parallel only works with one dma descriptor

Posted: Fri Nov 29, 2019 5:48 pm
by Baldhead
Hi ESP_houwenxiang,

"I think it's no use to reset the tx fifo, can you try resetting the tx module with the following code ?"
I am already doing this.

Code: Select all

int i2s_lcd_write_data ( uint32_t length, bool buffer_id )  // length = number in bytes. length <= 7680.
{
    static uint32_t i;
    static uint8_t* ptr = NULL; 


    if ( length > pixels_size_in_bytes )    // Length > buffer capacity. pixels_size_in_bytes = 7680 bytes. 
    {
        printf( "Error: length > %d. \n\n", pixels_size_in_bytes );
        return -1;
    }     

    
    if ( buffer_id == 0 )    
    {   
        ptr = (uint8_t *) &buffer_a;    // buffer_a is uint16_t.

        /*
        printf( "\n&buf_a = %p\n", &buf_a );
        printf( "&buffer_a = %p\n", &buffer_a );
        printf( "ptr = %p\n\n", ptr );
        */

        for ( i = 0 ; i < length ; i = i + 2 )    // length <= 7680 bytes.  loop max 7680/2 = 3840 times.
        {        
            buf_a[ i ] = ptr[ i ];    // The address of buf_a increment in 4 bytes while the address of buffer_a(ptr) increment in 1 byte.
            buf_a[ i + 1 ] = ptr[ i + 1 ];

            /*           
            printf( "&ptr[ %d ] = %p\n", i, &ptr[ i ] );
            printf( "ptr[ %d ] = 0x%02X\n", i, ptr[ i ] );

            printf( "&ptr[ %d ] = %p\n", i+1, &ptr[ i+1 ] );
            printf( "ptr[ %d ] = 0x%02X\n", i+1, ptr[ i+1 ] );

            printf( "&buf_a[ %d ] = %p\n", i, &buf_a[ i ] );      
            printf( "buf_a[ %d ] = 0x%08X\n", i,  buf_a[ i ] );

            printf( "&buf_a[ %d ] = %p\n", i+1, &buf_a[ i+1 ] );
            printf( "buf_a[ %d ] = 0x%08X\n", i+1,  buf_a[ i+1 ] );           

            printf("\n");
            */
        }
    
        fill_dma_descriptor_a( (uint32_t) 4 * length );               // ( 4 * length ) = change from byte(8 bits) to word(32bits). 
        I2SX.out_link.addr = (uint32_t) &dma_desc_buf_a[0];    // ( (uint32_t) ( &dma_desc_buf_a[0] ) ) & I2S_OUTLINK_ADDR;  
    }
    else
    {
        ptr = (uint8_t *) &buffer_b;   

        for ( i = 0 ; i < length ; i = i + 2 )    
        {        
            buf_b[ i ] = ptr[ i ];    
            buf_b[ i + 1 ] = ptr[ i + 1 ];
        }         
         
        fill_dma_descriptor_b( (uint32_t) 4 * length );  
        I2SX.out_link.addr = (uint32_t) &dma_desc_buf_b[0];
    }


    I2SX.out_link.start = 1;          // Set this bit to start outlink descriptor. (R/W).
    I2SX.fifo_conf.dscr_en = 1;    // Set this bit to enable I2S DMA mode. (R/W).   
    I2SX.conf.tx_start = 1;          // Set this bit to start transmitting data. (R/W).  
    
    
    while ( ! ( I2SX.state.tx_idle ) )   // The status bit of the transmitter. 1: the transmitter is idle. 0: the transmitter is busy.(RO)
    { }
    

    I2SX.conf.tx_start = 0;           // Set this bit to start transmitting data. (R/W).    
    I2SX.fifo_conf.dscr_en = 0;    // Set this bit to enable I2S DMA mode. (R/W).


    tx_reset( );            // Set this bit to reset the transmitter. (R/W)
    dma_tx_reset( );    // Set this bit to reset out DMA FSM. FSM = Finite State Machine. (R/W)

/*
    I2SX.lc_conf.ahbm_rst = 1; 
    I2SX.lc_conf.ahbm_rst = 0;
    
    I2SX.lc_conf.ahbm_fifo_rst = 1;
    I2SX.lc_conf.ahbm_fifo_rst = 0;
*/

    return 2019;
}
I already tried with all possibilities with different sequential order using:
* tx_reset( );
* dma_tx_reset( );
* fifo_tx_reset( ):

And enable only tx_reset( ).
After tx_reset( ) and fifo_tx_reset( ) and dma_tx_reset( ) and so on.

I am try this to:

I2SX.lc_conf.ahbm_rst = 1;
I2SX.lc_conf.ahbm_rst = 0;

I2SX.lc_conf.ahbm_fifo_rst = 1;
I2SX.lc_conf.ahbm_fifo_rst = 0;


But nothing solved the problem.


Thank's for the help.

Re: i2s parallel only works with one dma descriptor

Posted: Fri Nov 29, 2019 7:28 pm
by Baldhead
Hi again,

Could these compiler warnings have any influence on this problem ?


#warning rom/lldesc.h is deprecated, please use esp32/rom/lldesc.h instead

#warning esp_intr.h is deprecated, please include esp_intr_alloc.h instead


Thank's.

Re: i2s parallel only works with one dma descriptor

Posted: Fri Nov 29, 2019 8:07 pm
by Baldhead
Hi,

I changed the headers:

#include "rom/lldesc.h"
#include "esp_intr.h"


To headers:

#include "esp32/rom/lldesc.h"
#include "esp_intr_alloc.h"


And the same problem persists.


Thank's.

Re: i2s parallel only works with one dma descriptor

Posted: Mon Dec 02, 2019 2:29 am
by ESP_houwenxiang
Hi, Baldhead

Can you provide a simple project that can reproduce your issue? I don't need your entire project, just an example that can make I2S work in your configuration. The code you provided before is missing the I2S configuration and I cannot make it work in my environment. I would appreciate it if you could rearrange the issues you encountered.

thanks !!

Re: i2s parallel only works with one dma descriptor

Posted: Mon Dec 02, 2019 4:41 am
by Baldhead
Hi,

I send the code via technical inquire. I can send via technical inquire again with the bugs that i encontered after send first time corrected.

Or i can send via private message maybe.

But at the moment i am traveling.

Here in Brazil are 1:37 hrs of sunday dawn to monday.

Thank's.