trigger one time DMA after 5 ADC channel and every channel get 80 data.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

trigger one time DMA after 5 ADC channel and every channel get 80 data.

2,973 Views
renshaoshuai
Contributor II

i have an example about multi ADC channel sampling once, then trigger DMA interrupt. 

now i have a new requirement from customer. for example. now i have 5 ADC0 channel, and every ADC channel need sampling 80 datas, after get 5x80 = 400 datas, then trigger one time DMA interrupt. do you have any idea to realize this?

Labels (1)
Tags (3)
0 Kudos
11 Replies

2,248 Views
michael_90300
Contributor I

Hello,

@renshaoshuai You wrote have an example about multi ADC channel sampling once, then trigger DMA interrupt."

Could you please the example ?

thank you. 

BR

 

 

 

0 Kudos

2,787 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

I can imagine several ways, depending on how the DMA trigger is generated.

If you have DMA request after each ADC single channel conversion, then I think you can use channel linking after major loop. Thus one channel will be read ADC registers still into temp buffer and after major loop (5 results transferred) linked DMA channel is started and moves whole temp buffer into final result array. This linked channel should have minor loop offset enabled so you can return source address to temp buffer after each minor loop. 

If the DMA request comes after 5 channel sampled then single DMA channel can be used and configured similarly as linked channel above, but with reading ADC result registers directly. 

BR, Petr

0 Kudos

2,787 Views
renshaoshuai
Contributor II

use FTM 400us timer as 5 ADC channel trigger, use PDB as ADC pretrigger. after 5 channel ADC sampling as one time data, then repeat 80 times. and get 400 data. but how to set DMA buffer to receive these 400 buffer? dose there have any tips, eg. must start at ADC1->SC1[2] ?  do you have an example for these?

0 Kudos

2,789 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

I do not have example for this, just gave an idea how to do that.

BR, Petr

0 Kudos

2,789 Views
renshaoshuai
Contributor II

DMA->TCD[0].CSR &= 0xFFFFU ^ DMA_TCD_CSR_DONE_MASK; /* Clear Channel Done flag */
DMA->TCD[0].ATTR = DMA_TCD_ATTR_SMOD(0) | 
                                       DMA_TCD_ATTR_SSIZE(2) | /* Source data transfer size: 1: 16-bit, 2=32-bit */
                                       DMA_TCD_ATTR_DMOD(0) | /* Destination address modulo feature: 0=disabled, x= x power of 2 buffer[Disabled] */
                                 DMA_TCD_ATTR_DSIZE(2); /* Destination data transfer size: 1: 16-bit, 2=32-bit */
DMA->CR = DMA_CR_EMLM(1);
DMA->TCD[0].NBYTES.MLOFFYES = DMA_TCD_NBYTES_MLOFFYES_NBYTES(28)//; /*Minor Byte Transfer Count is 20 bytes*/
| DMA_TCD_NBYTES_MLOFFYES_SMLOE(1)
| DMA_TCD_NBYTES_MLOFFYES_DMLOE(0)
| DMA_TCD_NBYTES_MLOFFYES_MLOFF(-28); /* Minor Byte Transfer Count is 4bytes */
DMA->TCD[0].CITER.ELINKNO = DMA_TCD_CITER_ELINKNO_CITER(80) | /* Current Major Iteration Count is 40 Minor loops */
DMA_TCD_CITER_ELINKNO_ELINK(0); /* The channel-to-channel linking is disabled */
DMA->TCD[0].BITER.ELINKNO = DMA_TCD_BITER_ELINKNO_BITER(80) | /* Starting major iteration count is 40 Minor loops */
DMA_TCD_BITER_ELINKNO_ELINK(0); /* The minor channel-to-channel linking is disabled */

DMA->TCD[0].SADDR = DMA_TCD_SADDR_SADDR(&(ADC0->R[2])); /* Source Address */
DMA->TCD[0].SOFF = DMA_TCD_SOFF_SOFF(4); /* Source Offset is 4bytes */
DMA->TCD[0].SLAST = DMA_TCD_SLAST_SLAST(-28); /* Last Source Address Adjustment is 0 */

DMA->TCD[0].DADDR = DMA_TCD_DADDR_DADDR(&Get_Value_ADC0toDMA[0][0]); /* Destination Address of Buffer */
DMA->TCD[0].DOFF = DMA_TCD_DOFF_DOFF(4); /* Destination Address Signed Offset is 4 */
DMA->TCD[0].DLASTSGA = DMA_TCD_DLASTSGA_DLASTSGA(-2240); /* Destination last address adjustment is -160 */


DMA->TCD[0].CSR = DMA_TCD_CSR_BWC(0) | /* BWC=0: No eDMA engine stalls - full bandwidth */
DMA_TCD_CSR_MAJORELINK(0) | /* The channel-to-channel linking is disabled */
DMA_TCD_CSR_MAJORLINKCH(0) | /* channel 1 will be called from ch0 */
DMA_TCD_CSR_ESG(0) | /* The current channel fs TCD is normal format - No scatter/gather */
DMA_TCD_CSR_DREQ(0) | /* The channel's ERQ bit is affected */
DMA_TCD_CSR_INTHALF(0) | /* The half-point interrupt is disabled */
DMA_TCD_CSR_INTMAJOR(1) | /* The end-of-major loop interrupt is enabled */
DMA_TCD_CSR_START(0); /* The channel is not explicitly started */

hi there,

the above code is used for ADC0 7 channel sample. Is this right?

0 Kudos

2,789 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

I understand this DMA setting reads 7 ADC result registers (from ADC_R2) per single DMA request and store them into final array, repeat this per each DMA request (80 times) to fully fill destination array[28x80).

BR, Petr

0 Kudos

2,789 Views
renshaoshuai
Contributor II

Drawing4.jpg

i add a picture for the logic, this is not as expected.

0 Kudos

2,789 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

what is the DMA trigger source?

You need to generate trigger after all 7 channels are converted so your DMA code can work. Thus from PDB I guess.

If DMA trigger comes from ADC then it will not work, or work as you outlined.

BR, Petr

0 Kudos

2,789 Views
renshaoshuai
Contributor II

hi petr,

the following is the PDB0 setting: 

still trigger DMA after 1 channels are converted.


/* Chapter 43 Programmable delay block(PDB) */
void PDB0_Init(void)
{
uint8_t PREn;

PCC->PCCn[PCC_PDB0_INDEX] &= ~PCC_PCCn_CGC_MASK; /* CGC=0b,clock disabled */
PCC->PCCn[PCC_PDB0_INDEX] |= PCC_PCCn_CGC_MASK; /* Enable SYSCLK in PDB0 */
PCC->PCCn[PCC_PDB0_INDEX] |= PCC_PCCn_CGC_MASK; /* Enable SYSCLK in PDB0 */

PDB0->SC |= PDB_SC_TRGSEL(0) /* TRGSEL = 0000b,Trigger-In0(PDB0) is selected */
                  | PDB_SC_PRESCALER(2) /* PRESCALER=010b, SYSCLK divided by 4 */
                     | PDB_SC_MULT(2) /* MULT = 01b, Multiplication factor is 20,PDB Clock = SYSCLK/(4*MULT) = 112M / (4*20) = 1.4M */
                     | PDB_SC_PDBEN(1); /* PDBEN = 1b, PDB enabled */

PDB0->CH[0].C1 |= PDB_C1_BB(0x0) /* BB = 1b, pre-trigger back-to-back operation disabled */
                              | PDB_C1_TOS(0xFF) /* TOS = 1b, pre-trigger Output Select: 0=bypassed , 1=enabled */
                                 | PDB_C1_EN(0xFC); /* EN = 1b, corresponding pre-trigger enabled */
PDB0->CH[1].C1 |= PDB_C1_BB(0x0) /* BB = 1b, pre-trigger back-to-back operation disabled */
                              | PDB_C1_TOS(0xFF) /* TOS = 1b, pre-trigger Output Select: 0=bypassed , 1=enabled */
                              | PDB_C1_EN(0x01); /* EN = 1b, corresponding pre-trigger enabled */

PDB0->MOD = PDB0_MOD_VAL; /* Period of counter,28/1.4M = 20us */

for(PREn=0; PREn<=5; PREn++)
{
       PDB0->CH[0].DLY[PREn+2] = DLY0_PRIM * (PREn+1); /* Delay value of pre-trigger(0,1,2,3,4) for PDB0 Channel 0 */
}

PDB0->CH[1].DLY[0] = DLY0_PRIM * (7); /* Delay value of pre-trigger(0,1,2,3,4) for PDB0 Channel 0 */

PDB0->SC |= PDB_SC_LDOK_MASK; /* Load OK,THEN MOD BUFFER (and other buffers) IS LOADED INTO ITS REGISTER */
}

0 Kudos

2,789 Views
PetrS
NXP TechSupport
NXP TechSupport

Hi,

- disable DMA request from the ADC, ADC->SC2[DMAEN]=0

- set PDB0 IDLY to a value to be sure last ADC conversion is finished

- enable DMA from PDB0, PDB0->SC[DMAEN]=1

- within DMAMUX select PDB0 as a DMA source

BR, Petr

0 Kudos

2,788 Views
renshaoshuai
Contributor II

hi,

but the test result is not as expected.

the actual result is , for each ADC channel, will sample 7 times, then move to next ADC channel to sample 7 times.

0 Kudos