AnsweredAssumed Answered

i.MX7Dual high-speed ADC sampling

Question asked by Thomas Benson on Apr 2, 2018
Latest reply on Apr 6, 2018 by Raymundo Velarde



[Edited to add new information.]


I have an i.MX7Dual Sabre SD development board and I would like to develop a test application that performs high-speed (1 Msample/sec) sampling of the two ADC blocks on the M4 as a bare metal application. I have read through Ch. 14 of the reference manual and reviewed the adc_imx7d example in the FreeRTOS BSP, but I still have several questions:


- [A previous version of this question asked about multiple channels, but I since realized that it would be better to use a single channel for both ADCs, so I have removed the channel-related questions.]

- The manual briefly mentions a DMA FIFO for the ADCs, but it does not address how to use DMA with the ADCs. Similarly, the FreeRTOS BSP ADC driver does not support DMA and neither does the Linux kernel driver in the forked 4.1.x kernel series. Is there some other documentation or source of examples that can provide details on using DMA with A/D conversion?

- One motivation for using the FIFO mechanism is that it provides feedback for FIFO over/underruns. If not using FIFO/DMA, is there any way to determine if we are dropping samples? I believe that the i.MX6 SoCs had a flag to control whether new samples overwrote previous samples or were discarded in the case that the conversion complete flag was still set from a previous conversion, but the i.MX7 manual does not seem to address the possibility of overruns, other than when using the FIFO with DMA.

- What constitutes a conversion timeout? I have developed a sample bare metal application and have confirmed that conversion overruns do not set the timeout flag, so from what I can tell, there is no way to determine if samples have been dropped/missed.

- All of the MX7D SabreSD documentation indicates that the M4 runs at "up to 200 MHz". It appears based on the BSP and the values reported from the cycle counter that the M4 is actually running at 240 MHz (e.g. see the SystemCoreClock variable in system_MCIMX7D_M4.c from the BSP).

- I believe there may be a bug in the ADC driver for the FreeRTOS BSP. In the function ADC_SetConvertRate() from adc_imx7d.c, the quotient sampleRate/convertRate is written to the CHA_TIMER field of the CFG1 register, but according to the documentation this yields a conversion rate of (CHA_TIMER+1)*sampleRate. Thus, for matched values, we want CHA_TIMER=0 rather than CHA_TIMER=1; presumably we need to subtract 1 from the quotient prior to writing it to CHA_TIMER.


I have developed a bare-metal application running on the M4 that samples both ADCs in continuous mode using matched-priority interrupts. I also record the cycle counter immediately after reading the ADC value. I get stable results when only managing a single ADC (cycle counts reliably in the range 238-242 cycles, which is consistent with a 240 MHz clock and 1 MSPS sampling). However, with both ADC blocks running, I get some timing anomalies. For example, I see the following with a single ADC:

conv=2608 cyc= 5291581 diff=241
conv=2576 cyc= 5291820 diff=239
conv=2549 cyc= 5292062 diff=242
conv=2505 cyc= 5292300 diff=238
conv=2475 cyc= 5292542 diff=242
conv=2429 cyc= 5292780 diff=238
conv=2399 cyc= 5293022 diff=242
conv=2371 cyc= 5293260 diff=238

and this with two:

conv=2399 cyc= 5294669 diff=460 conv=3060 cyc= 5295358 diff=458
conv=2339 cyc= 5295131 diff=462 conv=2979 cyc= 5295821 diff=463
conv=2294 cyc= 5295590 diff=459 conv=2864 cyc= 5296279 diff=458
conv=2263 cyc= 5296048 diff=458 conv=2792 cyc= 5296742 diff=463
conv=2204 cyc= 5296510 diff=462 conv=2757 cyc= 5297200 diff=458
conv=2170 cyc= 5296969 diff=459 conv=2514 cyc= 5299500 diff=2300

where conv is the raw value from the ADC, cyc is the cycle counter, and diff is the difference between cycle counters for the same block. I fill up a fixed-sized buffer and then stop the ADCs to print the results, so there are no debugging print statements while processing. The conversions seem to be running at roughly half-rate with both blocks enabled. In addition, I seem to drop a lot of samples from ADC2 intermittently (i.e. the diff=2300 above). Does anyone know why this is the case?


More generally, does anyone have any recommendations for reliably sampling both ADCs at 1 MSPS without dropping samples? Or is this task just not suited to this SoC?