High speed external ADC sampling

This forum is for users of Microchip MPUs and who are interested in using Linux OS.

Moderator: nferre

linuxnoob
Posts: 7
Joined: Thu May 21, 2020 4:09 pm

High speed external ADC sampling

Fri Oct 23, 2020 12:50 pm

Hi all,
I am using the SAMA5D27_WLSOM1_EK board with linux4sam 5.4.41.
I have an external ADC (MCP3914) connected via SPI1 on the Mikrobus port,
which I am trying to interface with at high speed.
I developed a driver using iio_triggered_buffer to read samples on an interrupt
when the Data Ready pin from the board falls. It works well and using
iio_generic_buffer I can get a fairly fast reading of the 8 channels from the board.
However, I would like to be able to sample at the maximum speed of 125KSps of the ADC.
I have searched everywhere for an example of a similar project but cannot find it.
I have tried to implement DMA, but I am not sure whether I need to just copy data to memory
via dma, or whether to configure the SPI to use it. Also, using a hardware interrupt will probably
take a lot of CPU cycles and might not be the best way to implement this.
Can anyone give any suggestions of the best approach (if it's even possible).
I have read of some getting >200KSps for an ADC, but I'm not sure if that is with the internal peripheral.
Many thanks for any help.
blue_z
Location: USA
Posts: 2154
Joined: Thu Apr 19, 2007 10:15 pm

Re: High speed external ADC sampling

Sat Oct 24, 2020 3:14 am

linuxnoob wrote: I am using ... linux4sam 5.4.41.
The is no such software and version combination .
There is the linux4sam-2020.04 release tag for linux-at91 that is based on Linux kernel version 5.4.41.

linuxnoob wrote: I developed a driver using iio_triggered_buffer to read samples on an interrupt when the Data Ready pin from the board falls.
Assuming that you didn't write a (SPI protocol) driver from scratch, which Linux kernel driver(s) did you use as a model?
The only "board" you have mentioned is the SAMA5D27_WLSOM1_EK board, so "Data Ready pin from the board" is misleading.

linuxnoob wrote: It works well and using iio_generic_buffer I can get a fairly fast reading of the 8 channels from the board.
However, I would like to be able to sample at the maximum speed of 125KSps of the ADC.
How fast is "fairly fast"? IOW how much improvement do you need to attain the goal?
Is your trigger clock fast enough?
Do you have a program to read the data that fast? See this topic.

linuxnoob wrote: I have tried to implement DMA, but I am not sure whether I need to just copy data to memory via dma, or whether to configure the SPI to use it.
If you don't describe what you did and the results, then telling us you "tried" is not informative.
Your "X or Y" dilemma makes no sense.
Do you understand that the data flow is from your (external) ADC to the SPI master controller (integrated into the SoC) over the SPI bus, and then there is a second transfer from the SPI master controller to main memory (aka RAM) using either programmed I/O (aka PIO) or DMA?
The SPI protocol driver would coordinate the first transfer between the ADC and SPI master controller, e.g. handle an ADC completion interrupt and then request the SPI master controller to initiate the SPI transfer.
The second transfer (either DMA or PIO) would be handled by the driver for the SPI master controller, which is atmel-spi.c.

linuxnoob wrote: Also, using a hardware interrupt will probably take a lot of CPU cycles and might not be the best way to implement this.
Are you (incorrectly) using "hardware interrupt" to refer to programmed I/O (aka PIO)?
If not, then why is there a hesitation to use "hardware interrupts"?
DMA can also use "hardware interrupts". Without using a completion interrupt, you have to poll for the completion of the DMA transfer, which is counterproductive to the purpose of DMA.

The SoC-level Device Tree file sama5d2.dtsi configures the spi1 controller node with DMA capability by default.
So unless your board-level entry for that SPI master controller disables DMA by re-defining those properties, you could be unknowingly using DMA.

Regards
linuxnoob
Posts: 7
Joined: Thu May 21, 2020 4:09 pm

Re: High speed external ADC sampling

Sun Oct 25, 2020 4:33 pm

Hi and thanks,
I used the MCP3911 driver that is already available, and modified it to support triggered buffering.
The "hardware interrupt" is the data-ready pin of the ADC which is connected to a pin on the
Mikrobus and use as the trigger to read.
I put a scope on the data-ready line and the SPI clock and I can see that they are not aligned.
I am reading packets every ~180us, whatever the frequency of the data-ready pulse.
At a higher rate of 78KSps, (with the Data Ready interrupt every 12.6uS), when I enable the buffer, the board locks up.
I also tried with a hrtimer and was unable to get any higher read rate. It seems that the SPI
reads are somehow fixed at this rate.
I am just unsure if I am approaching this the right way, using the data-ready pin.
Thanks again.
blue_z
Location: USA
Posts: 2154
Joined: Thu Apr 19, 2007 10:15 pm

Re: High speed external ADC sampling

Tue Oct 27, 2020 12:26 am

linuxnoob wrote: I am reading packets every ~180us, whatever the frequency of the data-ready pulse
SPI is not a dumb hardware interface. What commands are those "packets every ~180us" in response to? Continuous Read mode?

linuxnoob wrote: At a higher rate of 78KSps, ... the board locks up.
Which "board"?
Try enabling the various kernel debug configuration features such as spinlock and rw-lock debugging and deadlock detection.

linuxnoob wrote: I also tried with a hrtimer and was unable to get any higher read rate. It seems that the SPI
reads are somehow fixed at this rate.
I am just unsure if I am approaching this the right way, using the data-ready pin.
Do not try using a (hr)timer in place of the DR interrupt. The latency will accumulate, and then the driver will not be able to maintain the rate of DRCLK.

Perhaps instead of focusing on how to get faster rates, what steps have you performed to confirm proper operation at a basic level?
For the simplest possible configuration, e.g. a slow sample rate and minimum oversampling on one channel, are conversion values available at the expected rate?
Then what happens as the sampling rate is increased?

Regards
linuxnoob
Posts: 7
Joined: Thu May 21, 2020 4:09 pm

Re: High speed external ADC sampling

Tue Oct 27, 2020 1:34 pm

Hi blue,
Thanks for the reply.
What I am seeing on the scope is the data-ready signal every ~100us (at an OSR of 256) and the SPI
transfer I set up to read the ADC values every ~180us, so they aren't getting sent
when the data-ready interrupt occurs.
Thanks for the info about hrtimer.
When I say the board locks up, I mean my tera-term connection to the SAM board. I can only
reset the board to recover.
I used the MCP3911 driver and modified it to use iio triggered buffer, as I assumed that was the
best way to read samples based on the hardware data-ready interrupt.
I am not sure how to do a continuous read and am struggling to find any information on how to do this.
I will do some testing on various read rates now.
Much appreciated.
linuxnoob
Posts: 7
Joined: Thu May 21, 2020 4:09 pm

Re: High speed external ADC sampling

Tue Oct 27, 2020 1:52 pm

Just did a quick test, on a few of the slower sample rates and it does send the SPI transfer
after each DR interrupt. However, it takes about 30us between the interrupt and sending the SPI transfer.
At an OSR of 128 (DR frequency of ~50us), I am missing many interrupts, sending transfers only every ~100us.
Thanks again.
linuxnoob
Posts: 7
Joined: Thu May 21, 2020 4:09 pm

Re: High speed external ADC sampling

Tue Oct 27, 2020 3:50 pm

Further testing, I removed any spi calls in the trigger_handler just writing data with iio_push_to_buffers_with_timestamp
and set the osr at 32. The DR interrupts every ~12.6us and the board still freezes. It seems to me that the
system cannot handle interrupts at that frequency?
linuxnoob
Posts: 7
Joined: Thu May 21, 2020 4:09 pm

Re: High speed external ADC sampling

Wed Oct 28, 2020 10:41 am

I spoke to someone in Microchip and it does appear that the problem is the interrupt latency.
blue_z
Location: USA
Posts: 2154
Joined: Thu Apr 19, 2007 10:15 pm

Re: High speed external ADC sampling

Thu Oct 29, 2020 12:57 am

linuxnoob wrote: Further testing, I removed any spi calls in the trigger_handler just writing data with iio_push_to_buffers_with_timestamp ...
I'm not an expert on IIO or ADCs, but your use of terminology is confusing to me, e.g. what you are referring to with "trigger_handler "?

In the context of an ADC, I'm used to seeing "trigger" almost exclusively used to refer to the what/how the sample-hold-conversion process is initiated. For the integrated ADC of the SAMA5D2, you have several choices for the trigger, e.g. software, internal hardware (timer/counter), or external hardware.
The MCP391x is described as "synchronous sampling", which I interpret to mean that the one and only trigger is a clock. And since that clock is always running, the means of controlling/initiating conversions would be to configure the ADC channels.

Since the MCP391x is synchronous sampling, the DR interrupt would have nothing to do with triggering.
The DR interrupt means that a 24-bit value can be requested, which seems to be implemented in the mcp3911.c driver as a spi_write_then_read() operation. Note that it is a write (command) over SPI, then read (data) over SPI.
Then that data value has to be transferred by PIO or DMA from the SPI master controller to main memory.
You're not clear as to which of these operations are performed at the ISR level; i.e. the more processing that is done in the ISR, then fewer interrupts can be processed!

At the very least the DR generation should be configured for just a single DR pulse for all channels (i.e. the DR_LINK control bit should be enabled), and a continuous read should transfer the converted channels as one message.

Regards

Return to “LINUX”

Who is online

Users browsing this forum: No registered users and 4 guests