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.

UART Receive using DMA -> send via radio

Other Parts Discussed in Thread: SIMPLICITI, CC430F5137, MSP430F5510

Hi!

Im trying to read a stream of data coming to my UART filling in a string of 30 bytes and then sending this string via SimpliciTI. Unfortunately I dont receive everything, some information is missing and I can not figure out why.

I also tried using 2 char arrays, so while Im sending one with Simpliciti the other one gets filled from the UART.

Here is my DMA UART configuration:

DMACTL0 = DMA0TSEL_16+DMA1TSEL_16; //DMA0 UCA0RXIFG interrupt
//DMACTL4 = DMARMWDIS;
__data16_write_addr((unsigned short) &DMA0SA, (unsigned long) &UCA0RXBUF);
__data16_write_addr((unsigned short) &DMA0DA,(unsigned long) &current_string1);
DMA0SZ = 30;//sizeof(current_string1); // Block size
DMA0CTL = DMASRCINCR_0+DMASBDB+DMALEVEL+DMADSTINCR_3+DMADT_4+DMAIE; // src does not change, destination increments, repeated single transfer
DMA0CTL &= ~DMAIFG;
DMA0CTL |= DMAEN;

__data16_write_addr((unsigned short) &DMA1SA, (unsigned long) &UCA0RXBUF);
__data16_write_addr((unsigned short) &DMA1DA,(unsigned long) &current_string2);
DMA1SZ = 30;//sizeof(current_string1); // Block size
DMA1CTL = DMASRCINCR_0+DMASBDB+DMALEVEL+DMADSTINCR_3+DMADT_4+DMAIE; // src does not change, destination increments, repeated single transfer
DMA1CTL &= ~DMAIFG;

And here is the DMA interrupt:

#pragma vector=DMA_VECTOR
__interrupt void DMA_ISR(void)
{
switch(__even_in_range(DMAIV,16))
{
case 0: break;
case 2: // DMA0IFG = DMA Channel 0

DMA0CTL &= ~DMAEN;
DMA1CTL |= DMAEN;

SMPL_Send(SMPL_LINKID_USER_UUD, current_string1, sizeof(current_string1));

break;
case 4:
DMA1CTL &= ~DMAEN;
DMA0CTL |= DMAEN;

SMPL_Send(SMPL_LINKID_USER_UUD, current_string2, sizeof(current_string2));

break; // DMA1IFG = DMA Channel 1

default: break;
}
}

Anybody has an idea how I can improve it?

PS:

Device: CC430F5137

UART configured at 115200 from XT2/2 = 13Mhz

DCO running at 20Mhz

  • Don't understand what is the reason (in your example) for using DMA with UART RX side. You are using UART configured at 115200 bps, but even if it goes over 1 Mbps, it can still work fine without DMA. Why make things more complicated without improving anything.

    Anyway, if DMA must be used, and UART is always receiving (same size) 30 bytes, it can be done by single transfer mode (not repeated), and DMA can be triggered, whitout forcing DMALEVEL. Maybe I don't see everything clear, but why 2 DMA channels are used for same function (UART UCA0RXBUF -> string1/2).

  • What im trying to do is to create a 30byte package that could be sent via SimpliciTI. The stream on the UART is non-stop, so I just split 30 bytes every time and then it will be assembled back and parsed on the server.

    If I just use UART ISR count to 30 and send the string I miss some characters in the stream on the other side (server). And thats why I was thinking to use DMA.

    I used 2 DMA channels because one channel fills one string that string is being sent by SimpliciTI and in the meantime second DMA channel fills up the second string. And we do switching.

    Do you have a better idea on how to stream continuously?

  • I am working on UART-USB bridge, so basically don't know (in advance) how many bytes will be received on RX, and when stream will stop. In non-DMA version it can go (without transfer errors) till 3 Mbps, so if you are losing some characters on 115200 bps stream with your non-DMA version, than you code is really slow (or receiving on UART is interrupted by something else).

    http://forum.43oh.com/topic/3350-msp430f550x-based-usb-uart-bridge

    Don't know SimpliciTI, but if your packet are sized to 30 bytes (due to interface), than it is easier to handle it. If you want to use DMA, use it. Anyway, don't see reason for 2 channels for same job. You can use one channel with changing DMA destination address (circular buffer) after 30 bytes are received.

  • Hi Zrno Soli,

    I am also stuck in my dma , as I came to this thread because I am also having same problem
    I have program to send a large chunk of data ( of 2KB) to be sent over uart.

    So for that I am using DMA tx over uart.

    my basic settings are as below.
    DMACTL0 = DMA0TSEL__UCA0TXIFG;
    DMA0SA = (__SFR_FARPTR)(unsigned int ) source;
    DMA0DA = (__SFR_FARPTR)(unsigned int ) destination; //&UCA0TXBUF;
    DMA0SZ =size; // Block size
    DMA0CTL = DMADT_1 | DMASBDB| DMASRCINCR_1 | DMAIE| DMALEVEL_L; // Rpt, inc
    DMA0CTL |= DMAEN;

    I have flag that sets while tx is on going and I am reseting every time block tx is done.
    here I want data to be tx continuously by dma over uart with out stop.

    Also I am getting Only one byte stored at first location in my buffer, I am not getting other data..


    Thanks,

  • In similar case to yours I am not using DMA, because DMA doesn't improve anything (except possible low consumption).

  • So what you are using,? onlu UART..? I have to send data very frequently, ( 100 milisec intereval) ,So I have to Use DMA , ( if you have tried UART in this situation successfully. and result is batter I will also implement ).

    Is my settings are correct for the dma to send data over uart frequently.

  • Make small ring buffer, and lite (with min possible CPU cycles) TX UART interrupt that will trigger sending of new byte, and increment pointer to next position in ring buffer. Of course if depend on MCLK and how much CPU busy state is, but I was able to use it (MSP430F5510, 24 MHz) at 4 Mbps, for 1 MByte transfer without any lost bytes.

  • Ya that is one good way, And you can send 1mb that is more than I wanted to send .

    I have 4 sensors data. that I am collecting them in four separate buffer. And How to add them in one buffer ( i Have tried memset , but that will require more memory). If I can have all gathered in One buffer.

    It will be easy to send them over Ring buffer As you suggested.

    A little Update.
    ( when i tried using DMA to send data over UART , It worked (Though there are some errors ), I have kept UART rx as in my interrupt, So when Tx is on , and send data to controller ( UART rx) , I am not getting any interrupt. But When I turn off the DMA tx over uart. The uart works fine.
    can you please comment on this. Without dma UART works fine., When dma on , rx is not working but tx is., )

**Attention** This is a public forum