This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

how to use uart's dma event support

Other Parts Discussed in Thread: TMS320C6747

I want to use edma to send uart data.The hardware is tms320c6747.Howerver,I can only send 16 bytes data.The edma configure ,the function parameter 'len' is the character string's length.

void EDMA3_Uart(int len)
{

EDMA3ccRegs->DRA[1].DRAE = (1<<12) |(1<<13);

EDMA3ccRegs->DMAQNUM[1]  = 0x00110000 ;
 EDMA3ccRegs->PARAMSET[13].OPT = 0x0010D004;
 EDMA3ccRegs->PARAMSET[13].SRC = (Uint32)tx_buf; 
 EDMA3ccRegs->PARAMSET[13].A_B_CNT = _pack2(len, 1);
 EDMA3ccRegs->PARAMSET[13].DST = (Uint32)(&(Uart2Regs->THR));
 EDMA3ccRegs->PARAMSET[13].SRC_DST_BIDX = _pack2(0, 1);
 EDMA3ccRegs->PARAMSET[13].LINK_BCNTRLD = _pack2(0, 0xffff); 
 EDMA3ccRegs->PARAMSET[13].SRC_DST_CIDX = _pack2(0, 0);
 EDMA3ccRegs->PARAMSET[13].CCNT = 1;

 BCACHE_writeback((Ptr)tx_buf, sizeof(tx_buf));
}

 

then I use Manually-Triggered Transfer Request ,set ESR corresponding bit 1.The code as below :

// 串口输出字符串
Int16 uart1_send(String uart_tx_str)
{
 volatile Uint16 dummy;
 Uint8 lsr_status;
 int len,i;
 unsigned char* src=tx_buf;
 len = strlen(uart_tx_str);
 
 memset(tx_buf,0,sizeof(tx_buf));
 strcpy(tx_buf,uart_tx_str);
 EDMA3_Uart(len);

 EDMA3ccRegs->ESR = 1<<13;

}

But this program only send 16 bytes when character string length greater than 16.I am guess becausethe transmitter FIFO only 16 bytes,subsequent character  is lost.

How to solve the question?

I'm sorry,I english is not well!   Thanks.

  • Hi gao weidong,

    Since you are using Manually - triggered transfer request, you need to manually set the events. The next step would be to decide whether to use A - sync based transfer or AB - sync based transfers?. Looking at your code, seems like you are using AB sync based transfer. To brief a little about these transfers,

    Let’s take for example, you are attempting to transfer 24 bytes of data -

    A - sync based transfers:

    >> (aCnt) bytes of data is transferred per event.

    >> (bCnt * cCnt) number of events needs to be generated to completely service the PaRAM set.

    Ex 1: aCnt = 24, bCnt = 1, cCnt = 1 (Set the event only once(Manually trigger once), and the DMA should be able to transfer 24 bytes)

    Ex 2: aCnt = 1, bCnt = 24, Cnt = 1 (Set the event 24 times(Manually trigger 24 times), and the DMA should be able to transfer 24 bytes)

     

    AB - sync based transfer:

    >> (aCnt * bCnt) bytes of data transferred per event.

    >> (cCnt) number of events are needed to completely service the PaRAM set.

    Ex 1: aCnt = 1, bCnt = 6, Cnt = 4 (Set the event 4 times(Manually trigger 4 times), and the DMA should be able to transfer 24 bytes)

    - EDMA3ccRegs->ESR = 1<<13;  (To be set/triggered 4 times in this case)

    Similarly, 'n' number of configurations can be done. But, when using manually triggered based transfers, calculate the number of events that needs to completely service the PaRAM set and trigger manually accordingly.

    Note: The Src and Dst - Bidx, Cidx needs to be taken care accordingly. Please refer sections 2.2, 2.4.1.2 of EDMA User's guide 

    I am not sure as to how much are you setting the aCnt, bCnt, cCnt values to?. Let me know..

    Meanwhile, try the above examples and let us know the results.Hope this helps in resolving your issue.

    Thanks & regards,

    Raghavendra

     

  • Dear Raghavendra!

    when I test send character string as follows:uart1_send("ATD1000tttttttcccgjjadfs");//24 bytes

    A - sync based transfers:

    Ex 1: aCnt = 24, bCnt = 1, cCnt = 1 (Set the event only once(Manually trigger once), src,dst bindex,cindex is zero.).The result have nothing at all.

    void EDMA3_Uart(int len)
    {
     EDMA3ccRegs->PARAMSET[13].OPT = 0x0010D000;
     EDMA3ccRegs->PARAMSET[13].SRC = (Uint32)tx_buf; 
     EDMA3ccRegs->PARAMSET[13].A_B_CNT = _pack2(1, 24);
     EDMA3ccRegs->PARAMSET[13].DST = (Uint32)(&(Uart2Regs->THR));
     EDMA3ccRegs->PARAMSET[13].SRC_DST_BIDX = _pack2(0, 0);
     EDMA3ccRegs->PARAMSET[13].LINK_BCNTRLD = _pack2(0, 0xffff); 
     EDMA3ccRegs->PARAMSET[13].SRC_DST_CIDX = _pack2(0, 0);
     EDMA3ccRegs->PARAMSET[13].CCNT = 1;

     BCACHE_writeback((Ptr)tx_buf, sizeof(tx_buf));
    }

    Int16 uart1_send(String uart_tx_str)
    {
     volatile Uint16 dummy;
     Uint8 lsr_status;
     int len,i;
     unsigned char* src=tx_buf;
     len = strlen(uart_tx_str);
     
     memset(tx_buf,0,sizeof(tx_buf));
     strcpy(tx_buf,uart_tx_str);
     EDMA3_Uart(len);

      EDMA3ccRegs->ESR = 1<<13;

    }

    Ex 2: aCnt = 1, bCnt = 24, Cnt = 1 (Set the event 24 times(Manually trigger 24 times), src bidx is 1,src cidx,dst bidx cidx is 0).The result is ATD1000tttttttcc

    void EDMA3_Uart(int len)
    {
     EDMA3ccRegs->PARAMSET[13].OPT = 0x0010D000;
     EDMA3ccRegs->PARAMSET[13].SRC = (Uint32)tx_buf; 
     EDMA3ccRegs->PARAMSET[13].A_B_CNT = _pack2(24, 1);
     EDMA3ccRegs->PARAMSET[13].DST = (Uint32)(&(Uart2Regs->THR));
     EDMA3ccRegs->PARAMSET[13].SRC_DST_BIDX = _pack2(0, 1);
     EDMA3ccRegs->PARAMSET[13].LINK_BCNTRLD = _pack2(0, 0xffff); 
     EDMA3ccRegs->PARAMSET[13].SRC_DST_CIDX = _pack2(0, 0);
     EDMA3ccRegs->PARAMSET[13].CCNT = 1;

     BCACHE_writeback((Ptr)tx_buf, sizeof(tx_buf));
    }
    Int16 uart1_send(String uart_tx_str)
    {
     volatile Uint16 dummy;
     Uint8 lsr_status;
     int len,i;
     unsigned char* src=tx_buf;
     len = strlen(uart_tx_str);
     
     memset(tx_buf,0,sizeof(tx_buf));
     strcpy(tx_buf,uart_tx_str);
     EDMA3_Uart(len);

     for(i=0;i<24;i++){
      EDMA3ccRegs->ESR = 1<<13;
     }
    }

    AB - sync based transfer:

    Ex 1: aCnt = 1, bCnt = 6, Cnt = 4 (Set the event 4 times(Manually trigger 4 timesm),src Bidx=1,src Cidx=6, other is 0),and the result is also ATD1000tttttttcc

    void EDMA3_Uart(int len)
    {
     EDMA3ccRegs->PARAMSET[13].OPT = 0x0010D004;
     EDMA3ccRegs->PARAMSET[13].SRC = (Uint32)tx_buf; 
     EDMA3ccRegs->PARAMSET[13].A_B_CNT = _pack2(6, 1);
     EDMA3ccRegs->PARAMSET[13].DST = (Uint32)(&(Uart2Regs->THR));
     EDMA3ccRegs->PARAMSET[13].SRC_DST_BIDX = _pack2(0, 1);
     EDMA3ccRegs->PARAMSET[13].LINK_BCNTRLD = _pack2(0, 0xffff); 
     EDMA3ccRegs->PARAMSET[13].SRC_DST_CIDX = _pack2(0, 6);
     EDMA3ccRegs->PARAMSET[13].CCNT = 4;

     BCACHE_writeback((Ptr)tx_buf, sizeof(tx_buf));
    }

    Int16 uart1_send(String uart_tx_str)
    {
     volatile Uint16 dummy;
     Uint8 lsr_status;
     int len,i;
     unsigned char* src=tx_buf;
     len = strlen(uart_tx_str);
     
     memset(tx_buf,0,sizeof(tx_buf));
     strcpy(tx_buf,uart_tx_str);
     EDMA3_Uart(len);

     for(i=0;i<4;i++){
      EDMA3ccRegs->ESR = 1<<13;
     }
    }

    At at previous,I am use AB-sync ,the aCnt = 1, bCnt = len, Cnt = 1,src Bidx=1,the reuslt is the same.

    following is the UART initialization code,Whether have wrong in here?

    UART_Handle EVMOMAPL137_UART_open( Uint16 id, Uint32 baudrate )
    {
            UART_Handle uart_handle;
            Uint32 divisor;
      volatile Uint16 dummy;

            /*
             *  UART clk / baudrate
             *  = 24,000,000 / (115200 * 16)
             */
            divisor = 150000000 / ( baudrate * 16);

            switch ( id )
            {
                case 0:
                    uart_handle = ( UART_Handle )&UART_MODULE_0;
                    break;
                case 1:
                    uart_handle = ( UART_Handle )&UART_MODULE_1;
                    break;
                case 2:
                    uart_handle = ( UART_Handle )&UART_MODULE_2;
                    break;
                default:
                    return ( UART_Handle )-1;
            }

            uart_handle->regs->PWREMU_MGMT = 0;         // Reset UART TX & RX components

            EVMOMAPL137_wait( 100 );

            uart_handle->regs->DLL = (divisor & 0xff);  // Set baud rate
            uart_handle->regs->DLH = (divisor >> 8);
           
            uart_handle->regs->FCR = 0x0007;            // Clear UART TX & RX FIFOs
           uart_handle->regs->FCR = 0x0089;   //DMA and FIFO mode,and receiver fifo triger level 8 bytes;
            uart_handle->regs->IER = 0x0007;//0x0007;            // Enable interrupts
            uart_handle->regs->LCR = 0x0003;            // 8-bit words,
                                                        // 1 STOP bit generated,
                                                        // No Parity, No Stick paritiy,
                                                        // No Break control
            uart_handle->regs->MCR = 0x0000;            // RTS & CTS disabled,
                                                        // Loopback mode disabled,
                                                        // Autoflow disabled

            uart_handle->regs->PWREMU_MGMT = 0xE001;//0xE001;    // Enable TX & RX componenets

      // Clear any pre-existing characters
            dummy = uart_handle->regs->THR;
         return uart_handle;
    }

    Thanks & regards,

    gao weidong

  • Hi gao weidong,

    A question here: Are you enabling the Intermediate completion and completion interrupts of the EDMA?. If not, enable them. Can you please share us the EDMA ISR?. How are you handling the DMA interrupts?. 

    The transfer completion interrupts are latched to the interrupt pending register(IPR) after each transfer. Are you clearing the interrupt by writing a 1 to the corresponding bit in the interrupt pending clear register (ICR) when the ISR is called?.

    Thanks & regards,

    Raghavendra

  • In the DMA interurpts,I didn't do anything on the inside.so I haved disable the interrupt.Now I enble the interrupt by wirting 1 to the corresponding bit in the register IESR.As following.But it haven't effect to the result.

     

    void EDMA3_Uart(int len)
    {
     EDMA3ccRegs->DRA[1].DRAE |= 1<<13;
     EDMA3ccRegs->DMAQNUM[1]  = 0x00110000 ;
     EDMA3ccRegs->PARAMSET[13].OPT = 0x0010D004;
     EDMA3ccRegs->PARAMSET[13].SRC = (Uint32)tx_buf; 
     EDMA3ccRegs->PARAMSET[13].A_B_CNT = _pack2(6, 1);
     EDMA3ccRegs->PARAMSET[13].DST = (Uint32)(&(Uart2Regs->THR));
     EDMA3ccRegs->PARAMSET[13].SRC_DST_BIDX = _pack2(0, 1);
     EDMA3ccRegs->PARAMSET[13].LINK_BCNTRLD = _pack2(0, 0xffff); 
     EDMA3ccRegs->PARAMSET[13].SRC_DST_CIDX = _pack2(0, 6);
     EDMA3ccRegs->PARAMSET[13].CCNT = 4;

     BCACHE_writeback((Ptr)tx_buf, sizeof(tx_buf));
     EDMA3ccRegs->IESR |= (1<<13);
    }

    //EDMA 中断
    interrupt void audiodma(void)
    {
     volatile Uint32 ipr;
     ipr = EDMA3ccRegs->IPR;
     while(ipr)
     {
      if((ipr & (1<<12)) != 0)
      {
       }

      if ((ipr & (1<<13)) != 0)
      {
       printf("transmit interrupt!\r\n");
      }
      //清零对应的中断标示,等待下次中断进入
      EDMA3ccRegs->ICR = ipr;

      ipr = EDMA3ccRegs->IPR;  
     }
     
    }

     

    I should add   Manually-Triggered Transfer int the interrupt?like this:

      if ((ipr & (1<<13)) != 0)
      {

    EDMA3ccRegs->ESR = 1<<13;

     }

  • gao weidong,

    Are you hitting the audiodma ISR?. I mean, is the audiodma func called?. You need not manually trigger inside the ISR.

    You can even try implementing it this way - (refer attachment) let us know your results.. 

     

     Thanks & regards,

    Raghavendra

  • Thank you,it is right.

    But I have a  new trouble,when I call the func twice or more,only output the first ,for example:

      uart1_send("ATD1000tttttttcccgjjadfs\r\n");
      uart1_send("TBBDdsxx11fdk");

    the "TBBDdsxx11fdk" will loss.Then I look on the EDMA3ccRegs->ESR value,it is 8192.Is also haven't triger DMA,I have reconfigure the DMA to send new string,is these way have wrong?

  • Hi gao weidong,

    So, the first string is transferred without any loss right?. You are facing problems when doing second transaction now. Can you please clarify this?. 

    Since you were doing a Manual based triggering, I did not want to confuse you by mentioning other transfer types but to try getting this working. For Manual based triggering, I believe you need not enable the DMA in the UART. Please disable this and try running your application else, it might lead to problems. please try this and let us know the results.

    EDMA transfers can be done using Event based transfers also. When configuring UART in DMA mode, mostly event based transfer mechanism is opted. If you refer section 2.9 of the UART Userguide , it mentions about the DMA Event support. When the DMA is enabled in the UART(DMAMODE1 in FCR), the uart automatically generates the events. When these events are generated is mentioned in that section. So you will just need to set the PaRAM sets and set the event only once in the EESR, and the UART will take of generating the events, and the DMA will take care of the transfers. But I recommend you to go through the EDMA User guide/SPRU regarding this mechanism before implementing it. And, if you are going for Event based transfers, ensure that the DMA in UART is enabled, and the associated UART DMA channels(for Ex: UART1 rx - 12 and tx - 13)are used.

    Hope this helps..

     

    Thanks & regards,

    Raghavendra

  • Yeah,the first transmit no problem,the second transmit have nothing to ouput,the ESR register value is 8192.

    in the first instance ,I am use event triger.are you sure the uart automatically generates the events(UTXEVT),the uart DMA EVENT Support segment:

    Transmit event (UTXEVT): When the transmitter FIFO is empty (when the last byte in the transmitter
    FIFO has been copied to the transmitter shift register), the UART sends an UTXEVT signal to the
    EDMA controller. In response, the EDMA controller refills the transmitter FIFO by way of the transmitter
    holding register (THR). The UTXEVT signal is also sent to the DMA controller when the UART is taken
    out of reset using the UTRST bit in the power and emulation management register
    (PWREMU_MGMT).

    only two way to  generates the events:

    1. transmitter FIFO is empty  (when the last byte in the transmitter FIFO has been copied to the transmitter shift register).when I config the DMA enable the  event in EER
    by writing into EESR,It haven't generate the event yet.But I write a character to uart register THR ,the event be trigered! In this way,must increase a extra character to THR register,when the character copy to the TSR,the transmitter FIFO will be empty,it will bring a event.

    2.reset using the UTRST bit in the power and emulation management register (PWREMU_MGMT).I think it is not a good way,you must set the FREE bit to 0 in the PWREMU_MGMT register with set UTRST bit together,it can take effect.It will make the uart halt.Effect the uart receive.

    All above,I just want to use Manual based triggering.

    in addition,I am set the param link( LINK_BCNTRLD) value is 0xFFFF,The link update occurs after the current PaRAM set event parameters have been exhausted.That is,the value of LINK is FFFFh then a null PaRAM set is written to the current PaRAM set. And I also set the event only once? What should I do?

  • gao weidong,

    You partly misunderstood me.. I meant, when in Event based triggering, you need not set/generate the events manually. The UART itself will take care of it. Now how the UART generates these events is mentioned in that section is what I meant. Well, Initially the transmit FIFO is empty!!. and since DMAMODE is enabled in UART, It generates an event to DMA and if the PaRAM sets are programmed appropriately, the transfer starts. Since the FIFO is only 16 bytes, and there is no threshold for TX unlike RX, try aCnt =1,bCnt =1 and cCnt = bytes to be transferred; in AB sync configuration. Hence, every time a byte is written into the FIFO, the byte is moved out and the FIFO is again empty and an event is generated again. this goes on, and DMA transfers until the programmed PaRAM set exhausts. After all the bytes are transferred, you receive a completion interrupt.Setting the param link( LINK_BCNTRLD) value to 0xFFFF is correct since you are not going to do any linking.

    Hope this clears your doubts.. 

     

    Thanks & regards,

    Raghavendra

     

  • I see you means,once uart reset,the transfer starts.

    1.But it is not necessary to transmit any string at this time.It will output many messy code,like this,"???????????"

    ,when I want to tranmit ,nothing to output.

    2. I transmit have interval,sometimes transmit complete,wait a moment,I will transmit other string.the cCnt is uncertainly.

    They are maintain trouble to me now.

  • Hi gao weidong,

     

    Sorry for the delayed response.. 

    Keeping Event based trigger/transfer mechanism aside, did u try disabling the DMA in UART and do a Manual based transfer? as I mentioned earlier. If so, what was the result/observation?.

    One more question - Are you doing a transfer at different intervals of time or doing variable length transfers?.

     

    Thanks & regards,

    Raghavendra

  • Hi,Raghavendra

    Part of loss event in EMR register when do a Manual based transfer.It is impossible I need to enable DMA as uart  recevie .

    Yes,I do a transfer at different intervals of time and  variable length transfers.

     

  • Hi gao weidong,

    Is there any progress??.. And for UART to transfer data in DMA mode, it is important that the lenght of the data is known prior. Because the EDMA transfers only depending on the paramsets programmed.

    I guess it would be a better option, if you can download and refer the BIOS PSP UART driver regarding configuration of the DMA in UART and try it. UART driver(Uart.c and Uart_edma.c files) placed in: pspdrivers_01_30_01\packages\ti\pspiom\uart\src

    Download Link: http://software-dl.ti.com/dsps/dsps_public_sw/psp/BIOSPSP/01_30_01/index_FDS.html

    API's you can refer to:

    uartConfigure(...)

    uartHwSetup(...) for UART register configuration in Uart.c

    uartStartEdmaTxTransfer(...) for edma related config in Uart_edma.c file - (Here only event based transfer mechanism is used)

    And the sample application that demonstrates reading of 100bytes data from the UART console and output the same on the UART console can be found in uartSample.c file placed in: pspdrivers_01_30_01\packages\ti\pspiom\examples\evm6747\uart\edma\src

    NOTE: Only settings/configuration with respect to UART can be found here. 

    Hope this helps..

     

    Thanks & regards,

    Raghavendra

  • good.

    I have complete it.thank you