Hi,
I'm developing a small program to test the ADC12 + DMA + TimerB Trigger on an MSP430F5438 (Olimex MSP430-H5438).
I wrote a piece of code to configure ADC12 to sample 4 channels (in Sequence Of Channels mode) using TimerB0 as trigger.
Everything works fine without DMA, I see the ADC interrupt fired up when the sequence of channels has finished, but when I add the DMA code, the DMA interrupt is never fired and I can't understand why.
The code I'm actually using is the following:
#ifdef __MSP430F5438__
#include <msp430f5438.h>
#endif
#include "dcolib.h"
unsigned int adcReadings[64];
unsigned int adcReadingsCounter;
unsigned int tmp;
unsigned int ADCMemBuf[4];
#define USE_DMA
void main(void)
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
// Port Initialization (Olimex MSP430-H5438)
PASEL = PBSEL = PCSEL = PDSEL = PESEL = PFSEL = 0x0000; // All GPIO
PADIR = PBDIR = PCDIR = PDDIR = PEDIR = PFDIR = 0xFFFF; // All OUTPUT
PAOUT = PBOUT = PCOUT = PDOUT = PEOUT = PFOUT = 0x0000; // All 0
// DCO Calibration (MCLK = 16MHz, SMCLK = 8MHz)
if ( calibrate_dco() != DCO_NO_ERROR )
WDTCTL = 0;
adcReadingsCounter = 0;
P6SEL |= (BIT2 | BIT3 | BIT4 | BIT5); // ADC Peripheral Function
P6DIR &= ~(BIT2 | BIT3 | BIT4 | BIT5); // ADC Input Direction
P4SEL |= BIT1; // TimerB0.1OUT Peripheral Function
P4DIR |= BIT1; // TimerB0.1OUT Output Direction
ADC12CTL0 = ADC12MSC | ADC12SHT0_2 | ADC12ON | ADC12REFON | ADC12REF2_5V;
ADC12CTL1 = ADC12SHP | ADC12SHS_3 | ADC12SSEL_3 | ADC12DIV_1 | ADC12CONSEQ_1;
ADC12CTL2 = ADC12RES_2 | ADC12TCOFF;
ADC12MCTL0 = ADC12INCH_2 | ADC12SREF_1;
ADC12MCTL1 = ADC12INCH_3 | ADC12SREF_1;
ADC12MCTL2 = ADC12INCH_4 | ADC12SREF_1;
ADC12MCTL3 = ADC12INCH_5 | ADC12SREF_1 | ADC12EOS;
#ifdef USE_DMA
// Configure DMA0 (ADC12IFG trigger)
DMACTL0 = DMA0TSEL_24; // ADC12IFG trigger
DMACTL4 = DMARMWDIS; // Read-modify-write disable
DMA0CTL &= ~DMAIFG;
__data16_write_addr((unsigned short)&DMA0SA, (unsigned long)&ADC12MEM0); // Source single address
__data16_write_addr((unsigned short)&DMA0DA, (unsigned long)&ADCMemBuf); // Destination array address
DMA0SZ = 4; // 4 ADC conversions
DMA0CTL = DMADT_4 | DMADSTINCR_3 | DMASRCINCR_3 | DMAEN | DMAIE; // Rpt, inc dest, inc src, enable int after seq of convs
#else
ADC12IE = BIT3;
#endif
// Wait Refon
msDelay(20);
// Enable conversion
ADC12CTL0 |= ADC12ENC;
// TB0CCR0, TB0CCR1, OUTMOD_4 to get a rising edge every 1ms on TB0.1
TB0CCR0 = (SMCLK_TICKS_PER_MS >> 1); // Total Sampling Time
TB0CCR1 = (SMCLK_TICKS_PER_MS >> 2); // Sampling Period (TB0.1)
TB0CCTL1 = OUTMOD_4; // Trigger ADC conversion mode
TB0CTL = TBSSEL_2 | MC_1 | TBCLR; // SMCLK, Up mode
// Enable GIE
__bis_SR_register(GIE);
// Do nothing
while(1);
}
#ifdef USE_DMA
#pragma vector=DMA_VECTOR
__interrupt void DMA0_ISR (void)
{
switch(__even_in_range(DMAIV,16))
{
case 0: break; // No interrupt
case 2: // DMA0IFG
// ADC10 conversions completed
// Need to set again the ADC12ENC
ADC12CTL0 |= ADC12ENC;
// Toggle port (to debug on oscilloscope)
P8OUT ^= BIT4;
break;
case 4: break; // DMA1IFG
case 6: break; // DMA2IFG
case 8: break; // Reserved
case 10: break; // Reserved
case 12: break; // Reserved
case 14: break; // Reserved
case 16: break; // Reserved
default: break;
}
}
#else
#pragma vector=ADC12_VECTOR
__interrupt void ADC12_ISR (void)
{
switch(__even_in_range(ADC12IV,12))
{
case 0: break; // Vector 0: No interrupt
case 2: break; // Vector 2: ADC overflow
case 4: break; // Vector 4: ADC timing overflow
case 6: break; // Vector 6: ADC12IFG0
case 8: break; // Vector 8: ADC12IFG1
case 10: break; // Vector 10: ADC12IFG2
case 12: // Vector 12: ADC12IFG3
tmp = ADC12MEM0;
tmp = ADC12MEM1;
tmp = ADC12MEM2;
tmp = ADC12MEM3;
adcReadingsCounter++;
// Need to set again the ADC12ENC
ADC12CTL0 |= ADC12ENC;
if(adcReadingsCounter == 20)
{
adcReadingsCounter = 0;
// Toggle port (to debug on oscilloscope)
P8OUT ^= BIT4;
}
break;
case 14: break; // Vector 14: ADC12IFG4
case 16: break; // Vector 16: ADC12IFG5
case 18: break; // Vector 18: ADC12IFG6
case 20: break; // Vector 20: ADC12IFG7
case 22: break; // Vector 22: ADC12IFG8
case 24: break; // Vector 24: ADC12IFG9
case 26: break; // Vector 26: ADC12IFG10
case 28: break; // Vector 28: ADC12IFG11
case 30: break; // Vector 30: ADC12IFG12
case 32: break; // Vector 32: ADC12IFG13
case 34: break; // Vector 34: ADC12IFG14
default: break;
}
}
#endif
Thanks for any help and suggestions.
Regards,
Samuele.