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
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
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)
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
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);
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
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
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.