"Best" way to trigger fast ADC sample rate with freeRTOS???....... - Page 1
Forum section: electronics / general

author: Smokey
author_rank: Super Contributor
timestamp: March 07, 2024, 02:39:26 am
content: I have a project that requires the use of FreeRTOS because of a network stack. This happens to be running on an ESP32, but I think this is essentially the same question for any project running freeRTOS.Problem:I need to take ADC samples from a single channel at about 5kHz (200us), but the FreeRTOS system tick is 1ms. That rules out using FreeRTOS tasks/timers/etc that rely on the tick. Making the tick faster starves the system of cycles since it runs so often.Given that I can't just go bare-metal for everything and have to keep the FreeRTOS system happy and not break anything RTOS related, what is the "best" way to trigger the ADC and store those samples at a rate faster than the System Tick?

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 07, 2024, 02:40:50 am
content: Use interrupts.https://freertos.gitbook.io/mastering-the-freertos-tm-real-time-kernel/mastering.ch07

author: JPortici
author_rank: Super Contributor
timestamp: March 07, 2024, 06:31:04 am
content: +1 for interrupts, and read that chapter page. or if DMA is available ADC + DMA and then interrupt once you have enough samples in the DMA buffer

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 07, 2024, 06:36:21 am
content: +1 for DMA as well, unless you need to react to each sample in some specific way.

author: hans
author_rank: Super Contributor
timestamp: March 07, 2024, 08:16:17 am
content: I think still the answer is bare metal.The tick period of 1ms is already quite fast (some projects use 10ms or are tickless), and should be allocated for the relatively slow response of RTOS tasks.5kHz sampling is then too fast to do in software and carry all of this RTOS overhead. Unless the ADC needs to be preemptive its better to put it in a small IRQ handler and call it a day.RTOS is great if you need preemption, but for 5kHz (200us) you would need to very quickly handle that preemption (and subsequent priority inversion) to adhere to this real-time requirement.If those ADC samples @5kHz need to go to ADC, consider buffering a couple to cut down the invocation rate of the RTOS task. This is also a common technique applied with DMA, where you can specify how many transfers till a half/full complete IRQ occurs.

author: nctnico
author_rank: Super Contributor
timestamp: March 07, 2024, 04:16:16 pm
content: DMA is certainly the way to go in this specific case. Normally a microcontroller shouldn't have a problem with keeping up with a 5kHz interrupt at all but I have the feeling the Espressif software is blocking interrupts for prolonged periods of time. Recently I investigated why the UART on an ESP32 loses characters at 115k2 baud. After digging deep into the UART driver (including stripping it to a bare minimum) it turns out that the UART overflows due to missing the interrupts even though the UART has a 128byte FIFO.Edit: the UART problem turned out to be caused by the UART ISR handler not being placed into IRAM (this is a configuration option).

author: MarginallyStable
author_rank: Regular Contributor
timestamp: March 07, 2024, 04:53:07 pm
content: Can run RTOS on one core and a baremetal task on the other.

author: tggzzz
author_rank: Super Contributor
timestamp: March 07, 2024, 05:11:13 pm
content: Quote from: Smokey on March 07, 2024, 02:39:26 amCan I suggest you evaluate thejitterin the 200µs that your application can tolerate. That may determine what is and isn't possible.

author: PlainName
author_rank: Super Contributor
timestamp: March 07, 2024, 05:22:12 pm
content: QuoteIsn't FreeRTOS tick on the ESP32 10ms? The resolution is 1ms but actual task switch is 10ms I'm sure. Not that it makes much of a difference in this caseQuoteIt's perfectly possible to use FreeRTOS as a subservient process. You can use it in cooperative mode if necessary, or you could drive the tick from the ADC interrupt (allowing the ADC to pre-empt FreeRTOS.In this case, apparently FreeRTOS is desired because of the services it provides, so going baremetal would require much more work than just bringing the ADC interrupt forward a bit.

author: martinribelotta
author_rank: Regular Contributor
timestamp: March 07, 2024, 05:27:27 pm
content: Here is the pertinent example using ESP-IDF:https://github.com/espressif/esp-idf/blob/v5.1.1/examples/peripherals/adc/continuous_read/main/continuous_read_main.cThis use ADC in continuous mode (ADC-DMA) and is suitable to change the sampling rate and take the result per frame (configurable amount of samples)In my experience, the sample-to-sample mode (in any platforms) is only suitable when the processing latency from input to output will be only one sample... This situation is extremelly rare and normally is desirable to process frame by frame in an application-dependent size buffer

author: TomS_
author_rank: Frequent Contributor
timestamp: March 10, 2024, 12:31:26 pm
content: Timing doesn't have to come exclusively from FreeRTOS. You can use interrupts at a priority above the FreeRTOS kernel (and any priorities that FreeRTOS needs to be able to mask) and still have those interrupts fire even if FreeRTOS masks out the lower priorities.This allows you to e.g. run a timer whos ISR takes an ADC reading. But you can't interface with FreeRTOS from those higher priorities to put those readings into a queue for example, so you have to get a bit more clever with how you take and store the readings to make them available to a task running under FreeRTOS.

author: peter-h
author_rank: Super Contributor
timestamp: March 12, 2024, 04:48:00 pm
content: Timer -> ADC -> DMA -> RAMThe DMA writes into a circular buffer and this either just wraps and overwrites old stuff, or reaching the transfer count triggers an ISR which resets the DMA address or whatever.ISRs run very fast on these chips. I have ISRs running is 3-4us on a 168MHz 32F417.And using the timer to trigger the ADC will give you minimal jitter.

author: radiolistener
author_rank: Super Contributor
timestamp: March 17, 2024, 02:22:20 pm
content: just put some sound codec chip in your circuit, something likeTLV320AIC3204.You can find a lot of examples and drivers for these codecs.It helps you to capture signal with higher sample rate and low sample jitter.There is no need RTOS for such simple task.PS: by the way, 5 kHz sample rate for ADC is a very slow low speed ADC. High speed ADC working at 100-200 MHz sample rate or higher.

author: PlainName
author_rank: Super Contributor
timestamp: March 17, 2024, 02:41:02 pm
content: QuoteI think you've just responded to the title and neglected to read this bit in the actual requirements of the first post:Quote

author: radiolistener
author_rank: Super Contributor
timestamp: March 18, 2024, 01:58:18 pm
content: Quote from: PlainName on March 17, 2024, 02:41:02 pmI responded to original post. What I wanted to say is that RTOS is not required for ADC or audio codec like TLV320. If you're needs to use RTOS for other requirements, that's your choice, but you can read stream data from audio codec independently if you use RTOS or just implementing bare metal firmware with no RTOS.

author: tooki
author_rank: Super Contributor
timestamp: March 22, 2024, 08:54:50 am
content: Quote from: radiolistener on March 18, 2024, 01:58:18 pmBut everyone, including the OP, clearly knows an RTOS isn’t needed for the ADC. You aren’t providing some keen insight, you’re just adding noise.

author: radiolistener
author_rank: Super Contributor
timestamp: March 25, 2024, 01:29:21 pm
content: I just proposed the good and cheap way to get low jitter ADC measurements.It allows to decrease ADC phase noise and get higher speed stream from ADC with less CPU load.And it provide you much less ADC phase noise and more easy solution than using internal ADC with DMA.There are possible other solutions but they are not so simple and cheap, because it requires more expensive components, such as FPGA. Which are more complicated and will be overkill for the topic starter needs.While internal ADC phase noise is limited with internal timers jitter, which is not good and you will get higher phase noise. With high clock jitter, you will get more noisy ADC output.Since topic starter needs ADC with about 5 kHz sample rate, using audio codec will be a nice solution. Because it already has all things to capture ADC data with low clock jitter and with high dynamic range and stream that data to CPU with sample rate up to 384 kHz.By using external audio codec, you can clock it from ultra low phase noise clock source and get ready to use sample stream... without having to worry about samples being taken with configured sample rate and with minimum clock jitter.The topic starter asked for the best way to trigger ADC. And trigger it from dedicated ultra low phase noise clock source is the best way to get maximum ADC performance and minimize phase and amplitude noise on ADC output.Any clock source from microcontroller is not good for ADC due to a very high clock jitter. Just open microcontroller datasheet and check it's jitter on GPIO, it is very high. FPGA has better jitter performance than microcontrollers, but still very bad for ADC clock. This is why using dedicated ultra low phase noise clock source is the best way to trigger ADC in order to get the best ADC performance.

author: Smokey
author_rank: Super Contributor
timestamp: March 25, 2024, 06:38:57 pm
content: ha! you guys leave radiolistener alone! He's just trying to be helpful! Let me just go add an FPGA and external audio codec to my design...Something like this should be good right?https://www.digikey.com/en/products/detail/amd/XC5VFX100T-2FF1738C/3981496Seriously though, nothing I'm doing for this application needs anywhere near that level of precision from either the ADC resolution or phase noise perspective (the ESP32 should be a giveaway).The "right" answer, as you guys pointed out, is interrupts/dma and then signaling the RTOS task to use the ADC data and being careful not to take too many cycles from the RTOS. That is so far working and not interfering with the radio aspects of the RTOS that I don't really have control over.

author: radiolistener
author_rank: Super Contributor
timestamp: March 25, 2024, 06:57:12 pm
content: Quote from: Smokey on March 25, 2024, 06:38:57 pmif you're want to work with a high speed ADC for a phased array radar it may be the good choiceFor 5 kHz sample rate and single ADC it will be overkillQuote from: Smokey on March 25, 2024, 06:38:57 pmbut you're asked for the best way to trigger ADC...Feeding ADC with a clock from microcontroller timer is definitely not the best way for jitter / phase noise performance.

author: tooki
author_rank: Super Contributor
timestamp: March 25, 2024, 07:15:55 pm
content: Quote from: radiolistener on March 25, 2024, 06:57:12 pmYou don’t understand sarcasm, do you? He was making fun of your suggestion, which was excessive and ignored OP’s stated requirements.

author: radiolistener
author_rank: Super Contributor
timestamp: March 25, 2024, 07:29:57 pm
content: Quote from: tooki on March 25, 2024, 07:15:55 pmI well understand his sarcasm. But some peoples just don't understand and don't realize that ADC clock jitter can affect ADC output results and dynamic range. And I'm not sure if these who laugh understand it.I personally feel there is something wrong with the design if it needs to read a 5kHz ADC clocked from software generated clock and using interrupts.