ADC - DMA - Circular buffer

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

ADC - DMA - Circular buffer

5,115 Views
lowly-user
Contributor I

Good morning everyone,
for several weeks I have been trying to implement ADC data acquisition through DMA on a circular buffer on micro iMXRT1020, I ask you for help.

DESIRED OPERATION

The board provides 8 analog inputs that go to an external MUX whose single output enters into iMX on an analog input. The application must sample this input, transfer the data via DMA and move the GPIOs to drive the external MUX on the next channel. The process must work in a continuous loop so I have implemented a circular buffer on which to store the data.

What I have done, following SDK examples and material online is:

  • Enable a PIT timer at the desired sample rate
  • Configure XBARA with PIT input and ADC_ETC output
  • Enable ADC on channel 1
  • Configure ADC_ETC with CHAIN_LENGTH = 1
  • Configure two EDMA channels like this:

TCD [1]
- source = ADC
- destination = circular buffer
- source data size = 2 (12bit)
- target data size = 2
- byte each minor loop = 2
- total number of bytes = 2
- Minor link connected to itself
- Major link connected to channel 0

Enabling the 32byte destination module

TCD [0]
- source = constant buffer containing mux configuration
- destination = GPIO-> DR
- source data size = 4 (size of a given source)
- target data size = 4 (GPIO log size)
- byte each minor loop = 4
- total number of bytes = 4
- Memory -> peripheral
- Minor link connected to itself

Enable the 32byte source module


In this way, the circular loop works: at each tick of the PIT I have an acquisition of the ADC channel, a data transfer in the DMA buffer [1] and an increase of the MUX DMA channel [0].

PROBLEM 1:
To do this, however, I had to enable the interrupt of the ADC and inside I must necessarily call
EDMA_EnableChannelRequest (DMA0, CH1);
otherwise the dma transfers only the first data and then it is as if it were no longer re-armed.
This is not good for me, it loses the sense of use of the dma.

between the different tests, I tried to modify the number of transfers (n) but in doing so I obtain that at the trigger of the PIT, the ADC converts and the DMA transfers the same data n times (which will have the same value).

PROBLEM 2:
on other platforms I'm used to using circular buffers like this: at each conversion ADC triggers the DMA which transfers the data. The dma is configured to circularly transfer N data and provides a half-transfer interrupt and a complete-transfer interrupt that the application uses to determine what the pointer to valid data is.
The system implemented in this way, however, does not allow me this system as the dma provides an interrupt every transfer and not every half or whole buffer.

Anyone have any suggestions? I have practically reached the evaluation time limit of this hardware that is blocking the project and the probable alternative is to change component.

thank you

0 Kudos
4 Replies

5,067 Views
lowly-user
Contributor I

hello Pavel, I am attaching the source.
As you can see, once the conversion has started I expect to fill the g_ADC0_resultBuffer buffer in a circular way.

The things that are not right are:

  • as implemented, if I remove the "EDMA_EnableChannelRequest" instruction inside the ADC interrupt (DONE0), the loop stops at the first conversion.
  •  keeping the interrupt activated makes you lose the sense of DMA
  •  in this way I have to manage the double buffering manually (in the EDMA_CAllback_1 I increase the counter that I will use in the wired_zone_run to define which is the half of buffer with valid data). In other architectures this was automatic using the half_interrupt and the transfer_complete but in this case it is impossible as I am forced to define a single transfer size.

I hope you can give me support.

thanks

0 Kudos

5,023 Views
Pavel_Hernandez
NXP TechSupport
NXP TechSupport

Hello, sorry for the time long this took, I reviewed your code and I have some suggestions, I checked the Initialization for the DMA that I compared with an example from the SDK, lpuart_edma_rb_transfer, it looks similar but I think you forgot the initialization of the TCD. Please review that information and let me know if you need help.

0 Kudos

4,979 Views
lowly-user
Contributor I

Hi Pavel, thanks for your reply. The example you suggested is related to the scatter gather mode configuration. Data from a UART is stored in a circular buffer which is filled in the EXAMPLE_ReadRingBuffer function where the index is also calculated.

This function, however, is performed from when a character is received and this occurs in interrupt.

In my case, I need to fill a circular buffer without the CPU handling any interrupts. No peripheral interrupts must be managed by the CPU but the ADC must autonomously transfer the data in a circular buffer through the DMA.

The only interrupts that I will have to manage are half-transfer and full-transfer DMA which will intervene at the middle (half-transfer) and at the completion (complete-transfer) of the circular buffer in order to define the pointer of valid data.

It seems to me an extremely basic application. I do not understand if it is me, a neophyte of this machine, who is not able to create the architecture or if the machine is not able to do it. In fact, I am deciding whether to propose to the company to change the device.

0 Kudos

5,074 Views
Pavel_Hernandez
NXP TechSupport
NXP TechSupport

Hello,

Could you share your code with us? it would be faster to analyze your code and see what configuration is needed.
 
Best Regards,
Pavel
0 Kudos