EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

dma problem msp430fg4618

Started by petebrayuk November 20, 2010
I'm using crossworks v2, and msp430fg4618 and trying to output a 256 word waveform out of DAC12_1 using dma. I'm triggering the dma transfer using timerA and passing the data directly through to the DAC rather than triggering the dac latch with a timer. i generate an IRQ after the 256 samples have been DMA transferred. This method seems to do what i want with one exception - i can't get the correct data to appear out of the DAC. i can put an arbitary address in to the DMA source register and see the garbage i would expect out of the dac, but i can't seem to point the source register at my array. here's the relevant source...

#define NumDACoutputWords 256
int DACoutputData[NumDACoutputWords];
//array is then filled with square wave
...
//set up vref etc
...
//set up the DMA to transfer array data to DAC
DMA1SA = (int)DACoutputData; // Source block address
DMA1DA = DAC12_1DAT_; // Destination address
DMA1SZ = NumDACoutputWords; // Block size
DMACTL0 = DMA1TSEL_7; //TimerA triggers DMA1
DMA1CTL = DMADT_0 + DMASRCINCR_3 + DMAIE + DMAEN;
//setup dac12_1
DAC12_1CTL = DAC12LSEL_0 + DAC12IR + DAC12AMP_5 + DAC12ENC;
//setup timerA and start
TACCTL1 = OUTMOD_3; // TACCR1 set/reset
TACCR1 = 01; // TACCR1 PWM Duty Cycle
//SMCLK=8MHz, want output at 20kHz, so tick every 400 cycles
TACCR0 = 400-1;
//up mode, SMCLK, start immediate
TACTL = TASSEL_2 + MC_1;
//enable interrupts

i call this code in a loop and can observe the output on a scope. if i change the DMA1SA to point to 0x0100 for example i can trigger the scope on a repeating waveform of 'random' data. the data interval and sample length both appear to be correct. the question is, can anyone advise me how to set the dma source register to point to my array in ram using crossworks? many thanks in advance.

Beginning Microcontrollers with the MSP430

It looks like you've set the DMA to trigger on TACCR0 CCIFG, but you're trying to use TACCR1 to trigger (or so I assume, you didn't include your last line which enables the interrupts?). I don't think that this will work, since the DMA can only trigger on TACCR2 and TACCR0 (and the interrupts at that, not the output).

There's a TI example that does essentially what you're trying to do, but they have the DMA trigger from the DAC rather than from the Timer, and the Timer triggers the DAC.

-Steve

void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
ADC12CTL0 = REFON; // Internal reference
DMA0SA = (int)Sin_tab; // Source block address
DMA0DA = DAC12_0DAT_; // Destination single address
DMA0SZ = 0x020; // Block size
DMACTL0 = DMA0TSEL_5; // DAC12IFG trigger
DMA0CTL = DMADT_4 + DMASRCINCR_3 + DMAEN; // Rpt, inc src, word-word
DAC12_0CTL = DAC12LSEL_2 + DAC12IR + DAC12AMP_5 + DAC12IFG + DAC12ENC;
TACCTL1 = OUTMOD_3; // TACCR1 set/reset
TACCR1 = 01; // TACCR1 PWM Duty Cycle
TACCR0 = 032-1; // Clock period of TACCR0
TACTL = TASSEL_2 + MC_1; // SMCLK, contmode
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0
}
-----Original Message-----
From: m... [mailto:m...] On Behalf Of petebrayuk
Sent: Saturday, November 20, 2010 4:08 PM
To: m...
Subject: [msp430] dma problem msp430fg4618

I'm using crossworks v2, and msp430fg4618 and trying to output a 256 word waveform out of DAC12_1 using dma. I'm triggering the dma transfer using timerA and passing the data directly through to the DAC rather than triggering the dac latch with a timer. i generate an IRQ after the 256 samples have been DMA transferred. This method seems to do what i want with one exception - i can't get the correct data to appear out of the DAC. i can put an arbitary address in to the DMA source register and see the garbage i would expect out of the dac, but i can't seem to point the source register at my array. here's the relevant source...

#define NumDACoutputWords 256
int DACoutputData[NumDACoutputWords];
//array is then filled with square wave
...
//set up vref etc
...
//set up the DMA to transfer array data to DAC
DMA1SA = (int)DACoutputData; // Source block address
DMA1DA = DAC12_1DAT_; // Destination address
DMA1SZ = NumDACoutputWords; // Block size
DMACTL0 = DMA1TSEL_7; //TimerA triggers DMA1
DMA1CTL = DMADT_0 + DMASRCINCR_3 + DMAIE + DMAEN;
//setup dac12_1
DAC12_1CTL = DAC12LSEL_0 + DAC12IR + DAC12AMP_5 + DAC12ENC;
//setup timerA and start
TACCTL1 = OUTMOD_3; // TACCR1 set/reset
TACCR1 = 01; // TACCR1 PWM Duty Cycle
//SMCLK=8MHz, want output at 20kHz, so tick every 400 cycles
TACCR0 = 400-1;
//up mode, SMCLK, start immediate
TACTL = TASSEL_2 + MC_1;
//enable interrupts

i call this code in a loop and can observe the output on a scope. if i change the DMA1SA to point to 0x0100 for example i can trigger the scope on a repeating waveform of 'random' data. the data interval and sample length both appear to be correct. the question is, can anyone advise me how to set the dma source register to point to my array in ram using crossworks? many thanks in advance.

Steve,

Thanks for looking over this code for me and spotting some errors. I'll test
out your suggestions.

Curiously, the dma operation does seem to run ok because the dma completion
interrupt does get called after the expected number of samples have been
passed to the DAC. The reason I did not trigger the DMA from the DAC is
because I thought that I could only do this from DAC12_0 and I'm using
DAC12_1 (because DAC12_0 pin is mux'd with an op-amp that I'm using).
Clearly I need to revisit the plan!

Meanwhile, the TI example is useful. However, I did already look at this and
I was not sure that it was correct for the 4618 because shouldn't the lookup
table address be passed as a 20bit pointer to the dma source address
register? I did experiment with trying to pass a 20bit address in my
application in case this had been the cause of my problem but since my array
is in RAM I think that a 16 bit address should be sufficient.

Thanks once again, and I will re-think my triggering strategy when I get
back to the h/w in a couple of days.

Regards, pete

-----Original Message-----
From: m... [mailto:m...] On Behalf Of
Hayashi, Steve
Sent: 22 November 2010 2:22 PM
To: m...
Subject: RE: [msp430] dma problem msp430fg4618

It looks like you've set the DMA to trigger on TACCR0 CCIFG, but you're
trying to use TACCR1 to trigger (or so I assume, you didn't include your
last line which enables the interrupts?). I don't think that this will
work, since the DMA can only trigger on TACCR2 and TACCR0 (and the
interrupts at that, not the output).

There's a TI example that does essentially what you're trying to do, but
they have the DMA trigger from the DAC rather than from the Timer, and the
Timer triggers the DAC.

-Steve

void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
ADC12CTL0 = REFON; // Internal reference
DMA0SA = (int)Sin_tab; // Source block address
DMA0DA = DAC12_0DAT_; // Destination single address
DMA0SZ = 0x020; // Block size
DMACTL0 = DMA0TSEL_5; // DAC12IFG trigger
DMA0CTL = DMADT_4 + DMASRCINCR_3 + DMAEN; // Rpt, inc src, word-word
DAC12_0CTL = DAC12LSEL_2 + DAC12IR + DAC12AMP_5 + DAC12IFG + DAC12ENC;
TACCTL1 = OUTMOD_3; // TACCR1 set/reset
TACCR1 = 01; // TACCR1 PWM Duty Cycle
TACCR0 = 032-1; // Clock period of TACCR0
TACTL = TASSEL_2 + MC_1; // SMCLK, contmode
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0
}
-----Original Message-----
From: m... [mailto:m...] On Behalf Of
petebrayuk
Sent: Saturday, November 20, 2010 4:08 PM
To: m...
Subject: [msp430] dma problem msp430fg4618

I'm using crossworks v2, and msp430fg4618 and trying to output a 256 word
waveform out of DAC12_1 using dma. I'm triggering the dma transfer using
timerA and passing the data directly through to the DAC rather than
triggering the dac latch with a timer. i generate an IRQ after the 256
samples have been DMA transferred. This method seems to do what i want with
one exception - i can't get the correct data to appear out of the DAC. i can
put an arbitary address in to the DMA source register and see the garbage i
would expect out of the dac, but i can't seem to point the source register
at my array. here's the relevant source...

#define NumDACoutputWords 256
int DACoutputData[NumDACoutputWords];
//array is then filled with square wave
...
//set up vref etc
...
//set up the DMA to transfer array data to DAC
DMA1SA = (int)DACoutputData; // Source block address
DMA1DA = DAC12_1DAT_; // Destination address
DMA1SZ = NumDACoutputWords; // Block size
DMACTL0 = DMA1TSEL_7; //TimerA triggers DMA1
DMA1CTL = DMADT_0 + DMASRCINCR_3 + DMAIE + DMAEN;
//setup dac12_1
DAC12_1CTL = DAC12LSEL_0 + DAC12IR + DAC12AMP_5 + DAC12ENC;
//setup timerA and start
TACCTL1 = OUTMOD_3; // TACCR1 set/reset
TACCR1 = 01; // TACCR1 PWM Duty Cycle
//SMCLK=8MHz, want output at 20kHz, so tick every 400 cycles
TACCR0 = 400-1;
//up mode, SMCLK, start immediate
TACTL = TASSEL_2 + MC_1;
//enable interrupts

i call this code in a loop and can observe the output on a scope. if i
change the DMA1SA to point to 0x0100 for example i can trigger the scope on
a repeating waveform of 'random' data. the data interval and sample length
both appear to be correct. the question is, can anyone advise me how to set
the dma source register to point to my array in ram using crossworks? many
thanks in advance.

There are other examples of course, but it seems as though the easiest for you would be to move everything to CCR2 and see what happens.

And I saw another TI example that's even closer to what you're doing, though my guess is that you're already using this Timer B for something else.

-Steve

void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
DMA2SA = (int)Sin_tab; // Source block address
DMA2DA = DAC12_1DAT_; // Destination single address
DMA2SZ = 0x020; // Block size
DMACTL0 = DMA2TSEL_2; // TBCCR2 trigger
DMA2CTL = DMASBDB + DMADT_4 + DMASRCINCR_3 + DMAEN; // Rpt, inc src, byte-byte
DAC12_1CTL = DAC12SREF_2 + DAC12RES + DAC12LSEL_3 + DAC12IR + DAC12AMP_5 + DAC12ENC;
TBCCTL2 = OUTMOD_7; // Reset/set
TBCCR2 = 01; // PWM Duty Cycle
TBCCR0 = 032 - 1; // Clock period of TBCCR0
TBCTL = TBSSEL_2 + MC_1; // SMCLK, up mode
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0
}

-----Original Message-----
From: m... [mailto:m...] On Behalf Of Pete Bray
Sent: Monday, November 22, 2010 1:32 PM
To: m...
Subject: RE: [msp430] dma problem msp430fg4618

Steve,

Thanks for looking over this code for me and spotting some errors. I'll test
out your suggestions.

Curiously, the dma operation does seem to run ok because the dma completion
interrupt does get called after the expected number of samples have been
passed to the DAC. The reason I did not trigger the DMA from the DAC is
because I thought that I could only do this from DAC12_0 and I'm using
DAC12_1 (because DAC12_0 pin is mux'd with an op-amp that I'm using).
Clearly I need to revisit the plan!

Meanwhile, the TI example is useful. However, I did already look at this and
I was not sure that it was correct for the 4618 because shouldn't the lookup
table address be passed as a 20bit pointer to the dma source address
register? I did experiment with trying to pass a 20bit address in my
application in case this had been the cause of my problem but since my array
is in RAM I think that a 16 bit address should be sufficient.

Thanks once again, and I will re-think my triggering strategy when I get
back to the h/w in a couple of days.

Regards, pete

-----Original Message-----
From: m... [mailto:m...] On Behalf Of
Hayashi, Steve
Sent: 22 November 2010 2:22 PM
To: m...
Subject: RE: [msp430] dma problem msp430fg4618

It looks like you've set the DMA to trigger on TACCR0 CCIFG, but you're
trying to use TACCR1 to trigger (or so I assume, you didn't include your
last line which enables the interrupts?). I don't think that this will
work, since the DMA can only trigger on TACCR2 and TACCR0 (and the
interrupts at that, not the output).

There's a TI example that does essentially what you're trying to do, but
they have the DMA trigger from the DAC rather than from the Timer, and the
Timer triggers the DAC.

-Steve

void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
ADC12CTL0 = REFON; // Internal reference
DMA0SA = (int)Sin_tab; // Source block address
DMA0DA = DAC12_0DAT_; // Destination single address
DMA0SZ = 0x020; // Block size
DMACTL0 = DMA0TSEL_5; // DAC12IFG trigger
DMA0CTL = DMADT_4 + DMASRCINCR_3 + DMAEN; // Rpt, inc src, word-word
DAC12_0CTL = DAC12LSEL_2 + DAC12IR + DAC12AMP_5 + DAC12IFG + DAC12ENC;
TACCTL1 = OUTMOD_3; // TACCR1 set/reset
TACCR1 = 01; // TACCR1 PWM Duty Cycle
TACCR0 = 032-1; // Clock period of TACCR0
TACTL = TASSEL_2 + MC_1; // SMCLK, contmode
__bis_SR_register(LPM0_bits + GIE); // Enter LPM0
}
-----Original Message-----
From: m... [mailto:m...] On Behalf Of
petebrayuk
Sent: Saturday, November 20, 2010 4:08 PM
To: m...
Subject: [msp430] dma problem msp430fg4618

I'm using crossworks v2, and msp430fg4618 and trying to output a 256 word
waveform out of DAC12_1 using dma. I'm triggering the dma transfer using
timerA and passing the data directly through to the DAC rather than
triggering the dac latch with a timer. i generate an IRQ after the 256
samples have been DMA transferred. This method seems to do what i want with
one exception - i can't get the correct data to appear out of the DAC. i can
put an arbitary address in to the DMA source register and see the garbage i
would expect out of the dac, but i can't seem to point the source register
at my array. here's the relevant source...

#define NumDACoutputWords 256
int DACoutputData[NumDACoutputWords];
//array is then filled with square wave
...
//set up vref etc
...
//set up the DMA to transfer array data to DAC
DMA1SA = (int)DACoutputData; // Source block address
DMA1DA = DAC12_1DAT_; // Destination address
DMA1SZ = NumDACoutputWords; // Block size
DMACTL0 = DMA1TSEL_7; //TimerA triggers DMA1
DMA1CTL = DMADT_0 + DMASRCINCR_3 + DMAIE + DMAEN;
//setup dac12_1
DAC12_1CTL = DAC12LSEL_0 + DAC12IR + DAC12AMP_5 + DAC12ENC;
//setup timerA and start
TACCTL1 = OUTMOD_3; // TACCR1 set/reset
TACCR1 = 01; // TACCR1 PWM Duty Cycle
//SMCLK=8MHz, want output at 20kHz, so tick every 400 cycles
TACCR0 = 400-1;
//up mode, SMCLK, start immediate
TACTL = TASSEL_2 + MC_1;
//enable interrupts

i call this code in a loop and can observe the output on a scope. if i
change the DMA1SA to point to 0x0100 for example i can trigger the scope on
a repeating waveform of 'random' data. the data interval and sample length
both appear to be correct. the question is, can anyone advise me how to set
the dma source register to point to my array in ram using crossworks? many
thanks in advance.

Use 16bit DMA with crossworks - basically they still use the 16bit mode for
RAM and constants in flash; only the code can sitting in the upper address
range - so 16bit DMA is sufficient.
I think there are also CPU Bugs with 20bit DMA (take a look in the errate of
the 2618).

M.

Pete Bray :

> Meanwhile, the TI example is useful. However, I did already look at this
> and I was not sure that it was correct for the 4618 because shouldn't
> the lookup table address be passed as a 20bit pointer to the dma source
> address register? I did experiment with trying to pass a 20bit address
> in my application in case this had been the cause of my problem but
> since my array is in RAM I think that a 16 bit address should be
> sufficient.


The 2024 Embedded Online Conference