The elegant way to handle ADCs with DMA in a RTOS

298 Views Asked by At

I'm currently setting up an AZURE RTOS (ThreadX on STM32), with Ethernet, SPI and ADCs activated.

This STM32 has to pass-through configuration information from time to time, coming from my PC over the Ethernet-Port.

It has to pass these information via SPI to two other STM32, which makes the first STM32 the system-controller / system-interface. This will be a low-priority task, since the activation of the passed configuration will be started by sync-lines, running from the system-controller to the two other STMs.

While doing so, the system-controller has to read-in ADC values constantly and pass them via Ethernet / TCP to my computer.

I've used the ThreadX TCP server example, as given by STM, as a starting point.

From there I've managed to set up three servers on three ports, communicating sucessfully with a python script on my PC (as a first test).

Now come the two great questions:

1) Since my input signal may contain frequencies up to 2.5 MHz, I want to digitize this signal with the full 5 MSPS (Nyquist), which ADC3 is capable of.

The smallest internally available data-type at full resolution is uint16_t, which makes the data rate work out to be R = 16 * 5 MSPS = 80 MBit/s (worst-case, I bet, there is optimization possible ... e.g. 8 bits resolution, which halves the data-rate ... but this resolution might not be enough ... or 16 bits, and FFT afterwards, which is also sufficient, since I'm mostly interested in energy per frequency band, but initially I wanted to do this on my computer, for best flexibility).

Even if the Ethernet-IF is capable of doing 100MBit/s, the TCP layer of NetXDuo, I bet, is not.

(There is also USB OTG on this board available, but since networked devices are in my opinion more versatile, I prefer using Ethernet ... nevertheless, USB might be a backup solution)

From my measurements, a data-stream transmitted to the uC via TC from within python, and mirrored back within a thread to my PC allows for relatively consistent 20 MBit/s.

... How do I push this speed to a better level?

(I think 20MBit/s is the back-and-forth data-rate, so one-way may be faster)

However. Second question:

2) The ADC within the STM is capable of storing data via DMA to memory.

There are two callbacks available, one at half-full, one at full buffer state.

My problem is mostly about the way of reading out the DMA and/or triggering the conversion in the first place.

How do you do this the "right" way on a RTOS (such that you don't brake the RT in RTOS)?

I see some options here, what are the pros/cons you can think of?

a) Let the ADC run freely, calling the call-backs at the respective fill-levels, triggering a TCP-transmission whenever one of the call-backs is reached -> may lead to glitches due to insufficient speed of the TCP layer in my opinion.

b) Let the ADC conversion be triggered by a thread, which is preempted and will later TCP-transmit the data, as soon as the memory-buffer is full -> may lead to inconsistency in the converted values, since you get burst-style conversions, with gaps in between, while the buffer is read

c) Let a thread trigger each conversion individually -> A no-go I think, since threads are not triggered that often, to get a decent sample-frequency

d) Let a free-running ADC trigger callbacks, let a thread do the FFT, transmit within another thread the data via TCP -> May work, but is less flexible, since the data gets crunched within the uC.

--> Are there other ways you can think of / what do you think about the ways I named here?

--> What do you think about question 1)?

Have a nice day!

0

There are 0 best solutions below