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.

MSP430FR5994: Configuring DMA to transfer data over UART

Part Number: MSP430FR5994


Hello,

I am trying to use DMA to transfer data over UART. My aim is to transfer 128 bytes using DMA over UART.

For UART i am using UCA3 and DMA channel 3

In order to achieve this, i wrote following code :

#include <msp430.h>
#include <stdint.h>

const uint16_t tx_char = 128;

volatile unsigned char TXData[128] =
"0123456789d!Hello World!Hello World!Hello World!Hello World!HellHello World!Hello World!Hello World!Hello World!Hello World!Hell";

volatile unsigned char RXData[128];

int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog

// configure gpio to toggle on interrupt
P4OUT &= ~BIT7; // Clear P4.7 output latch for a defined power-on state
P4DIR |= BIT7; // Set P4.7 to output direction

P3DIR |= BIT4;
P3SEL1 |= BIT4; // Output SMCLK

P1DIR |= BIT0;
P1SEL1 |= BIT0; // Output SMCLK

uint16_t c_tx = 0;

// Configure GPIO

P6SEL1 &= ~(BIT0 | BIT1);
P6SEL0 |= (BIT0 | BIT1); // USCI_A3 UART operation

// Disable the GPIO power-on default high-impedance mode to activate
// previously configured port settings
PM5CTL0 &= ~LOCKLPM5;

// Configure USCI_A3 for UART mode
UCA3CTLW0 = UCSWRST; // Put eUSCI in reset
UCA3CTLW0 |= UCSSEL__SMCLK; // CLK = SMCLK
UCA3BRW = 8; // 1000000/115200 = 8.68
UCA3MCTLW = 0xD600; // 1000000/115200 - INT(1000000/115200)=0.68
// UCBRSx value = 0xD6 (See UG)
UCA3CTLW0 &= ~UCSWRST; // release from reset

// disable interrupt functionality to use DMA to perform transfers
UCA3IE &= (~UCTXIE); // Enable USCI_A3 TX interrupt

// configure DMA

DMA3CTL &= ~DMAEN; // DMA trigger should only be set when DMAEN = 0
DMACTL0 = DMA3TSEL__UCA3TXIFG; // UC0TXIFG trigger
// no interrupt pending
//DMACTL0 &= ~DMAIFG;
__data16_write_addr((unsigned short) &DMA3SA, (unsigned long) &TXData);
// Source single address
//__data16_write_addr((unsigned short) &DMA3DA, (unsigned long) &RXData);
__data16_write_addr((unsigned short) &DMA3DA, (unsigned long) &UCA3TXBUF);
// Destination array address
DMA3SZ = 128; // 128 bytes

// enable burst block transfer
// source increment
// enable DMA IE
// byte transfer

DMA3CTL = DMADT_1 + DMAEN + DMASRCINCR + DMASRCBYTE
+ DMADSTBYTE + DMADSTINCR;

__bis_SR_register(GIE); // Enter LPM0, interrupts enabled
__no_operation();

}

//------------------------------------------------------------------------------
// DMA Interrupt Service Routine
//------------------------------------------------------------------------------
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=DMA_VECTOR
__interrupt void DMA_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(DMA_VECTOR))) DMA_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch(__even_in_range(DMAIV,16))
{
case 0: break;
case 2: // DMA0IFG = DMA Channel 0
P1OUT ^= BIT0; // Toggle P1.0 - PLACE BREAKPOINT HERE AND CHECK DMA_DST VARIABLE
break;
case 4: break; // DMA1IFG = DMA Channel 1
case 6: break; // DMA2IFG = DMA Channel 2
case 8: // DMA3IFG = DMA Channel 3
DMA3CTL |= DMAREQ;
P1OUT ^= BIT0; // Toggle P1.0 - PLACE BREAKPOINT HERE AND CHECK DMA_DST VARIABLE
break;
case 10: break; // DMA4IFG = DMA Channel 4
case 12: break; // DMA5IFG = DMA Channel 5
case 14: break; // DMA6IFG = DMA Channel 6
case 16: break; // DMA7IFG = DMA Channel 7
default: break;
}
}

 


Here, I am not able to generate any DMA interrupts. Can someone help me with this?

  • Hi, 

    You're setting the wrong register with this line of code;

    DMACTL0 = DMA3TSEL__UCA3TXIFG; // UC0TXIFG trigger

    DMACTL0 can only setup DMA1 and DMA0 trigger sources. You want to use the DMACTL1 register:

    DMACTL1 = DMA3TSEL__UCA3TXIFG; // UC0TXIFG trigger

    Also, I noticed you've setup your destination address to increment and I don't think this is the behavior you're looking for. You most likely want to leave the destination address unchanged in this scenario.

    At the end of main you have the following code:

    __bis_SR_register(GIE); // Enter LPM0, interrupts enabled
    __no_operation();

    This does not actually put the device into LPM0 and it lets the device exit main which is something you never want to do. You should either change the code to actually enter LPM0 or have an infinite loop at the end of main, 

    Finally, you need something to trigger the DMA start which would be the UCA3TXIFG going from 0 to 1. To start the transfer process you should toggle this interrupt flag from 0 to 1. 

    Best regards, 

    Caleb Overbay

  • Hi,

    Do you still need help with this issue?

    Best regards,
    Caleb Overbay

**Attention** This is a public forum