Hi,
I am having similar problem with what was described in this e2e thread.
The erratasheet doesn't mention anything about the DMA. So I wonder what I should do to make the DMA work after being stopped and re-enabled.
Context:
- Use ADC MEM0 to convert channel 1. The ADC is triggered by TimerA0 every 312.5us.
- Use DMA to move 64 consecutive results to a buffer in SRAM. The DMA works well.
- Disable the DMA after 64 transfers
- Use ADC MEM0 to convert channel 2 once
- Re-enable DMA
- Use ADC MEM0 to convert channel 1, again. Use DMA to move 64 consecutive results to a buffer in SRAM. This time the DMA doesn't work (no transfer happens).
Below is the code I used.
#include <msp430fr5994.h> #include <stdint.h> #define TRANSFER_SIZE 64 unsigned int result_A3 = 0; unsigned int result_array[100]; void InitClock() { // Clock System Setup CSCTL0_H = CSKEY_H; // Unlock CS registers CSCTL1 = DCOFSEL_0; // Set DCO to 1MHz // CSCTL2 = SELA__LFMODCLK | SELS__DCOCLK | SELM__DCOCLK; // Set ACLK = 32kHz crystal, SMCLK = MCLK = DCO CSCTL2 = SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK; // Per Device Errata set divider to 4 before changing frequency to // prevent out of spec operation from overshoot transient CSCTL3 = DIVA__4 | DIVS__4 | DIVM__4; // Set all corresponding clk sources to divide by 4 for errata CSCTL1 = DCOFSEL_3; // Set DCO to 4MHz // Delay by ~10us to let DCO settle. 60 cycles = 20 cycles buffer + (10us / (1/4MHz)) __delay_cycles(100); CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1; // MCLK = 4MHz, SMCLK = 4MHz, ACLK = 4MHz CSCTL0_H = 0; // Lock CS Registers } void InitTimer() { /* TA0CCR0 = 1249; TA0CCTL1 = OUTMOD_3; // TACCR1 output mode = set/reset TA0CCR1 = 1200; // TACCR1 PWM Duty Cycle TA0CTL = TASSEL__SMCLK | MC__UP; // SMCLK, up mode*/ TA0CCTL0 = CCIE; // TACCR0 interrupt enabled TA0CCR0 = 1249; // trigger cycle for ADC is 312.5us = (4MHz/3200) TA0CCTL1 = OUTMOD_3; // TACCR1 output mode = set/reset TA0CCR1 = 1200; // TACCR1 is the trigger source for ADC TA0CTL = TASSEL__SMCLK | MC__UP; // SMCLK, up mode } void InitDMA() { /* // Configure DMA channel 0 __data20_write_long((uintptr_t) &DMA0SA,(uintptr_t) 0x1C20); // Source block address __data20_write_long((uintptr_t) &DMA0DA,(uintptr_t) 0x1C40); // Destination single address DMA0SZ = 16; // Block size DMA0CTL = DMADT_5 | DMASRCINCR_3 | DMADSTINCR_3; // Rpt, inc */ DMACTL0 |= DMA0TSEL__ADC12IFG; __data16_write_addr((unsigned short) &DMA0SA,(unsigned long) &ADC12MEM0); __data16_write_addr((unsigned short) &DMA0DA,(unsigned long) &result_array[0]); DMA0SZ = TRANSFER_SIZE; // 64 conversions DMA0CTL = DMADT_4 + DMADSTINCR_3 + DMAEN; } void InitADC() { P1SEL1 |= BIT3 + BIT4; // Configure P1.3 (A3) for ADC light sensor, Configure P1.4 (A4) for ADC batt voltage P1SEL0 |= BIT3 + BIT4; ADC12CTL1 = 0; ADC12CTL0 = 0; ADC12CTL0 |= ADC12ON; // Turn on. No sample or conversion starts ADC12CTL1 = ADC12PDIV__1 + ADC12SHS_1 // TA0 CCR1 triggers conversion + ADC12SHP + ADC12CONSEQ_2; // repeated single channel ADC12CTL2 = ADC12RES__12BIT; ADC12CTL3 = 0; // start address = MEM0 ADC12LO = 0; // comparator hi and lo thresholds ADC12HI = 0x0FFF; ADC12IFGR0 = 0; // clear all pending flags if any ADC12IFGR1 = 0; ADC12IFGR2 = 0; ADC12IER0 = 0; // interrupt disabled ADC12IER1 = 0; ADC12IER2 = 0; ADC12MCTL0 = ADC12EOS // end of sequence + ADC12INCH_4; // A4 single-ended ADC12CTL0 |= ADC12ENC; // enable conversions } void InitIO() { // Configure GPIO P1OUT = 0; P1DIR = BIT0|BIT5; // For LED // Disable the GPIO power-on default high-impedance mode to activate // previously configured port settings PM5CTL0 &= ~LOCKLPM5; } /** * main.c */ int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop WDT InitClock(); InitIO(); P1OUT|= BIT5; InitADC(); InitTimer(); InitDMA(); // __bis_SR_register(LPM0_bits + GIE); // Enter LPM0 w/ interrupt // while((ADC12IFGR0 & ADC12IFG0) == 0); // wait for conversion done while((DMA0CTL & DMAIFG) == 0); // wait for transfer done _NOP(); DMA0CTL &= ~DMAEN; // Disable DMA0 // stop any pending conversion ADC12CTL1 = 0; ADC12CTL0 = 0; _NOP(); // select A3 ADC12CTL0 |= ADC12ON; // Turn on. No sample or conversion starts ADC12CTL1 = ADC12PDIV__1 + ADC12SHS_0 // SW triggers conversion + ADC12SHP + ADC12CONSEQ_0; // single channel, single conversion ADC12IFGR0 = 0; // clear all pending flags if any ADC12IFGR1 = 0; ADC12IFGR2 = 0; ADC12IER0 = 0; // interrupt disabled ADC12IER1 = 0; ADC12IER2 = 0; ADC12MCTL0 = ADC12EOS // end of sequence + ADC12INCH_3; // A3 single-ended ADC12CTL0 |= ADC12ENC | ADC12SC; // enable and start conversion while((ADC12IFGR0 & ADC12IFG0) == 0); // wait for conversion done result_A3 = ADC12MEM0; _NOP(); P1OUT&= ~BIT5; ADC12IFGR0 = 0; // clear all pending flags if any ADC12IFGR1 = 0; ADC12IFGR2 = 0; // re-init DMA DMACTL0 |= DMA0TSEL__ADC12IFG; DMA0CTL = DMADT_4 + DMADSTINCR_3 + DMAEN; InitADC(); while((DMA0CTL & DMAIFG) == 0); // wait for transfer done _NOP(); while(1); }