iMXRT1021 ADC multi channel DMA transfer

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

iMXRT1021 ADC multi channel DMA transfer

3,509 Views
manuabraham
Contributor III

Hi,

 

I would like to do a multichannel conversion at least 8channels, or more channels (I see the evkmimxrt1020_adc_etc_hardware_trigger_conv example).

From the Reference Manual, I see that there exists:

ETC DMA control Register (DMA_CTRL) 61.5.1.5

The only comment that's seen in the Reference Manual is this:

"DMA request or interrupts will assert according to the software configurations."

Is there any further detail available, or sample code describing the ADC multi channel DMA ?

 

Thanks,

Manu

 

0 Kudos
28 Replies

2,931 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Manu,

Thank you for your interest in NXP Semiconductor products and for the opportunity to serve you.
1) Is there any further detail available, or sample code describing the ADC multi-channel DMA?
-- Until now, there's no such kind of ADC-ETC's DMA application demo in the SDK library, so I was wondering if you can introduce what application you want to implement, then I can share some advice and guides.

Hope this is clear.
Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

2,927 Views
manuabraham
Contributor III

Hi Jeremy,

 

Thanks for the reply.

I am trying to read 8 (or more) analog values, get it out through the serial port and out to a SPI LCD.

It needs to be the fastest possible (I know, I am limited to 1MSPS). I need to save CPU resources as much as possible for the LCD drawing application. Hence the ADC transfers needs to have minimal CPU involvement.

For this reason, I decided to go with ADC-ETC with multi channel DMA .

 

Thanks,

Manu

 

0 Kudos

2,923 Views
manuabraham
Contributor III

I missed to state additionally that; The multi channel DMA needs to be time triggered, by a timer. In this situation, the PIT would be the right choice ?

But I am fairly confused with the documentation, how it should all work together and hence my question.

 

Thanks,

Manu

 

0 Kudos

2,913 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Manu,

Thanks for your reply.
In the ADC-ETC, trig0~trig7 share one DMA source, it means that DMA request can be granted by any ADC-ETC trigger, and all DMA channels will response to the DMA request.
So it's impossible to set up different DMA channels to respond to particular ADC-ETC triggers.
Back to your question, it's okay to use the PIT to trigger the DMA to transfer the ADC result data when ADC conversion completes.
However, in my opinion, it's not a good idea, and I'd suggest you enable the done interrupt and in the interrupt function, start the DMA request via the software way to transfer the ADC result data.

Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

2,910 Views
manuabraham
Contributor III

Hi Jeremy,

 

I dont need different DMA channels. On the contrary, what I need is a single one. The whole point why I am doing this is to coalesce data from different ADC channels using DMA to a single buffer, which can be sent to a port directly.

I guess maybe what I said was not clear at some places. Let me rephrase it differently.

 

1. I have a Timer; Timer generates a trigger for ADC to start conversion.

 

2. ADC Starts Conversion of Channels in list

 a) Start with conversion of Sequence Rank #0 (Rank0 is associated with ADC input 14)

 b) Goes on to convert Sequence Rank #1 (Rank 1 is associated with ADC input 2)

..

n-1) Goes on to convert Sequence Rank #n-1 (Rank n-1 is associated with ADC input 10)

n) Goes on to convert Sequence Rank #n (Rank n is associated with ADC input 15)

 

3) Once ADC has finished converting 'n' Sequences, it stores the data somewhere with/or Without DMA support.

4) The DMA was instructed to transfer 'x' blocks of 'n' sequences.

5) When the DMA has successfully transferred 'x'/2 blocks, it sends a HALF TRANSFER IRQ

6) When the DMA has successfully transferred 'x' blocks, it sens a TRANSFER COMPLETE IRQ

7) The transactions are expected to complete before the Timer fires again, asking the ADC to do the SEQUENCE set conversion.

 

From the Reference Manual, Table 5-5. TCD Control and Status fields

INT_HALF Control bit to enable interrupt when major loop is half complete
INT_MAJ Control bit to enable interrupt when major loop completes

 

I have tried the following with a ST H7 MCU and it works as expected.

https://forums.freertos.org/t/interrupt-handling-and-a-task/10414/29

But I would like to apply the same application to the iMXRT1020.

 

I get the feeling that, the outlined above is possible. But the RM, is very vague on how to do it.

Maybe you can help me.

 

Thanks,

Manu

 

0 Kudos

2,891 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Manu,
Thanks for your reply and clarification.
Firstly, it's able to implement the above implementation on the i.MX RT MCU.
Secondly, to make it, you can add the DMA function to the evkmimxrt1020_adc_etc_hardware_trigger_conv example, and below the application describes how to combine the ADC and DMA, please refer to it for details.
Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

 

0 Kudos

2,886 Views
manuabraham
Contributor III

Hi Jeremy,

 

I will try out what you suggested. You mentioned an ADC + DMA example, but could not see any ?

You missed something ?

 

Thanks,

Manu

 

0 Kudos

2,878 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Ed,

Sorry, I forgot to attach the link.

https://www.nxp.com/docs/en/application-note/AN4590.pdf

Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

2,873 Views
manuabraham
Contributor III

Hi Jeremy,

 

Thanks for the document. I was looking for something similar, wondering where the documentation was.

 

I have one more question in there.

* The DMA module needs a SRC and DEST addresses.

* ADC_ETC trigger results in a conversion of a Chain of ADC inputs.

* Normal ADC trigger conversion result go into a single register, as per documentation.

* A Trigger also causes the conversion to go into a single register.

 

I assume that an ADC trigger results in a ADC_COCO "Conversion Complete", which is used to trigger the DMA.

 

My confusion is this:

When the trigger causes a "chain of conversion" say ADC1_IN1 .. 8, where would the conversion results go ?

 

My second question is this:

If ADC_COCO is used as the trigger, does it need to be an interrupt?

(ie, can I avoid the interrupt; Use it as an internal trigger between the ADC and DMA ? ie, I would like to avoid the CPU with an unnecessary SAVE/RESTORE/DISABLE irq events, at the RTOS level)

 

Thanks,

Manu

 

0 Kudos

2,862 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Manu,

Thanks for your reply.
1) When the trigger causes a "chain of conversion" says ADC1_IN1 .. 8, where would the conversion results go?
-- The ADC conversion results are stored in ETC_TRIG Result Data registers.
2) If ADC_COCO is used as the trigger, does it need to be an interrupt?
-- No, for your application, after completes a chain of ADC conversion, the ADC_ETC module will generate a TRIG done DMA request.

Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

2,851 Views
manuabraham
Contributor III

Hi Jeremy,

 

That part is now clear. Thanks!

 

Confusion prevails, over the following:

 

// From adc_etc_hardware_trigger_conv.c


#define DEMO_ADC_USER_CHANNEL 16U

#define DEMO_ADC_ETC_CHANNEL0 10U
#define DEMO_ADC_ETC_CHANNEL1 11U


// in ADC_Configuration()

adcChannelConfigStruct.channelNumber = DEMO_ADC_USER_CHANNEL; /* External channel selection from ADC_ETC. */
adcChannelConfigStruct.enableInterruptOnConversionCompleted = false;
ADC_SetChannelConfig(DEMO_ADC_BASE, DEMO_ADC_CHANNEL_GROUP0, &adcChannelConfigStruct);
ADC_SetChannelConfig(DEMO_ADC_BASE, DEMO_ADC_CHANNEL_GROUP1, &adcChannelConfigStruct);


// and main()


adcEtcTriggerChainConfig.ADCChannelSelect =
DEMO_ADC_ETC_CHANNEL0; /* ADC_HC0 will be triggered to sample Corresponding channel. */
adcEtcTriggerChainConfig.InterruptEnable = kADC_ETC_Done0InterruptEnable; /* Enable the Done0 interrupt. */
ADC_ETC_SetTriggerChainConfig(DEMO_ADC_ETC_BASE, 0U, 0U,
&adcEtcTriggerChainConfig); /* Configure the trigger0 chain0. */

 

Initially you configure DEMO_ADC_USER_CHANNEL (Does this definition imply ADC_IN16 ?)

with ADC_SetChannelConfig()

after that, you configure DEMO_ADC_ETC_CHANNEL0 (Does this imply ADC_IN10 ?) DEMO_ADC_ETC_CHANNEL1 (Does this imply ADC_IN11 ?)

with ADC_ETC_SetTriggerChainConfig().

 

That said, running the example, I get 2 values.

#1. Which ADC inputs are being read/converted ?

#2. 3 ADC inputs are involved, but 2 inputs are converted. I see that the values that are converted are based on the ETC config, but then why config DEMO_ADC_USER_CHANNEL ?

#3. Are the definitions, such as DEMO_ADC_USER_CHANNEL imply ADC1_IN16 and so on ?

 

A bit confusing.

Can you please explain ?

 

Thanks,

Manu

 

 

0 Kudos

2,833 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Manu,
Thanks for your reply.
1) Which ADC inputs are being read/converted ?
-- Two channels: DEMO_ADC_ETC_CHANNEL0 and DEMO_ADC_ETC_CHANNEL1.2) 3 ADC inputs are involved, but 2 inputs are converted. I see that the values that are converted are based on the ETC config, but then why config DEMO_ADC_USER_CHANNEL?
-- After configuring DEMO_ADC_USER_CHANNEL, the ADC channels is determined by ADC_ETC.

jeremyzhou_0-1602733583965.png

 


In my opinion, I think you'd better go through the ADC and ADC_ETC chapters in advance, it can help to understand the code.
Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

2,826 Views
manuabraham
Contributor III

Hi Jeremy,

Thanks for the pointer.

So Channel selection is done by the channel number held in ADC_ETC CSEL. So does 10 imply ? Does it imply ADC_IN10, or does it imply the Sequence/Chain number ?

The language construct of document, the way the document is written, organized, makes it quite hard to follow.

The document ADC_ETC section states "ADC channel selection" for CSEL.

I guess CSELn = 10 implies ADC_IN10 ?

 

Thanks,

Manu

 

0 Kudos

2,820 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Manu,
Thanks for your reply.
1) I guess CSELn = 10 implies ADC_IN10 ?
-- Yes.
Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

2,812 Views
manuabraham
Contributor III

Hi Jeremy,

 

Thanks for the clarification.

 

So, I have a trigger from the PIT (CH0) -> XBARA -> ADC_ETC Trigger 0

Trigger 0 associated with a single Chain of Length = 8

So that I get a conversion complete IRQ with ADC_ETC_DONE_0

 

(Currently, to avoid the DMA complexity as described in Errata ERR011164, I am trying initially without the DMA capability.)

Does the ADC_ETC need 2 IRQ's to function (ADC_ETC_DONE_0, 1 as described in the example) ? Or can it work with a single IRQ ?

 

Thanks,

Manu

 

0 Kudos

2,779 Views
jeremyzhou
NXP Employee
NXP Employee

Hi Manu,
Thanks for your reply.
1) Can it work with a single IRQ?
-- Yes.
Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

2,767 Views
manuabraham
Contributor III

Hi Jeremy,

 

That helped. Did try it out. The trigger with the single IRQ worked as expected. I do see data from the conversions.

 

I am trying out the DMA part now. ERR011164 from the Errata doc suggest as a workaround:

 

"Configuring two DMA channels for ADC_ETC data transfer. The first DMA channel with low
priority triggered by ADC_ETC request is to transfer ADC_ETC data. The second DMA channel
with high priority links to the first channel is to clear request of ADC_ETC by writing
DMA_CTRL register. Both channel’s priority need to be higher than any channel used by other
peripherals. This solution is result in DMA to transfer ADC_ETC data twice for one request signal
and application need handle the redundant data properly."

 

So, I created 2 DMA channels, one with High priority and the other Low Priority.

 

#1

For the first channel I need to setup source and destination addresses, widths and lengths.

#a) But, I am slightly confused about the second channel. How should it be set up ?

(That workaround hints, that there are 2 transfers, so in all likelihood, I guess SRC and DST parameters need to be same for the 1st and 2nd channel ?)

 

#b) But that raises, yet another question. The second transfer, it could likely corrupt the 1st transfer ?

(Maybe the 2nd transfer should be a NULL transfer to a dummy buffer, like /dev/null ?)

 

#2.

What does the document mean by "second DMA channel with high priority links to the first channel" ?

 

#3.

The DMA transfer that I am trying to do:

 

Trigger#0 is based on the PIT trigger
(PIT -> ADC_ETC Trigger#0)
-----------------------------------------------------------------------
Buf[0] - [3] Ring buffer with 4 Buffers
-----------------------------------------------------------------------
No. of Channels to be converted = 8
Total Conversions to be delivered in one DMARQ = 32 (ie, 1x DMA IRQ)
(4x DMA transfers depicted, from a Ring buffer application perspective)
(8x DMA transfers depicted, from ADC_ETC perspective)
(ie, DMA coalesce's 8x Data Registers into a Single RingBuffer location)
-----------------------------------------------------------------------

Minor Loop Length = 1 (or is Minor = Major = 1, in this context ?)
Major Loop Length = 8 (No. of Channels)

-----------------------------------------------------------------------
RBuf	Buf[0]	Buf[1]	Buf[2]	Buf[3]	Buf[0]	Buf[1]	Buf[2]	Buf[3]
-----------------------------------------------------------------------
Chan	Trig#0	Trig#1	Trig#2	Trig#3	Trig#4	Trig#5	Trig#6	Trig#7
		Major	Major	Major 	Major	Major	Major	Major	Major
-----------------------------------------------------------------------
Ch#0	Minor	Minor 	Minor 	Minor	Minor	Minor	Minor	Minor 
Ch#1	Minor	Minor	Minor 	Minor	Minor	Minor	Minor	Minor
Ch#2	Minor	Minor 	Minor 	Minor	Minor	Minor	Minor	Minor 
Ch#3	Minor	Minor 	Minor 	Minor	Minor	Minor	Minor	Minor
Ch#4	Minor	Minor 	Minor	Minor	Minor	Minor	Minor	Minor
Ch#5	Minor	Minor 	Minor	Minor	Minor	Minor	Minor	Minor
Ch#6	Minor	Minor 	Minor	Minor	Minor	Minor	Minor	Minor
Ch#7	Minor	Minor 	Minor	Minor	Minor	Minor	Minor	Minor

 

 

 

TRIGn_RESULT_1_0 =>|
TRIGn_RESULT_3_2 =>|
TRIGn_RESULT_5_4 =>|
TRIGn_RESULT_7_6 =>|--->Buf[n], where n = 0 - 3

 

 

On each trigger:
'n' increments from 0 till the Ring buffer MaxSiz,
eventually cycling through the Ring Buffer

 

The TCD setup needs a Source address, but in my situation, I have 4 registers at different addresses. How can the addresses be setup with the eDMA module ?

 

Can you please explain ?

 

Thanks,

Manu

 

0 Kudos

2,737 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thanks for your reply.
Let me explain how to implement the workaround of ERR011164.
As the below diagram shows, the PIT is as the hardware trigger of the ADC_ETC, when it happens, the ADC_ETC will complete 8 conversions due to the chain feature, when the conversion completes, a DMA request will arise and be assigned to a DMA channel to transfer the ADC data to the destination area, after transfer finishes, take advantage of DMA link feature, it will trigger another DMA channel to write a specific data to DMA_CTRL register to disable the DMA request.
The second DMA channel should have a high priority to avoid be preempted by other DMA channels.

WeChat Image_20201019145515.jpg
Hope this is clear.
Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------

0 Kudos

2,720 Views
manuabraham
Contributor III

Hi Jeremy,

 

I see the picture.

The issues that I am facing .. (Let me take 1 issue per post).

 

You mentioned previously:

 

1) When the trigger causes a "chain of conversion" says ADC1_IN1 .. 8, where would the conversion results go?
-- The ADC conversion results are stored in ETC_TRIG Result Data registers.

 

I looked deeper into the registers. There are 2 register sets.

ETC Trigger Result

Base Address: 0x403B_0000

ETC_TRIG Result Data 1/0 Register (TRIG0_RESULT_1_0) @ Offset 0x28

ETC_TRIG Result Data 3/2 Register (TRIG0_RESULT_3_2) @ Offset 0x2c

ETC_TRIG Result Data 5/4 Register (TRIG0_RESULT_5_4) @ Offset 0x30

ETC_TRIG Result Data 7/6 Register (TRIG0_RESULT_7_6) @ Offset 0x34

 

and

 

Data result register for HW triggers (ADC1_R0) @ Offset 0x24

Data result register for HW triggers (ADC1_R1) @ Offset 0x28

Data result register for HW triggers (ADC1_R2) @ Offset 0x2C

Data result register for HW triggers (ADC1_R3) @ Offset 0x30

Data result register for HW triggers (ADC1_R4) @ Offset 0x34

Data result register for HW triggers (ADC1_R5) @ Offset 0x38

Data result register for HW triggers (ADC1_R6) @ Offset 0x3C

Data result register for HW triggers (ADC1_R7) @ Offset 0x40

Base Address: 0x400C_4000

 

Which one should the DMA module use it as it's DMA source ?

(I have a feeling that it should be the ADC1_Rn register instead of the TRIG0_RESULT_x_y registers ?)

 

Can you please confirm ?

 

Thanks,

Manu

 

0 Kudos

2,699 Views
jeremyzhou
NXP Employee
NXP Employee

Hi,
Thanks for your reply.
1) Which one should the DMA module use it as it's DMA source?
-- The set of ETC_TRIG Result Data registers.
2) I‘ve attached a file that can help to address the basic DMA controller usage case, please refer to it for details.
Have a great day,
TIC

-------------------------------------------------------------------------------
Note:
- If this post answers your question, please click the "Mark Correct" button. Thank you!

- We are following threads for 7 weeks after the last post, later replies are ignored
Please open a new thread and refer to the closed one, if you have a related question at a later point in time.
-------------------------------------------------------------------------------