Hi,
I've been having issues with DMA and the ADC with this uC. Specifically with the DMA triggers. I've integrated background sampling of analog channels to an existing project using a timer to trigger the ADC and DMA to move the samples. I finally got it working, but encountered many issues, so I decided to try a minimal example and found similar issues. Maybe I'm not understanding the datasheet, but this fairly simple example fails to trigger:
#include <io430.h> void ConfigADC( void ) { ADC12CTL0 &= ~ADC12ENC; ADC12CTL0 &= ~ADC12ON; ADC12CTL0 = ADC12SHT0_2 | ADC12MSC_0; ADC12CTL1 |= ADC12SHS_0 // Sample-and-hold source = SC bit | ADC12SHP // SAMPCON signal is sourced from the sampling timer. | !ADC12ISSH // sample-input signal not inverted | ADC12DIV_0 // ADC12 clock divider /1 | ADC12SSEL_2 // ADC12 clock source = MCLK | ADC12CONSEQ_0; // Sequence-of-Channels Mode ADC12CTL2 = ADC12RES__12BIT; ADC12CTL3 = ADC12CSTARTADD_0; ADC12MCTL0 = ADC12VRSEL_0 | ADC12INCH_0; ADC12IER0 = ADC12IER1 = ADC12IER2 = 0; ADC12IFGR0 = ADC12IFGR1 = ADC12IFGR2 = 0; ADC12CTL0 |= ADC12ON; } unsigned int Convert( void ) { ADC12IFGR0 = 0; ADC12CTL0 |= ADC12ON; ADC12CTL0 &= ~ADC12ENC; ADC12CTL0 |= ADC12ENC | ADC12SC; while ( !ADC12IFGR0 ) {} unsigned int adcResult = ADC12MEM0; ADC12CTL0 &= ~ADC12ENC; ADC12CTL0 &= ~ADC12ON; return adcResult; } unsigned int TestVar1, TestVar2; void ConfigDMA() { DMA0CTL &= ~DMAEN__ENABLE; DMACTL0 = DMA0TSEL__ADC12IFG; DMA0CTL = DMADT_4 | DMADSTINCR_0 | DMASRCINCR_0 | DMADSTBYTE__WORD | DMASRCBYTE__WORD | DMALEVEL__EDGE | DMAIE__ENABLE; __data16_write_addr((unsigned short)&DMA0SA, (unsigned long) &TestVar1); __data16_write_addr((unsigned short)&DMA0DA, (unsigned long) &TestVar2); DMA0SZ = 1; DMA0CTL |= DMAEN__ENABLE; } #pragma vector = DMA_VECTOR __interrupt void DMA_ISR( void ) { static int int_count = 0; switch ( __even_in_range( DMAIV, 0x10 ) ) { case DMAIV__DMA0IFG: int_count++; break; } } void main( void ) { WDTCTL = (WDTPW | WDTHOLD); __enable_interrupt(); ConfigADC(); Convert(); //this breaks the DMA trigger ConfigDMA(); Convert(); Convert(); Convert(); Convert(); __no_operation(); }
I've found that doing an ADC conversion before setting up the DMA breaks it, meaning that it'll never trigger with the ADC12IFGR0. Even if I reconfigure the DMA and the ADC all over again (clearing every register before). When I run the above example with a breakpoint at the __no_operation(), I see int_count == 0 , which means the interrupt never occurred, also the DMA IFG is not set, which means that DMA never triggered. The ADC works just fines because I get to the __no_operation() at the end (if the ADC flag had not been raised, the uC would have been stuck in the while loop).
Commenting the line where Convert() is called before ConfigDMA() works as expected, int_count == 4 at the end of execution.
Is there an issue with the code?
Thanks in advance,
Federico