i2s parallel only works with one dma descriptor

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

i2s parallel only works with one dma descriptor

Postby Baldhead » Tue Nov 26, 2019 1:06 am

Hi,

I am developing my own i2s paralle 8 bits with dma library(static allocation memory).

When i write to the parallel port using only one descriptor(4092 uint8_t), the clock time to send, for example, 1000 uint8_t at 10 MHz is 100 microseconds(1000/10 000 000).
Apparently all ok with only one descriptor.

When i use more than one descriptor, the clock time to send, for example, 7680 uint8_t at 10 MHz is 1536 microseconds.
Should be half of this value 768 microseconds( 7680 / 10 000 000 ). I don't know why it's taking twice as long.

In annex follow an oscilloscope image of 7680 uint8_t at 10 MHz.
The yellow waveform are the clock(10MHz).
The blue waveform are the D0 channel data.
I initialize the buffer with zeros, but in D0 channel appears some weird data.


Also with only one descriptor, each time that i send the data i perform these instructions( partial code below ):

I2SX.conf.tx_start = 0; // Set this bit to start transmitting data. (R/W).

I2SX.conf.tx_reset = 1; // Set this bit to reset the transmitter. (R/W)
I2SX.conf.tx_reset = 0; // Set this bit to reset the transmitter. (R/W)

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


Partial code below: VVVV

Code: Select all

    fill_dma_descriptor_b(  (uint32_t) 4 * length  );    // fill_dma_descriptor_b( length );  lenght in bytes.
    
    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.conf.tx_reset = 1;    // Set this bit to reset the transmitter. (R/W)
    I2SX.conf.tx_reset = 0;    // Set this bit to reset the transmitter. (R/W)
    
    I2SX.fifo_conf.dscr_en = 0;    // Set this bit to enable I2S DMA mode. (R/W).

Right now i'm not using i2s module interrupt.
Could this be the problem ?

Any other suggestions is appreciated.


Thank's.
Attachments
TEK0000.JPG
TEK0000.JPG (211 KiB) Viewed 7938 times

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

Re: i2s parallel only works with one dma descriptor

Postby Baldhead » Tue Nov 26, 2019 1:09 am

i2SX = i2s0 in my application driver.

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

Re: i2s parallel only works with one dma descriptor

Postby ESP_Sprite » Tue Nov 26, 2019 2:09 am

Smells like you're filling the DMA descriptor wrong, but you're not including that code...

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

Re: i2s parallel only works with one dma descriptor

Postby Baldhead » Tue Nov 26, 2019 3:54 am

Hi ESP_Sprite,

Follow the code you commented.

Code: Select all

// static int IRAM_ATTR fill_dma_descriptor_a( uint32_t length )          IRAM_ATTR    ????????????

// verify if sosf = 1  ? 

#define buffer_size 30720     // uint8_t size

static lldesc_t dma_desc_buf_a[8];     // DMA_ATTR ????

DMA_ATTR uint16_t buffer_a[ buffer_size/2 ];


static int fill_dma_descriptor_a ( uint32_t length )    //  uint32_t length em bytes.    
{
    if ( length > buffer_size )  return -1;    // length = numero de pixels*2. 1 pixel = 2 bytes. 313 ns.
    if ( length == 0 )           return -2;    // 300 ns.


    if ( length <= 4092 )    // only need one single descriptor. // 740 ns.
    {        
        dma_desc_buf_a[0].size = 4092;// The size must be word-aligned. I can define 4092 here, but the dma only send ".length" bytes.
	dma_desc_buf_a[0].length = length;	
	dma_desc_buf_a[0].offset = 0;	
	dma_desc_buf_a[0].sosf = 0;	
	dma_desc_buf_a[0].eof = 1;	    // indicates that are the end of the linked list. 
	dma_desc_buf_a[0].owner = 1;     // the allowed operator is the DMA controller.		
	dma_desc_buf_a[0].buf = (uint8_t*) &buffer_a[0];  		
	dma_desc_buf_a[0].qe.stqe_next = ( lldesc_t* ) NULL;    // last node of linked list.

        return 1;    // ok.
    }

    // if ( length > 4092 )   // Need more than one descriptor. 

    static uint32_t fullBufferNum;                     // full buffer descriptor number(4092 bytes).     
    fullBufferNum = (uint32_t) length / 4092;    // integer division.

    static uint32_t remainderBufferNum;  // A single descriptor with buffer between (1 and 4091 bytes). 0 or 4092 bytes fall within "fullBufferNum". 0 bytes -> fullBufferNum only. 4092 bytes -> fullBufferNum + 1.  
     
    remainderBufferNum = ( length % 4092 );  // Returns the remainder of the division of the length/4092 ( integer number ).
                                                                   // Example: length/4092 = 14002 / 4092 = 3 e remainder = 1726. 3*4092 + 1726 = 14002.     


    static uint32_t i = 0;    // for iteration. 

    for ( i = 0 ; i < fullBufferNum ; i++ )     
    {	
	    dma_desc_buf_a[i].size = 4092;    // The size must be word-aligned. The size of the buffer corresponding to the current linked list.
	    dma_desc_buf_a[i].length = 4092;  // The number of valid bytes in the buffer corresponding to the current linked list. The field value indicates the number of bytes to be transferred to/from the buffer denoted by word DW1.	
	    dma_desc_buf_a[i].offset = 0;	
	    dma_desc_buf_a[i].sosf = 0;	
	    dma_desc_buf_a[i].eof = 0;	     // indicates that it is not the end of the linked list.  
	    dma_desc_buf_a[i].owner = 1;    // the allowed operator is the DMA controller.		
	    dma_desc_buf_a[i].buf = (uint8_t*) ( ( &buffer_a[0] ) + ( 4092 * i ) );  		
	    dma_desc_buf_a[i].qe.stqe_next = ( lldesc_t* ) &dma_desc_buf_a[ i+1 ];
    }

    if ( remainderBufferNum == 0 )    // integer division. Don't need allocate another descriptor.      
    {
        dma_desc_buf_a[ fullBufferNum - 1 ].eof = 1;    // indicates that is the end of linked list.
        dma_desc_buf_a[ fullBufferNum - 1 ].qe.stqe_next = ( lldesc_t* ) NULL;

        return 2;  // with 2 full descriptors(8184) = 1.63 us. with 7 full descriptors(28644) = 4.25 us.
    }
    else  // Need to allocate (statically) 1 more descriptor.
    {
        dma_desc_buf_a[fullBufferNum].size = 4092;// The size must be word-aligned. I can define 4092 here, but the dma only send ".length" bytes.
	dma_desc_buf_a[fullBufferNum].length = remainderBufferNum;	
	dma_desc_buf_a[fullBufferNum].offset = 0;	
	dma_desc_buf_a[fullBufferNum].sosf = 0;	
	dma_desc_buf_a[fullBufferNum].eof = 1;	        // indicates that is the end of linked list.
	dma_desc_buf_a[fullBufferNum].owner = 1;      // the allowed operator is the DMA controller.		
	dma_desc_buf_a[fullBufferNum].buf = (uint8_t*) ( &buffer_a[0] ) + ( 4092 * fullBufferNum );  	  		
	dma_desc_buf_a[fullBufferNum].qe.stqe_next = ( lldesc_t* ) NULL;    // last node.  

        return 3;  // with input parameter length = 4093 -> 1.47 us. with input parameter length = 30720 -> 4.7 us.      
    }   
}


/*
        printf("fullBufferNum = %d\n", fullBufferNum );
        printf("remainderBufferNum = %d\n", remainderBufferNum );

        printf(" &buffer_a = %p\n", &buffer_a );
        printf(" &buffer_b = %p\n", &buffer_b );        
        
        static uint32_t j = 0;    // for iteration.

        for ( j = 0 ; j < sizeof(dma_desc_buf_a)/sizeof(dma_desc_buf_a[0]) ; j++ )
        {
            printf("dma_desc_buf_a[%d].size = %d\n", j, dma_desc_buf_a[j].size );
            printf("dma_desc_buf_a[%d].length = %d\n", j, dma_desc_buf_a[j].length );
            printf("dma_desc_buf_a[%d].offset = %d\n", j, dma_desc_buf_a[j].offset );
            printf("dma_desc_buf_a[%d].sosf = %d\n", j, dma_desc_buf_a[j].sosf );
            printf("dma_desc_buf_a[%d].eof = %d\n", j, dma_desc_buf_a[j].eof );
            printf("dma_desc_buf_a[%d].owner = %d\n", j, dma_desc_buf_a[j].owner );
            
            printf("dma_desc_buf_a[%d].buf = %p\n", j, dma_desc_buf_a[j].buf );
            printf("dma_desc_buf_a[%d].qe.stqe_next = %p\n", j, dma_desc_buf_a[j].qe.stqe_next );

           
            printf("\n");
            printf("&dma_desc_buf_a[%d] = %p\n", j+1, &dma_desc_buf_a[j+1] );

            printf("\n\n");
        }
*/  
You can use the printf to check the code.

For me looks ok this code.


Thank's.

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

Re: i2s parallel only works with one dma descriptor

Postby Baldhead » Tue Nov 26, 2019 4:10 am

Hi,

Actually the new code are below, because i need copy an uint8_t buffer to an uint32_t buffer (very bad i2s design i think, unless there is another way), but the espressif team don't respond me(I'm not being rude).

Code: Select all

#define buffer_size 30720  // byte size

DMA_ATTR uint16_t buffer_a[buffer_size/2];

static lldesc_t dma_desc_buf_a[8];  // DMA_ATTR  ????

DMA_ATTR uint32_t buf_a[buffer_size/4];    // dma buffers. // buffer_size/4 = 7680 bytes.   uint32_t buf_a -> 30720 bytes.



// static int IRAM_ATTR fill_dma_descriptor_a( uint32_t length )     // IRAM_ATTR    ????   
// verificar se sosf = 1. 


static int fill_dma_descriptor_a ( uint32_t length )  //  uint32_t length em bytes.    
{
    if ( length > buffer_size )  return -1;    // length = numero de pixels*2. 1 pixel = 2 bytes. 313 ns.
    if ( length == 0 )           return -2;    // 300 ns.


    if ( length <= 4092 )    // Soh precisa um descriptor. // 740 ns.
    {        
        dma_desc_buf_a[0].size = 4092;    // The size must be word-aligned. Eu posso definir 4092 aqui, porem o dma soh ira enviar ".length" bytes.
	    dma_desc_buf_a[0].length = length;	
	    dma_desc_buf_a[0].offset = 0;	
	    dma_desc_buf_a[0].sosf = 0;	
	    dma_desc_buf_a[0].eof = 1;	    // indica que eh o final da lista. 
	    dma_desc_buf_a[0].owner = 1;    // the allowed operator is the DMA controller.		
	    dma_desc_buf_a[0].buf = (uint8_t*) &buf_a[0];  		
	    dma_desc_buf_a[0].qe.stqe_next = ( lldesc_t* ) NULL;    // ultimo nó da lista ligada.

        return 1;    // ok.
    }

    // if ( length > 4092 )  // Precisa mais que um descriptor. 

    static uint32_t fullBufferNum;               // Numero de descriptors com buffer cheio(4092 bytes).     
    fullBufferNum = (uint32_t) length / 4092;    // Divisao inteira.

    static uint32_t remainderBufferNum;          // Um unico descriptor com buffer entre ( 1 e 4091 bytes). 0 ou 4092 bytes se enquadra em "fullBufferNum". 0 bytes -> somente fullBufferNum. 4092 bytes -> fullBufferNum + 1.
    remainderBufferNum = ( length % 4092 );      // Retorna o resto da divisao de length/4092 ( numero inteiro ).
                                                 // Exemplo: length/4092 = 14002 / 4092 = 3 e resto = 1726. 3*4092 + 1726 = 14002.     


    static uint32_t i = 0;    // for iteration. 

    for ( i = 0 ; i < fullBufferNum ; i++ )     
    {	
	    dma_desc_buf_a[i].size = 4092;    // The size must be word-aligned. The size of the buffer corresponding to the current linked list.
	    dma_desc_buf_a[i].length = 4092;  // The number of valid bytes in the buffer corresponding to the current linked list. The field value indicates the number of bytes to be transferred to/from the buffer denoted by word DW1.	
	    dma_desc_buf_a[i].offset = 0;	
	    dma_desc_buf_a[i].sosf = 0;	
	    dma_desc_buf_a[i].eof = 0;	    // indica que não eh o final da lista. 
	    dma_desc_buf_a[i].owner = 1;    // the allowed operator is the DMA controller.		
	    dma_desc_buf_a[i].buf = (uint8_t*) ( ( &buf_a[0] ) + ( 4092 * i ) );  		
	    dma_desc_buf_a[i].qe.stqe_next = ( lldesc_t* ) &dma_desc_buf_a[ i+1 ];
    }

    if ( remainderBufferNum == 0 )    // divisao inteira. Não precisa mais alocar nenhum descriptor.      
    {
        dma_desc_buf_a[ fullBufferNum - 1 ].eof = 1;    // indica que eh o final da lista.
        dma_desc_buf_a[ fullBufferNum - 1 ].qe.stqe_next = ( lldesc_t* ) NULL;

        return 2;  // Com 2 full descriptors(8184) = 1.63 us. Com 7 full descriptors(28644) = 4.25 us.
    }
    else  // Precisa alocar(estaticamente) mais 1 descriptor.
    {
        dma_desc_buf_a[fullBufferNum].size = 4092;    // The size must be word-aligned. Eu posso definir 4092 aqui, porem o dma soh ira enviar ".length" bytes.
	    dma_desc_buf_a[fullBufferNum].length = remainderBufferNum;	
	    dma_desc_buf_a[fullBufferNum].offset = 0;	
	    dma_desc_buf_a[fullBufferNum].sosf = 0;	
	    dma_desc_buf_a[fullBufferNum].eof = 1;	    // indica que eh o final da lista. 
	    dma_desc_buf_a[fullBufferNum].owner = 1;    // the allowed operator is the DMA controller.		
	    dma_desc_buf_a[fullBufferNum].buf = (uint8_t*) ( &buf_a[0] ) + ( 4092 * fullBufferNum );  	  		
	    dma_desc_buf_a[fullBufferNum].qe.stqe_next = ( lldesc_t* ) NULL;    // ultimo nó da lista ligada. 




        printf("fullBufferNum = %d\n", fullBufferNum );
        printf("remainderBufferNum = %d\n", remainderBufferNum );

        printf(" &buf_a = %p\n", &buf_a );
        printf(" &buf_b = %p\n", &buf_b );        
        
        static uint32_t j = 0;    // for iteration.

        for ( j = 0 ; j < sizeof(dma_desc_buf_a)/sizeof(dma_desc_buf_a[0]) ; j++ )
        {
            printf("dma_desc_buf_a[%d].size = %d\n", j, dma_desc_buf_a[j].size );
            printf("dma_desc_buf_a[%d].length = %d\n", j, dma_desc_buf_a[j].length );
            printf("dma_desc_buf_a[%d].offset = %d\n", j, dma_desc_buf_a[j].offset );
            printf("dma_desc_buf_a[%d].sosf = %d\n", j, dma_desc_buf_a[j].sosf );
            printf("dma_desc_buf_a[%d].eof = %d\n", j, dma_desc_buf_a[j].eof );
            printf("dma_desc_buf_a[%d].owner = %d\n", j, dma_desc_buf_a[j].owner );
            
            printf("dma_desc_buf_a[%d].buf = %p\n", j, dma_desc_buf_a[j].buf );
            printf("dma_desc_buf_a[%d].qe.stqe_next = %p\n", j, dma_desc_buf_a[j].qe.stqe_next );

           
            printf("\n");
            printf("&dma_desc_buf_a[%d] = %p\n", j+1, &dma_desc_buf_a[j+1] );

            printf("\n\n");
        }
        
        
        return 3;  // Com input parameter length = 4093 -> 1.47 us. Com input parameter length = 30720 -> 4.7 us.      
    }   
}

Code: Select all


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


    if ( length > buffer_size/4  )    // Length > buffer capacity. Usar printf. buffer_size/4 = 30720/4 = 7680 bytes. 
    {
        printf( "error: length > buffer_size/4.\n\n" );
        return -1;
    }     

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

        for ( i = 0 ; i < length ; i = i + 2 )    // length <= 7680 bytes.  loop no maximo 7680/2 = 3840 vezes.
        {        
            buf_a[ i ] = ptr[ i ];    // o endereco de buf_a incrementa em 4 bytes enquanto o endereco de buffer_a(ptr) incrementa em 1 byte.
            buf_a[ i + 1 ] = ptr[ i + 1 ];
        }    
    
        fill_dma_descriptor_a( (uint32_t) 4 * length );  // ( 4 * length ) = converte de byte(8 bits) para word(32bits). // fill_dma_descriptor_a( length ); 
        I2SX.out_link.addr = (uint32_t) &dma_desc_buf_a[0];
    }
    else
    {
        ptr = (uint8_t *) &buffer_b;    // buffer_a é uint16_t.

        for ( i = 0 ; i < length ; i = i + 2 )    // length <= 7680 bytes.  loop no maximo 7680/2 = 3840 vezes.
        {        
            buf_b[ i ] = ptr[ i ];    // o endereco de buf_a incrementa em 4 bytes enquanto o endereco de buffer_a(ptr) incrementa em 1 byte.
            buf_b[ i + 1 ] = ptr[ i + 1 ];
        }         
         
        fill_dma_descriptor_b( (uint32_t) 4 * length );    // fill_dma_descriptor_b( 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).    

    tx_reset( );           // Set this bit to reset the transmitter. (R/W)
    //fifo_tx_reset( );
    //dma_tx_reset( );

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


    return 2019;
}

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

Re: i2s parallel only works with one dma descriptor

Postby Baldhead » Tue Nov 26, 2019 8:18 pm

Hi,

Now i add the following instructions:

* fifo_tx_reset( );
* dma_tx_reset( );

Besides:

* tx_reset( );

Code: Select all

static void fifo_tx_reset( )
{    
    I2SX.conf.tx_fifo_reset = 1;    // Set this bit to reset the transmit FIFO. (R/W)
    I2SX.conf.tx_fifo_reset = 0;
}

static void fifo_tx_reset( )
{    
    I2SX.conf.tx_fifo_reset = 1;    // Set this bit to reset the transmit FIFO. (R/W)
    I2SX.conf.tx_fifo_reset = 0;
}

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

Code: Select all

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


    if ( length > buffer_size/4  )    // Length > buffer capacity. Usar printf. buffer_size/4 = 30720/4 = 7680 bytes. 
    {
        printf( "error: length > buffer_size/4.\n\n" );
        return -1;
    }     

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

        for ( i = 0 ; i < length ; i = i + 2 )    // length <= 7680 bytes.  loop no maximo 7680/2 = 3840 vezes.
        {        
            buf_a[ i ] = ptr[ i ]; // o endereco de buf_a incrementa em 4 bytes enquanto o endereco de buffer_a(ptr) inc em 1 byte.
            buf_a[ i + 1 ] = ptr[ i + 1 ];
        }    
    
        fill_dma_descriptor_a( (uint32_t) 4 * length );  // ( 4 * length ) = converte de byte(8 bits) para word(32bits).   
        I2SX.out_link.addr = (uint32_t) &dma_desc_buf_a[0];
    }
    else
    {
        ptr = (uint8_t *) &buffer_b;    // buffer_a é uint16_t.

        for ( i = 0 ; i < length ; i = i + 2 )    // length <= 7680 bytes.  loop no maximo 7680/2 = 3840 vezes.
        {        
            buf_b[ i ] = ptr[ i ];    // o endereco de buf_a incrementa em 4 bytes enquanto o endereco de buffer_a(ptr) inc em 1 byte.
            buf_b[ i + 1 ] = ptr[ i + 1 ];
        }         
         
        fill_dma_descriptor_b( (uint32_t) 4 * length );    // fill_dma_descriptor_b( 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).  



    if ( I2SX.int_st.out_dscr_err )
    {
        printf( "Dma error, interrupt status: 0x%08x", I2SX.int_st.val );
    }
    
    
    while ( ! ( I2SX.state.tx_idle ) )   // The status bit of the transmitter. 1: the transmitter is idle. 0: the transmitter is busy.(RO)
    {}


    if ( I2SX.int_st.out_dscr_err )
    {
        printf( "Dma error, interrupt status: 0x%08x", I2SX.int_st.val );
    }



    I2SX.conf.tx_start = 0;    // Set this bit to start transmitting data. (R/W).    

    tx_reset( );           // Set this bit to reset the transmitter. (R/W)
    
    fifo_tx_reset( );
    dma_tx_reset( );


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


    return 2019;
}
Now when use more than one descriptor, the clock time to send, for example, 7680 uint8_t at 10 MHz is
768 microseconds( 7680 / 10 000 000 ).
The time is correct now, but only send one time and stop.
Also in the D0 channel appears some weird data yet.


In annex follow an oscilloscope image of 7680 uint8_t at 10 MHz.
The yellow waveform are the clock(10MHz).
The blue waveform are the D0 channel data.
I initialize the buffer with zeros, but in D0 channel appears some weird data.


Do i need to reset ahb bus or something like that ?
I will try.

I2S_LC_CONF_REG.

I2S_AHBM_RST Set this bit to reset AHB interface of DMA. (R/W)
I2S_AHBM_FIFO_RST Set this bit to reset AHB interface cmdFIFO of DMA. (R/W)


Thank's.
Attachments
TEK0001.JPG
TEK0001.JPG (198.77 KiB) Viewed 7826 times

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

Re: i2s parallel only works with one dma descriptor

Postby Baldhead » Tue Nov 26, 2019 8:39 pm

I used only the function below to isolate the above behavior.

* dma_tx_reset( );


With the function

fifo_tx_reset( );

the time error remained(1536 us).

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

Re: i2s parallel only works with one dma descriptor

Postby Baldhead » Tue Nov 26, 2019 11:23 pm

Hi,

"Smells like you're filling the DMA descriptor wrong, but you're not including that code..."

If i was filling the DMA descriptor wrong, the bit "I2S0.int_st.out_dscr_err" should not be set ?

The bit "I2S0.int_st.out_dscr_err" are always zero.

I am not enabling the interrupt and i don't know if the bit "I2S0.int_st.out_dscr_err" works without enabling interrupt.

Some others suggestions ???

Thank's.

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

Re: i2s parallel only works with one dma descriptor

Postby Baldhead » Wed Nov 27, 2019 2:46 am

Hi,

This function is better with or without this attribute "IRAM_ATTR" ???

"static int fill_dma_descriptor_a( uint32_t length )"
"static int IRAM_ATTR fill_dma_descriptor_a( uint32_t length )"

and,

This buffer is better with or without this attribute "DMA_ATTR" ???

static lldesc_t dma_desc_buf_a[8];
static DMA_ATTR lldesc_t dma_desc_buf_a[8];


Thank's.

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

Re: i2s parallel only works with one dma descriptor

Postby Baldhead » Wed Nov 27, 2019 3:07 am

Hi,

I encounter two problems in my function "static int fill_dma_descriptor_a ( uint32_t length )".

First bug:

Initially the buffer was uint8_t, so, the uint8_t buffer pointer increased the address by one address position ( ie: 4092 * i * 1 ).
dma_desc_buf_a.buf = (uint8_t*) ( ( &buf_a[0] ) + ( 4092 * i ) );

After, i changed the buffer to uint32_t, so, the uint32_t buffer pointer increased the address by four address position ( ie: 4092 * i * 4 ).
So, i changed to "1023 * i".
dma_desc_buf_a.buf = (uint8_t*) ( ( &buf_a[0] ) + ( 1023 * i ) );


Second bug:

dma_desc_buf_a[fullBufferNum].buf = (uint8_t*) ( ( &buf_a[0] ) + ( 1023 * fullBufferNum ) );

An extra parenthesis was missing in the formula: (uint8_t*) ( &buf_a[0] ) + ( 1023 * fullBufferNum )

I changed to: (uint8_t*) ( ( &buf_a[0] ) + ( 1023 * fullBufferNum ) )

The compiler calculated wrong way the address of the "dma_desc_buf_a[fullBufferNum].buf".

Who is online

Users browsing this forum: No registered users and 79 guests