Unable to launch interruput or DMA requests from ADC2 and ADC3 channels

cancel
Showing results for 
Search instead for 
Did you mean: 

Unable to launch interruput or DMA requests from ADC2 and ADC3 channels

671 Views
dcantero
Contributor II

Hello!!

I´m implementing an aplication based on application note AN4590 "Using DMA to Emulate ADC Flexible Scan Mode on Kinetis K Series". I was able to integrate ADC drivers and DMA configuration developed in the example above in a MQX 4.0 application, and the adquisition mechanism works fine.

I have used the same adc driver API to configure ADC channels 2 and 3 in a software trigger mode (modifiying the ADTRG bit in ADC_SC2 register) and read the results in a periodic interrupt (this interrupt  is in fact launched by ADC channel 1 DMA0 minor loop completion event!!)  The idea was to activate corresponding ADC channel by software trigger and configure a DMA to store results to a buffer automátically using the same mechanism described in the app note AN4590 for DMA channel 0. I have followed the same steps described in the app note for ADC2, ADC3, and DMA configuration with some little modifications described below:

1.- Enable ADC2 and ADC 3 in SIM_SCGC6 and SIM_SCGC3 respectively

2.- Enable DMA_MUX1 in SIM_SCGC6

3.- Initialize both ADCs. I have copied the initialization routine for ADC1 changing the registers name to ADC2 and ADC3 correspondingly:

4.- Initailize DMA channel 18 (in channel 2 of the DMA_MUX1) and 19 (in channel 3 of the DMA_MUX1).  I´m not sure if this is correc!!!!!!t

     The DMA lauch an interrupt when finish its major loop. This is used to sinchronize all adquisition mechanism and to store data to a doble buffer before save data to a file.

     The entire mechanism is quite complex due to large number of adquisition channels and different adquisition frequencies:

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

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

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

            DMAMUX1_CHCFG2           = DMAMUX_CHCFG_ENBL_MASK|DMAMUX_CHCFG_SOURCE(0x2A);   //DMA source ADC2

            DMA_TCD18_SADDR          = (uint32) &ADC2_RA;                                  //Source address ADC2 result register

            DMA_TCD18_SOFF           = 0x00;                                               //Source address increment, adding "1"

            DMA_TCD18_SLAST          = 0x00;                                               //Source address decrement after major loop complete

            DMA_TCD18_DADDR          = (uint32) &ui_adc2_result[0];                        //Destination address

            DMA_TCD18_DOFF           = 0x02;                                               //Destination address increment, adding "0"

            DMA_TCD18_DLASTSGA       = (uint32) -2*ADC_2_BUFFER_SIZE;                      //Destination address shift, go to back to [0]

            DMA_TCD18_NBYTES_MLNO    = 0x02;                                               //No of bytes minor loop

            DMA_TCD18_BITER_ELINKNO  = (DMA_BITER_ELINKNO_ELINK_MASK|ADC_2_BUFFER_SIZE);   //Major loop step,

            DMA_TCD18_CITER_ELINKNO  = (DMA_CITER_ELINKNO_ELINK_MASK|ADC_2_BUFFER_SIZE);   //Major loop step,

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

            DMA_TCD19_CSR            = /*(DMA_CSR_MAJORLINKCH(0)|DMA_CSR_MAJORELINK_MASK)|*/   //Major loop finished start request for Channel 0

                                                      DMA_CSR_INTMAJOR_MASK | DMA_CSR_INTHALF_MASK;       //Irq. enable, full transfer, half complet transfer

            DMA_ERQ                 |= DMA_ERQ_ERQ18_MASK; 

                                         

5.- In the periodic interrupt,  trigger correspnding ADC module and channel (something like this):

    switch (ch_select_cnt) {

        case 0:

            ADC2_SC1A = uc_adc2_3_mux[0];

        break;

Unafortunately result buffers remain empty, so DMAs are not been launched. I have configure a ADC conversion complete interrupt in all ADCs (1, 2 and 3)  but only the ADC1 response routine caugth the interruption.

Wow!!! is a very large explanation!!!!!!  The question is, Do you see something wrong in the steps described above? some idea to solve this issue? Do you had a similar problem once?

Thanks in advance!!!!

David

8 Replies

105 Views
mrandreas
Contributor III

I have utilized the same project and changed the configuration to utilize adc2 and adc3. I don't get any DMA IRQ on ADC1 - 3. ADC0 do however work for DMAMUX0 and DMAMUX1.

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

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

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

  DMAMUX1->CHCFG[0]           = DMAMUX_CHCFG_ENBL_MASK|DMAMUX_CHCFG_SOURCE(54);   //DMA source DMA Mux

  DMA0->TCD[17].SADDR          = (uint32) &uc_adc_mux[0];                            //New mux setiing

  DMA0->TCD[17].SOFF           = 0x01;                                               //Source address increment, adding "1"

  DMA0->TCD[17].SLAST          = (uint32) -3;                                        //Source address decrement after major loop complete

  DMA0->TCD[17].DADDR          = (uint32) &ADC2->SC1[0];                              //Destination address ADC2 mux selector

  DMA0->TCD[17].DOFF           = 0x00;                                               //Destination address increment, adding "0"

  DMA0->TCD[17].DLAST_SGA       = 0x00;                                               //Destination address shift, go to back to [0]

  DMA0->TCD[17].NBYTES_MLNO    = 0x01;                                               //No of bytes minor loop

  DMA0->TCD[17].BITER_ELINKNO  = 0x03;                                               //Major loop step, 3 ADC channel are scaning

  DMA0->TCD[17].CITER_ELINKNO  = 0x03;                                               //Major loop step, 3 ADC channel are scaning

  DMA0->TCD[17].ATTR           = DMA_ATTR_SSIZE(0)|DMA_ATTR_DSIZE(0);                //Source a destination size, 8bit

  DMA0->TCD[17].CSR            = 0x0000;                                             //

 

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

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

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

  NVIC_EnableIRQ(DMA2_DMA18_IRQn);                                                      //17

  DMAMUX1->CHCFG[2]           = DMAMUX_CHCFG_ENBL_MASK|DMAMUX_CHCFG_SOURCE(42);     //DMA source ADC2

  DMA0->TCD[18].SADDR          = (uint32) &ADC2->R[0];                                  //Source address ADC2 result register

  DMA0->TCD[18].SOFF           = 0x00;                                               //Source address increment, adding "0"

  DMA0->TCD[18].SLAST          = 0x00;                                               //Source address decrement after major loop complete

  DMA0->TCD[18].DADDR          = (uint32) &ui_adc_result[0];                         //Destination address, ADC2 result buffer

  DMA0->TCD[18].DOFF           = 0x02;                                               //Destination address increment, adding "+2"

  DMA0->TCD[18].DLAST_SGA       = (uint32) -24;                                       //Destination address decrement after major loop complete

  DMA0->TCD[18].NBYTES_MLNO    = 0x02;                                               //No of bytes minor loop, 16bit ADC result

  DMA0->TCD[18].BITER_ELINKNO  = (DMA_BITER_ELINKNO_ELINK_MASK|0x0000|0x0C);         //Channel 0 Link, Channel 0, Major loop step 3 x 4 = 12

  DMA0->TCD[18].CITER_ELINKNO  = (DMA_CITER_ELINKNO_ELINK_MASK|0x0C);                //Channel 0 Link, Major loop step 3 x 4 = 12

  DMA0->TCD[18].ATTR           = DMA_ATTR_SSIZE(1)|DMA_ATTR_DSIZE(1);                //Source a destination size, 16bit

  DMA0->TCD[18].CSR            = (DMA_CSR_MAJORLINKCH(0)|DMA_CSR_MAJORELINK_MASK)|   //Major loop finished start request for Channel 0

                            DMA_CSR_INTMAJOR_MASK; //|DMA_CSR_INTHALF_MASK;     //Irq. enable, full transfer, half complet transfer

  DMA0->ERQ                |= DMA_ERQ_ERQ18_MASK;                                  //HW request enable

Anny Qlues?

Thanks

A

0 Kudos

105 Views
arnoldbischof
Contributor III

Hi mrandreas

I think the problem in your code is the setup of the ADC control DMA (channel 0). If you want to use DMA channel 0, you have to use DMA0->TCD[16] instead of [17].

Following, I send you my code which works for the 4 ADC. Hope it helps.

Arnold

/// <summary>

/// setup_AdcDma

/// - This method performs the setup for the DMA used for fast AD conversion

///   of all channels

/// - Two DMA channels are needed for this functionality. One channel for the

///      transfer of the converted AD data from ADC to RAM and one channel for

///   the next AD input channel selection control.

/// - we set the priority of the ADCREAD DMA channel higher than the prio of

///   ADCONTROL to make sure converted AD value is transfered to RAM before next

///   conversion is initiated

/// - sequene description (SW triggered):

///     0. Setup of AD channel select RAM table, setup DMA

///     1. Start sequence within start of DMA channel ADCONTROL within DMA_SSRT.

///         This start may be timed within Timer or SW state machine

///     2. The start of DMA channel ADCONTROL writes the first AD channel input

///         selection from RAM to SC1A. This starts the AD conversion.

///     3. The ADC0 CoCo triggers the ADCREAD DMA channel which transfers

///         the data from ADC RA to RAM table.

///     4. The DMA channel ADCONTROL is linked to the DMA channel ADCREAD and

///         writes the next AD channel input selection from RAM to SC1A. This

///         starts the next AD conversion immediately.

///     5. The ADC0 CoCo triggers again and the sequence from Pt.3 is repeated

///        until number of programmed transfers is reached

///  </summary>

void CAdcDiffChannels::setup_AdcDma() {

    // Turn on the DMA Mux clock

    if (cUseDmaMux1) {

        // Turn on the DMA MUX1 clock

        // Attention: DMA MUX1 is routed to DMA channels 16-31 as described in

        // Reference manual MK10FX: chapter '3.3.9.1 DMA MUX request sources'

        // We have to use a DMA channel offset of 16 during setup of the DMAs 

        SET_BITMASK(SIM_SCGC6, SIM_SCGC6_DMAMUX1_MASK);

    } else {

        // Turn on the DMA MUX0 clock

        SET_BITMASK(SIM_SCGC6, SIM_SCGC6_DMAMUX0_MASK);

    }

    // -------------------------------------------------------------------------------------

    // setup ADC0 DMA channel selection table

    // -------------------------------------------------------------------------------------

    uint8_t adcUnit = 0;

    // set channel to DAD0 voltage and use differential mode

    adcChnSelectDma[adcUnit][ADC_DAD0_INDEX]            = DIFF_DIFFERENTIAL | ADC_DAD0_CHANNEL;

    // use single-ended mode for remaining channels

    adcChnSelectDma[adcUnit][ADC_TEMP_SENS_INT_INDEX]   = DIFF_SINGLE | ADC_TEMP_SENS_INT_CHANNEL;

    adcChnSelectDma[adcUnit][ADC_BANDGAP_VOLT_INDEX]    = DIFF_SINGLE | ADC_BANDGAP_VOLT_CHANNEL;

    // -------------------------------------------------------------------------------------

    // setup ADC0 DMA for this unit

    // DMA channel 'ADCONTROL' used to transfer next ADC0 control from RAM to ADC0_SC1A.

    // DMA channel 'ADCREAD' used to transfer ADC0 result data from ADC0_RA to RAM.

    // -------------------------------------------------------------------------------------

    configAdcDmaOfUnit(adcUnit, NUMBER_OF_ADC_A_CHANNELS,

                       ADC0_DMA_CHANNEL_ADCONTROL, ADC0_DMA_CHANNEL_ADCONTROL_MUX_SRC,

                       ADC0_DMA_CHANNEL_ADCREAD, ADC0_DMA_CHANNEL_ADCREAD_MUX_SRC);

    // -------------------------------------------------------------------------------------

    // setup ADC1 DMA channel selection table

    // -------------------------------------------------------------------------------------

    adcUnit = 1;

    // set channel to DAD0 voltage and use differential mode

    adcChnSelectDma[adcUnit][ADC_DAD0_INDEX]            = ADC_SC1_DIFF_MASK | ADC_DAD0_CHANNEL;

    // -------------------------------------------------------------------------------------

    // setup ADC1 DMA for this unit

    // DMA channel 'ADCONTROL' used to transfer next ADC1 control from RAM to ADC1_SC1A.

    // DMA channel 'ADCREAD' used to transfer ADC1 result data from ADC1_RA to RAM.

    // -------------------------------------------------------------------------------------

    configAdcDmaOfUnit(adcUnit, 1,

                       ADC1_DMA_CHANNEL_ADCONTROL, ADC1_DMA_CHANNEL_ADCONTROL_MUX_SRC,

                       ADC1_DMA_CHANNEL_ADCREAD, ADC1_DMA_CHANNEL_ADCREAD_MUX_SRC);

    // -------------------------------------------------------------------------------------

    // setup ADC2 DMA channel selection table

    // -------------------------------------------------------------------------------------

    adcUnit = 2;

    // set channel to DAD0 voltage and use differential mode

    adcChnSelectDma[adcUnit][ADC_DAD0_INDEX]            = ADC_SC1_DIFF_MASK | ADC_DAD0_CHANNEL;

    // -------------------------------------------------------------------------------------

    // setup ADC2 DMA for this unit

    // DMA channel 'ADCONTROL' used to transfer next ADC2 control from RAM to ADC2_SC1A.

    // DMA channel 'ADCREAD' used to transfer ADC2 result data from ADC2_RA to RAM.

    // -------------------------------------------------------------------------------------

    configAdcDmaOfUnit(adcUnit, 1,

                       ADC2_DMA_CHANNEL_ADCONTROL, ADC2_DMA_CHANNEL_ADCONTROL_MUX_SRC,

                       ADC2_DMA_CHANNEL_ADCREAD, ADC2_DMA_CHANNEL_ADCREAD_MUX_SRC);

    // -------------------------------------------------------------------------------------

    // setup ADC3 DMA channel selection table

    // -------------------------------------------------------------------------------------

    adcUnit = 3;

    // set channel to DAD0 voltage and use differential mode

    adcChnSelectDma[adcUnit][ADC_DAD0_INDEX]            = ADC_SC1_DIFF_MASK | ADC_DAD0_CHANNEL;

    // -------------------------------------------------------------------------------------

    // setup ADC3 DMA for this unit

    // DMA channel 'ADCONTROL' used to transfer next ADC3 control from RAM to ADC3_SC1A.

    // DMA channel 'ADCREAD' used to transfer ADC3 result data from ADC3_RA to RAM.

    // -------------------------------------------------------------------------------------

    configAdcDmaOfUnit(adcUnit, 1,

                       ADC3_DMA_CHANNEL_ADCONTROL, ADC3_DMA_CHANNEL_ADCONTROL_MUX_SRC,

                       ADC3_DMA_CHANNEL_ADCREAD, ADC3_DMA_CHANNEL_ADCREAD_MUX_SRC);

}

/// <summary>

/// configAdcDmaOfUnit

/// - This method configures the ADC DMA settings for a given ADC unit.

///   two DMA channels are used per unit (channel ADCONTROL and channel ADREAD).

///   ADCONTROL is used to program the next AD conversion

///   ADREAD is used to copy the convertet result from the ADC to RAM

/// - parameters:    - adcUnit                the adc unit to use

///                 - nbrOfChn                the number of channles to transfer

///                 - dmaChannelAdControl    the DMA channel for the ADCONTROL DMA

///                 - dmaReqSourceAdControl    the DMA request source for the ADCONTROL DMA

///                 - dmaChannelAdRead        the DMA channel for the ADREAD DMA

///                 - dmaReqSourceAdRead    the DMA request source for the ADREAD DMA

///  </summary>

void CAdcDiffChannels::configAdcDmaOfUnit(uint8_t adcUnit,

                                          uint8_t nbrOfChn,

                                          uint8_t dmaChannelAdControl,

                                          uint8_t dmaReqSourceAdControl,

                                          uint8_t dmaChannelAdRead,

                                          uint8_t dmaReqSourceAdRead) {

    // get values which depends on used unit

    const uint8_t cHalfwordBytes = sizeof(uint16_t)/sizeof(uint8_t); 

    uint32_t adrOfAdcSC1A;

    uint32_t adrOfAdcRA;

    switch (adcUnit) {

    case 0:

        adrOfAdcSC1A = (uint32_t)&ADC0_SC1A;

        adrOfAdcRA = (uint32_t)&ADC0_RA;

        break;

    case 1:

        adrOfAdcSC1A = (uint32_t)&ADC1_SC1A;

        adrOfAdcRA = (uint32_t)&ADC1_RA;

        break;

    case 2:

        adrOfAdcSC1A = (uint32_t)&ADC2_SC1A;

        adrOfAdcRA = (uint32_t)&ADC2_RA;

        break;

    case 3:

        adrOfAdcSC1A = (uint32_t)&ADC3_SC1A;

        adrOfAdcRA = (uint32_t)&ADC3_RA;

        break;

    }

    // -------------------------------------------------------------------------------------

    // DMA channel 'ADCONTROL' used to transfer next ADCx control from RAM to ADCx_SC1A.

    // -------------------------------------------------------------------------------------

    // Configure this DMA channel to an always enabled request source and enable this channel

    if (cUseDmaMux1) {

        DMAMUX1_CHCFG(dmaChannelAdControl)    = (DMAMUX_CHCFG_ENBL_MASK |    // Enable routing of DMA request

                                               DMAMUX_CHCFG_SOURCE(dmaReqSourceAdControl));    // Channel Activation Source: DMA MUX always enabled

        // Attention: DMA MUX1 is routed to DMA channels 16-31 as described in

        // Reference manual MK10FX: chapter '3.3.9.1 DMA MUX request sources'

        // We have to use a DMA channel offset of 16 during setup of the DMAs 

        dmaChannelAdControl += DMA_CHANNEL_OFFSET_USING_DMAMUX1;

    }

    else {   

        DMAMUX0_CHCFG(dmaChannelAdControl)    = (DMAMUX_CHCFG_ENBL_MASK |    // Enable routing of DMA request

                                               DMAMUX_CHCFG_SOURCE(dmaReqSourceAdControl));    // Channel Activation Source: DMA MUX always enabled

    }

    // Configure the TCD for the ADC_DMA_CHANNEL 'ADCONTROL'

    DMA_SADDR(dmaChannelAdControl)          = (uint32_t)&adcChnSelectDma[adcUnit][0]; // set source address to first entry of adcChnSelectDma

    DMA_SOFF(dmaChannelAdControl)           = sizeof(uint8_t);    // source address increment, adc channel select is 1 byte       

    DMA_SLAST(dmaChannelAdControl)          = -nbrOfChn;        // source address decrement after major loop of adcChnSelectDma is nbrOfChn*1Byte

    DMA_DADDR(dmaChannelAdControl)          = adrOfAdcSC1A;        // dest address is ADCx SC1A control register

    DMA_DOFF(dmaChannelAdControl)           = 0;                // dest address increment, no increment allowed

    DMA_DLAST_SGA(dmaChannelAdControl)      = 0;                // dest address shift after major loop, no shift needed

    DMA_NBYTES_MLNO(dmaChannelAdControl)    = sizeof(uint8_t);    // minor byte transfer count, ADC input select cmd -> 1byte

    // channel linking and major loop setting, no linking after minor loop, major loop transfers = Nbr of channel transfers

    DMA_BITER_ELINKNO(dmaChannelAdControl)  = DMA_BITER_ELINKNO_BITER(nbrOfChn);

    DMA_CITER_ELINKNO(dmaChannelAdControl)  = DMA_CITER_ELINKNO_CITER(nbrOfChn);

    // source and dest data transfer size is 8bit

    DMA_ATTR(dmaChannelAdControl)           = (DMA_ATTR_SSIZE(0) | DMA_ATTR_DSIZE(0));        

    // no additional controls for this DMA

    DMA_CSR(dmaChannelAdControl)            = 0;                       

    // -------------------------------------------------------------------------------------

    // DMA channel 'ADCREAD' used to transfer ADCx result data from ADCx_RA to RAM.

    // -------------------------------------------------------------------------------------

    // Configure this DMA channel to use ADCx CoCo as transfer request source and enable this channel

    if (cUseDmaMux1) {

        DMAMUX1_CHCFG(dmaChannelAdRead)        = (DMAMUX_CHCFG_ENBL_MASK |    // Enable routing of DMA request

                                               DMAMUX_CHCFG_SOURCE(dmaReqSourceAdRead));// Channel Activation Source: ADCx CoCo

        // Attention: DMA MUX1 is routed to DMA channels 16-31 as described in

        // Reference manual MK10FX: chapter '3.3.9.1 DMA MUX request sources'

        // We have to use a DMA channel offset of 16 during setup of the DMAs 

        dmaChannelAdRead += DMA_CHANNEL_OFFSET_USING_DMAMUX1;

    } else {

        DMAMUX0_CHCFG(dmaChannelAdRead)        = (DMAMUX_CHCFG_ENBL_MASK |    // Enable routing of DMA request

                                               DMAMUX_CHCFG_SOURCE(dmaReqSourceAdRead));// Channel Activation Source: ADCx CoCo

    }

    // Configure the TCD for the ADC_DMA_CHANNEL 'ADCREAD'

    DMA_SADDR(dmaChannelAdRead)             = adrOfAdcRA;        // source address is ADCx RA result register

    DMA_SOFF(dmaChannelAdRead)              = 0;                // source address increment, no increment allowed

    DMA_SLAST(dmaChannelAdRead)             = 0;                // source address shift after major loop, no shift needed

    DMA_DADDR(dmaChannelAdRead)             = (uint32_t)&adcConvValuesDma[adcUnit][0];// set dest address to first entry of adcConvValuesDma,

    DMA_DOFF(dmaChannelAdRead)              = cHalfwordBytes;    // dest address increment, adc conv values is 2 byte

    DMA_DLAST_SGA(dmaChannelAdRead)         = -nbrOfChn*cHalfwordBytes;    // dest address shift after major loop of adcChnResdDma is nbrOfChn*2Byte

    DMA_NBYTES_MLNO(dmaChannelAdRead)       = cHalfwordBytes;    // minor byte transfer count, ADC result 16bit -> 2byte

    // channel linking and major loop setting,

    // enable channel2channel linking on minor loop complete, link to ADCONTROL channel

    // and set major loop transfers = Nbr of channel transfers

    DMA_BITER_ELINKYES(dmaChannelAdRead)  =

    DMA_BITER_ELINKYES_ELINK_MASK | DMA_BITER_ELINKYES_LINKCH(dmaChannelAdControl) | DMA_BITER_ELINKYES_BITER(nbrOfChn);

    DMA_CITER_ELINKYES(dmaChannelAdRead)  =

    DMA_CITER_ELINKYES_ELINK_MASK | DMA_CITER_ELINKYES_LINKCH(dmaChannelAdControl) | DMA_CITER_ELINKYES_CITER(nbrOfChn);

    // source and dest data transfer size is 16bit

    DMA_ATTR(dmaChannelAdRead)            = (DMA_ATTR_SSIZE(1) | DMA_ATTR_DSIZE(1));         

    // enable HW request (ADC coco) for the ADC_DMA_CHANNEL 'ADCREAD'

    DMA_SERQ = DMA_SERQ_SERQ(dmaChannelAdRead);

    // setup interrupt which fires every time the ADC_DMA_CHANNEL 'ADCREAD' transfer is completed.

    // no linking after major loop needed

    DMA_CSR(dmaChannelAdRead) = DMA_CSR_INTMAJOR_MASK;

}

where

the constant cUseDmaMux1 ist set to 'true' if all ADCs are used. If ADC 0&1 is used only the constant may be set to false

// ADC DMA channels and DMA sources

#define ADC0_DMA_CHANNEL_ADCONTROL            0    // DMA channel used for AD control

#define ADC0_DMA_CHANNEL_ADCONTROL_MUX_SRC     54    // DMA MUX source used for AD0 control

#define ADC0_DMA_CHANNEL_ADCREAD            1    // DMA channel used for AD read

#define ADC0_DMA_CHANNEL_ADCREAD_MUX_SRC     40    // DMA MUX source used for AD0 read

#define ADC0_DMA_IRQChannel                    CAT3(DMA,ADC0_DMA_CHANNEL_ADCREAD,_IRQn)

#define ADC0_DMA_IRQHandler                    CAT3(DMA,ADC0_DMA_CHANNEL_ADCREAD,_IRQHandler)

#define ADC1_DMA_CHANNEL_ADCONTROL            4    // DMA channel used for AD1 control

#define ADC1_DMA_CHANNEL_ADCONTROL_MUX_SRC     55    // DMA MUX source used for AD1 control

#define ADC1_DMA_CHANNEL_ADCREAD            5    // DMA channel used for AD1 read

#define ADC1_DMA_CHANNEL_ADCREAD_MUX_SRC     41    // DMA MUX source used for AD1 read

#define ADC1_DMA_IRQChannel                    CAT3(DMA,ADC1_DMA_CHANNEL_ADCREAD,_IRQn)

#define ADC1_DMA_IRQHandler                    CAT3(DMA,ADC1_DMA_CHANNEL_ADCREAD,_IRQHandler)

#define ADC2_DMA_CHANNEL_ADCONTROL            6    // DMA channel used for AD2 control

#define ADC2_DMA_CHANNEL_ADCONTROL_MUX_SRC     56    // DMA MUX source used for AD2 control

#define ADC2_DMA_CHANNEL_ADCREAD            7    // DMA channel used for AD2 read

#define ADC2_DMA_CHANNEL_ADCREAD_MUX_SRC     42    // DMA MUX source used for AD2 read

#define ADC2_DMA_IRQChannel                    CAT3(DMA,ADC2_DMA_CHANNEL_ADCREAD,_IRQn)

#define ADC2_DMA_IRQHandler                    CAT3(DMA,ADC2_DMA_CHANNEL_ADCREAD,_IRQHandler)

#define ADC3_DMA_CHANNEL_ADCONTROL            8    // DMA channel used for AD3control

#define ADC3_DMA_CHANNEL_ADCONTROL_MUX_SRC     57    // DMA MUX source used for AD3 control

#define ADC3_DMA_CHANNEL_ADCREAD            9    // DMA channel used for AD3 read

#define ADC3_DMA_CHANNEL_ADCREAD_MUX_SRC     43    // DMA MUX source used for AD3 read

#define ADC3_DMA_IRQChannel                    CAT3(DMA,ADC3_DMA_CHANNEL_ADCREAD,_IRQn)

#define ADC3_DMA_IRQHandler                    CAT3(DMA,ADC3_DMA_CHANNEL_ADCREAD,_IRQHandler)

105 Views
gpontis
Contributor IV

Thank you for posting this excellent code for setting up multiple ADC and more than one DMA mux. It was just what I needed to find mistakes in my code and get ADC2 and ADC3 running under DMA on a K70.

George

0 Kudos

105 Views
mrandreas
Contributor III

Thanks Arnold!

Yes the channel was wrong but there are still a bugger in here. I will compare your code. Here is the AN4590 for keil. I'm thought all I need to replace is the mux source and ADC1 to ADCx to test another adc.

best regards

A

0 Kudos

105 Views
mrandreas
Contributor III

My problem was the configuration of pdb.

modified the pdb trigger interface.

PDBTRG_Init (PDB_ADC1, PDB_ADC_CHA, PDB_PRETRG_ON_DEALYED_CONFIG, 0x0010);

0 Kudos

105 Views
arnoldbischof
Contributor III

Hello David,

I have realized a similar application on a MK10FX512, using the 4 ADC and DMA to get the converted AD results. My application runs now as expected - after some setup problems.

Your setup, using the DMA channel 18 for the DMA configuration and the DMAMUX1_CHCFG2, is correct. But you should write DMA_TCD18_CSR instead of DMA_TCD19_CSR at the end of the setup code.

Hope it helps

0 Kudos

105 Views
arnoldbischof
Contributor III

Hi David

In the setup of the CITER and BITER you should use

DMA_CITER_ELINKNO(18) = DMA_CITER_ELINKNO_CITER(ADC_2_BUFFER_SIZE);

DMA_BITER_ELINKNO(18) = DMA_BITER_ELINKNO_BITER(ADC_2_BUFFER_SIZE);

and check the setting for ATTR

Hope it helps

105 Views
dcantero
Contributor II

Hi Arnold!!!

The source and destination sizes were wrong!!!! I check de ATTR a change to:

DMA_TCD18_ATTR           = DMA_ATTR_SSIZE(1)|DMA_ATTR_DSIZE(1); 

I use the macros you suggest too, but unfortunately the problem remains!!!! 

In my opinion there is a configuration trick that I´m not able to find!!!  In fact, I cant lauch nor DMA nor Interrupts, although the configuration for both is quite simple (Set the corresponding bit in the ADC configuration registers and instal an interrupt routine).

I did some test to guarantee that ADCs are actually working modifying the periodic interrupt code like this:

    switch (ch_select_cnt) {

     

        case 0:

            ADC2_SC1A = uc_adc2_3_mux[0];

            while ((ADC2_SC1A & ADC_SC1_COCO_MASK ) == 0 ) {}

            ui_adc2_result[ch_select_cnt] = ADC2_RA; 

        break;

The ADCs are working correctly and I get the result in the memory buffer, so the ADC sets de COCO bit when finish the converson, but i dont know why this event dont lauch nor DMA nor Interrupt.

Thanks for your reply!!!!!

David.

0 Kudos