EmbeddedRelated.com
Forums

DMA problems with F2619

Started by herlhayashi April 15, 2009
Hello everyone,

I'm trying to use the DMA to send a string out to my UART and unfortunately, while the example code that TI provides works, my code does not.

#include
#include
#include "msp430x26x.h"

#define BUFFER_SIZE 16

char uart_out[2*BUFFER_SIZE+1];
int main( void )
{
int i;
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;

BCSCTL1 = CALBC1_1MHZ; // Set DCO
DCOCTL = CALDCO_1MHZ;
for(i!00;i>0;i--); // Wait for DCO to stabilize.

//Setup UART
P3SEL |= 0x30;
UCA0CTL1 |= UCSSEL_1; // UCLK = ACLK
UCA0BR0 = 0x03; // 9600 from 32.768 K
UCA0BR1 = 0x00; //
UCA0MCTL = UCBRS_3; // Modulation

UCA0CTL1 &= ~UCSWRST; // Initialize UART state machine
IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt

//Setup DMA for UART
DMACTL0 = DMA0TSEL_4; //Set to trigger on USCI A0 TX
DMA0SA = (int)uart_out; //Use uart_out as source
DMA0DA = (int)UCA0TXBUF; //use tx buffer as destination
DMA0SZ = sizeof uart_out-1;
DMA0CTL= DMASRCINCR_3 + DMASBDB + DMALEVEL;

_BIS_SR(LPM0_bits + GIE); // CPU off, enable interrupts
}

#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCIAB0RX_ISR (void)
{
unsigned char uart_in;

if (IFG2 & UCA0RXIFG) { // Serial Signal
uart_in = UCA0RXBUF;
memset(uart_out, 0, sizeof(uart_out));
switch (uart_in) {
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '0':
sprintf(uart_out, "%c\r\n", uart_in);
DMA0CTL |= DMAEN;
break;
default:
break;
}
}
}

Beginning Microcontrollers with the MSP430

(1) "DMA0CTL |= DMAEN;" might not work (DMA3 bug)
(2) 20-bit address might not work (DMA4 bug)

--- In m..., "herlhayashi" wrote:
>
> Hello everyone,
>
> I'm trying to use the DMA to send a string out to my UART and unfortunately, while the example code that TI provides works, my code does not.
>
> #include
> #include
> #include "msp430x26x.h"
>
> #define BUFFER_SIZE 16
>
> char uart_out[2*BUFFER_SIZE+1];
> int main( void )
> {
> int i;
> // Stop watchdog timer to prevent time out reset
> WDTCTL = WDTPW + WDTHOLD;
>
> BCSCTL1 = CALBC1_1MHZ; // Set DCO
> DCOCTL = CALDCO_1MHZ;
> for(i!00;i>0;i--); // Wait for DCO to stabilize.
>
> //Setup UART
> P3SEL |= 0x30;
> UCA0CTL1 |= UCSSEL_1; // UCLK = ACLK
> UCA0BR0 = 0x03; // 9600 from 32.768 K
> UCA0BR1 = 0x00; //
> UCA0MCTL = UCBRS_3; // Modulation
>
> UCA0CTL1 &= ~UCSWRST; // Initialize UART state machine
> IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
>
> //Setup DMA for UART
> DMACTL0 = DMA0TSEL_4; //Set to trigger on USCI A0 TX
> DMA0SA = (int)uart_out; //Use uart_out as source
> DMA0DA = (int)UCA0TXBUF; //use tx buffer as destination
> DMA0SZ = sizeof uart_out-1;
> DMA0CTL= DMASRCINCR_3 + DMASBDB + DMALEVEL;
>
> _BIS_SR(LPM0_bits + GIE); // CPU off, enable interrupts
> }
>
> #pragma vector=USCIAB0RX_VECTOR
> __interrupt void USCIAB0RX_ISR (void)
> {
> unsigned char uart_in;
>
> if (IFG2 & UCA0RXIFG) { // Serial Signal
> uart_in = UCA0RXBUF;
> memset(uart_out, 0, sizeof(uart_out));
> switch (uart_in) {
> case '1':
> case '2':
> case '3':
> case '4':
> case '5':
> case '6':
> case '7':
> case '8':
> case '9':
> case '0':
> sprintf(uart_out, "%c\r\n", uart_in);
> DMA0CTL |= DMAEN;
> break;
> default:
> break;
> }
> }
> }
>

DMAEN flag is not set in init. (another hint use | instead of +).

M.

"herlhayashi" :

> Hello everyone,
>
> I'm trying to use the DMA to send a string out to my UART and
> unfortunately, while the example code that TI provides works, my code
> does not.
>
> #include
> #include
> #include "msp430x26x.h"
>
> #define BUFFER_SIZE 16
>
> char uart_out[2*BUFFER_SIZE+1];
> int main( void )
> {
> int i;
> // Stop watchdog timer to prevent time out reset
> WDTCTL = WDTPW + WDTHOLD;
>
> BCSCTL1 = CALBC1_1MHZ; // Set DCO
> DCOCTL = CALDCO_1MHZ;
> for(i!00;i>0;i--); // Wait for DCO to
> stabilize.
>
> //Setup UART
> P3SEL |= 0x30;
> UCA0CTL1 |= UCSSEL_1; // UCLK = ACLK
> UCA0BR0 = 0x03; // 9600 from 32.768 K
> UCA0BR1 = 0x00; //
> UCA0MCTL = UCBRS_3; // Modulation
>
> UCA0CTL1 &= ~UCSWRST; // Initialize UART state
> machine IE2 |= UCA0RXIE; // Enable USCI_A0 RX interrupt
>
> //Setup DMA for UART
> DMACTL0 = DMA0TSEL_4; //Set to trigger on USCI A0
> TX DMA0SA = (int)uart_out; //Use uart_out as source
> DMA0DA = (int)UCA0TXBUF; //use tx buffer as
> destination DMA0SZ = sizeof uart_out-1;
> DMA0CTL= DMASRCINCR_3 + DMASBDB + DMALEVEL;
>
> _BIS_SR(LPM0_bits + GIE); // CPU off, enable
> interrupts
> }
>
> #pragma vector=USCIAB0RX_VECTOR
> __interrupt void USCIAB0RX_ISR (void)
> {
> unsigned char uart_in;
>
> if (IFG2 & UCA0RXIFG) { // Serial Signal
> uart_in = UCA0RXBUF;
> memset(uart_out, 0, sizeof(uart_out));
> switch (uart_in) {
> case '1':
> case '2':
> case '3':
> case '4':
> case '5':
> case '6':
> case '7':
> case '8':
> case '9':
> case '0':
> sprintf(uart_out, "%c\r\n", uart_in);
> DMA0CTL |= DMAEN;
> break;
> default:
> break;
> }
> }
> }
>

--- In m..., Matthias Weingart wrote:
>
> DMAEN flag is not set in init. (another hint use | instead of +).
>
> M.
>
> "herlhayashi" shayashi@...:
>
> > Hello everyone,
> >
> > I'm trying to use the DMA to send a string out to my UART and
> > unfortunately, while the example code that TI provides works, my
code
> > does not.
> >
> > #include
> > #include
> > #include "msp430x26x.h"
> >
> > #define BUFFER_SIZE 16
> >
> > char uart_out[2*BUFFER_SIZE+1];
> > int main( void )
> > {
> > int i;
> > // Stop watchdog timer to prevent time out reset
> > WDTCTL = WDTPW + WDTHOLD;
> >
> > BCSCTL1 = CALBC1_1MHZ; // Set DCO
> > DCOCTL = CALDCO_1MHZ;
> > for(i!00;i>0;i--); // Wait for DCO to
> > stabilize.
> >
> > //Setup UART
> > P3SEL |= 0x30;
> > UCA0CTL1 |= UCSSEL_1; // UCLK = ACLK
> > UCA0BR0 = 0x03; // 9600 from 32.768 K
> > UCA0BR1 = 0x00; //
> > UCA0MCTL = UCBRS_3; // Modulation
> >
> > UCA0CTL1 &= ~UCSWRST; // Initialize UART state
> > machine IE2 |= UCA0RXIE; // Enable USCI_A0 RX
interrupt
> >
> > //Setup DMA for UART
> > DMACTL0 = DMA0TSEL_4; //Set to trigger on USCI
A0
> > TX DMA0SA = (int)uart_out; //Use uart_out as
source
> > DMA0DA = (int)UCA0TXBUF; //use tx buffer as
> > destination DMA0SZ = sizeof uart_out-1;
> > DMA0CTL= DMASRCINCR_3 + DMASBDB + DMALEVEL;
> >
> > _BIS_SR(LPM0_bits + GIE); // CPU off, enable
> > interrupts
> > }
> >
> > #pragma vector=USCIAB0RX_VECTOR
> > __interrupt void USCIAB0RX_ISR (void)
> > {
> > unsigned char uart_in;
> >
> > if (IFG2 & UCA0RXIFG) { // Serial Signal
> > uart_in = UCA0RXBUF;
> > memset(uart_out, 0, sizeof(uart_out));
> > switch (uart_in) {
> > case '1':
> > case '2':
> > case '3':
> > case '4':
> > case '5':
> > case '6':
> > case '7':
> > case '8':
> > case '9':
> > case '0':
> > sprintf(uart_out, "%c\r\n", uart_in);
> > DMA0CTL |= DMAEN;
> > break;
> > default:
> > break;
> > }
> > }
> > }
> >
> >
>

So DMAEN is supposed to be set on init? If so, then how do you start
the DMA when it's supposed to start?

-S

P.S. To everyone, sorry about spamming the board with a post bereft of
content.
--- In m..., Matthias Weingart wrote:
>
> DMAEN flag is not set in init. (another hint use | instead of +).
>
> M.
>

"herlhayashi" :

>
> So DMAEN is supposed to be set on init? If so, then how do you start
> the DMA when it's supposed to start?

I see. You are start the DMA tranfer using the RX Interrupt. Then this should
work (but see the errata, use "=" with all your bits and not "|=" ).
Maybe you also have to set UCA0TXIFG to trigger the first transfer.
However I would never use sprintf from within interrupt routines.

M.