AnsweredAssumed Answered

K20 having issues linking ADC channels with eDMA

Question asked by Brent Williams on Oct 2, 2013
Latest reply on Oct 14, 2013 by Brent Williams

Hi, I am using a K20.

 

I want to set up the ADC so that I can use DMA to load TCD as well as for  writing the ADC results to SRAM (i.e. utilizing linking of channels).

 

Specifically I have a array of 3 DMA TCDs = used to load ADC0_SC1A, with  an array of 3 16 bit words for the ADC results.

 

I have tried following the "Using DMA to Emulate ADC Flexible Scan Mode on Kinetis K Series" app note without success.

 

What I am seeing is that I get two ADC interrupts (used only for debug) before I get the DMA interrupt signifying the end of my major loop.

I have 3 ADC result values in my SRAM buffer.  I would assume I would get 3 ADC interrupts.  One for each of the TCD mux values loaded into the ADC0_SC1A register.

 

  DMA0_TCD0_CSR - 0x00 indicating that it is NOT done

  DMA0_TCD1_CSR - 0x82 indicating that the major loop is done

 

  DMA0_TCD0_CITER_ELINKYES = 0x0001 indicating I have one more TCD to load.

 

Looking at ADC0_SC1A = 65 (the second element in my MUX array)

 

My code is below.  Any insight would be welcomed.

 

volatile unsigned short ui_adc_result[NUM_CHANNELS] = {0};

volatile unsigned char uc_adc_mux[NUM_CHANNELS] = {

  64,

  65,

  66

};

 

void ADCSetup_InitADC(void)

{

    // ADC 0:

    // enable clock gate control for ADC 0

    SIM_SCGC6 |= SIM_SCGC6_ADC0_MASK;          

 

    NVICISER1 |= (1<<25);   // Set Enable Register

    NVICICPR1 |= (1<<25);   // Clear Pending Register

    NVICIP57   = 0x10;

               

    // Normal Power

    // Divide by one

    // Short Sample Time

    // 12 bit conversion

    // Bus clock divided by 2--12.5 MHz

    ADC0_CFG1 = 0x0005;

 

    // Select ADC Mux A*

    // Asynchronous Clock Output disabled

    // Normal conversion

    // shortest sample time selected*

    ADC0_CFG2 = 0x0003;

               

    // Software Trigger selected

    // Compare fx disabled

    // DMA enabled

    // Voltage reference section is default*

    ADC0_SC2 = 0x0004;

               

    // Continuous Conversion disabled--i.e. do single conversion

    // Hardware average disabled

    ADC0_SC3 = 0;

 

    // select channel--0x1F disables

    // enable in timer interrupt

    ADC0_SC1A = 0x1F;                                                        

 

    // select channel--0x1F disables

    // enable in timer interrupt

    ADC0_SC1B = 0x1F;                                                        

 

    // Programmable Gain Amplifier is disabled

    ADC0_PGA = 0;

 

    // enable clock gate control for DMA Mux

    SIM_SCGC6 |= SIM_SCGC6_DMAMUX_MASK;

               

    // enable clock gate control for DMA Module

    SIM_SCGC7 |= SIM_SCGC7_DMA_MASK;           

 

    // Clear All Enable Error Interrupts

    DMA_CEEI |= 0x40;

    DMA_CERR |= 0x40;

               

    //****************************************************************************

    //**** DMA channel 0, use for Write ADC mux channel, from SRAM to ADC ********

    //****************************************************************************

    DMAMUX_CHCFG0 = 0x00;

               

    // DMA source DMA Mux (54)

    DMAMUX_CHCFG0 = DMAMUX_CHCFG_ENBL_MASK|DMAMUX_CHCFG_SOURCE(0x36);  

                               

    // SADDR is a 32 bit number

    // New mux setting

    DMA_TCD0_SADDR          = (Uint32) &uc_adc_mux[0];                           

 

    // SOFF is a signed 16 bit number

    // Source address increment, adding "1"

    DMA_TCD0_SOFF           = 0x01;                                              

 

    // SLAST is signed 32 bit number

    // Source address decrement after major loop complete

    DMA_TCD0_SLAST          = (Uint32)-3;                                        

 

    // DADDR is a 32 bit number

    // SC1A is a 32 bit number with only the meaning only in the LSbyte

    DMA_TCD0_DADDR             = (Uint32) &ADC0_SC1A;                                       // Destination address ADC0 mux selector

    DMA_TCD0_DOFF               = 0x00; // always the same destination--SC1A          // Destination address increment, adding "0"

    DMA_TCD0_DLASTSGA       = 0x00; // always the same destination--SC1A          // Destination address shift, go to back to [0]

 

    DMA_TCD0_NBYTES_MLNO    = 0x01; // No of bytes minor loop

    DMA_TCD0_BITER_ELINKNO  = 0x03; // Major loop step, 3 ADC channel are scanning

    DMA_TCD0_CITER_ELINKNO  = 0x03; // Major loop step, 3 ADC channel are scanning

               

    // 0 = 8 bit

    // 1 = 16 bit

    // 2 = 32 bit

    DMA_TCD0_ATTR           = DMA_ATTR_SSIZE(0)|DMA_ATTR_DSIZE(0);  // Source a destination size, 8bit

    DMA_TCD0_CSR            = 0x0000;                              

               

    //****************************************************************************

    //**** DMA channel 1, use for Read ADC result data, form ADC to SRAM *********

    //****************************************************************************

    NVICISER0 |= (1<<1); // Set Enable Register

    NVICICPR0 |= (1<<1); // Clear Pending Register

    NVICIP1 = 0x20;      // Interrupt Priority--priority 0 is the highest, 15 is the lowest (Most Significant Nibble is priority)

 

    DMAMUX_CHCFG1                  = 0x00;

    DMAMUX_CHCFG1                  = DMAMUX_CHCFG_ENBL_MASK|DMAMUX_CHCFG_SOURCE(0x28); // DMA source ADC0  (40)

    DMA_TCD1_SADDR                 = (Uint32) &ADC0_RA;                                                                        // Source address ADC0 result register

    DMA_TCD1_SOFF                    = 0x00;  // always the same source--ADC0_RA                                    // Source address increment, adding "0"

    DMA_TCD1_SLAST                  = 0x00;  // always the same source--ADC0_RA                                     // Source address decrements after major loop complete

    DMA_TCD1_DADDR                 = (Uint32) &ui_adc_result[0];                                                               // Destination address, ADC0 result buffer

    DMA_TCD1_DOFF                    = 0x02;                                                                                             // Destination address increment, adding "+2"

    DMA_TCD1_DLASTSGA           = (Uint32) -6;                                                                                     // Destination address decrements after major loop complete

    DMA_TCD1_NBYTES_MLNO    = 0x02;                                                                                             // No of bytes minor loop, 16 bit ADC result

    DMA_TCD1_BITER_ELINKNO   = (DMA_BITER_ELINKNO_ELINK_MASK|0x0000|0x03);                       // Channel 0 Link, Channel 0, Major loop step 3

    DMA_TCD1_CITER_ELINKNO   = (DMA_CITER_ELINKNO_ELINK_MASK|0x03);                                  // Channel 0 Link, Major loop step 3

    DMA_TCD1_ATTR                    = DMA_ATTR_SSIZE(0)|DMA_ATTR_DSIZE(0);                                    // Source a destination size, 16 bit

    DMA_TCD1_CSR                     = DMA_CSR_INTMAJOR_MASK;

    DMA_ERQ                              |= DMA_ERQ_ERQ1_MASK;                                                             // HW request enable

    DMA_CINT                               = DMA_CINT_CINT(1);                                                                     // Clear the interrupt flag for channel 1

}

 

__ramfunc void dma_ch1_isr( void )

{

  DMA_CINT = DMA_CINT_CINT(1);  // clear the interrupt flag for channel 1      

}

 

volatile int adcIntCount = 0;

__ramfunc void adc0_isr( void )

{

  adcIntCount++;

}

 

__ramfunc void Timers_isr( void )

{

  if( DMA_INT == 0 )         

      DMA_SSRT = 0x01; // start DMA channel 0, which triggers another round of ADC readings

}

_

Outcomes