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