High speed ADC with Imx6UL

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

High speed ADC with Imx6UL

2,439 Views
jonasnyberg
Contributor III

Hi all,

We've got a project that involves reading up to 6 ADC values simultaneously with a speed of minimum 20KHz per channel. All data channels has to be synced with each other up to an accuracy of ~±100uS. The data-width required is 12-16bits. The 20KHz reading frequency should be quite stable, but a small jitter is acceptable.

With a fast calculation this would sum up to ~20000*6*16 = 1,92MBit/s or 240kByte/s.

As we are using the IMX6UL in another project (with one internal ADC-channel in use) I was wondering if anyone has done or been successfull in modifying the driver to suit this purpose?

We now read our one channel though Sysfs via file-read which is very slow, we can only get sample rates up to around 1KHz while already utilizing 25% of the processor time. Also the sample jitter simultaneously gets really big because of highly differing read-times.

Another approach I was thinking of is adding an external ADC through SPI, but it would be so much easier if directly using the already present internal ADC. Just as the calculation showed a raw data stream of ~240kB/s, I don't think that this would be impossible at all. The data-stream would go to a ring-buffer in RAM and HD-write (FLASH) is only enabled by user input.

Kind regards and all help appreciated,

Jonas Nyberg 

Labels (4)
7 Replies

2,024 Views
gdam
Contributor I

Hi Jonas, we are planning to do the same: high-speed sampling of 2 analogue inputs using the internal ADC. Can you advice what path you ended-up following? What have been the results? Thanks!

0 Kudos

2,024 Views
ceggers1
Contributor IV

Hi Gert,

do you need a particular sample rate? It looks like the i.MX6UL(L) ADCs cannot be triggered by a timer. So the only option to control the sample rate is adjusting the ADC frequency, sample time and conversion time.

For higher performance, I would suggest using the SDMA (custom script). Using SDMA usually means to capture a number of samples (e.g. 64, 128, 256, ...) and then raise an interrupt to the ARM CPU. This can greatly reduce the number of required context switches (between user space, kernel and ARM IRQ) and so increase the performance.

Please provide some further details about your application if your problem still exists.

regards

Christian

2,024 Views
gdam
Contributor I

Hi Christian, many thanks for your kind reply.

A few more details:

  1. we like to sample complete vibration time-waveforms, sampled at 64kHz
  2. preferably this is done on both ADC inputs simultaneously 
  3. the length of the time-waveform would be max. 2 seconds = 128k samples
  4. I've been reading the nxp manual on this chip but didn't read about the sdma also able to work with the ADC (other applications were mentioned but not the ADC)
  5. I also haven't found a ready driver which can pick-up complete time-waveforms at a high frequency
  6. We would want to pick-up such a time waveform once / minute 

So far I havent had an answer on the question if it can actually be done....

We run Linux  OS on the NXP chip

Many thanks for any guidance you can give on this - Gert

0 Kudos

2,024 Views
ceggers1
Contributor IV

Hi Gert,

> 1. we like to sample complete vibration time-waveforms, sampled at 64kHz

lets try some calculations for the sample rate. I use the following clock frequencies from my system:

  • tBus = 1 / 66 MHz = 0.015 µs
  • tADC = 1 / 33 MHz (66 MHz / 2) = 0.030 µs
  • SFCAdder = 3 tADC + 1 tADC + 2 tBus = 0.150 µs
  • AverageNum = 1

Single Conversion Time = SFCAdder + AverageNum x (BCT + LSTAdder) = 0.150 µs + 1 x (0.75 µs + 0.090 µs) = 0.99 µs

So the maximum sample rate for this conditions would be 1 / 1 µs = 1 MHz. Now lets try to find suitable parameters for 64 kHz. Lets decrease the ADC frequency:

  • tADC = 1 / 4.125 MHz (66 MHz / 2 / 8) = 0.24 µs
    • SFCAdder = 3 tADC + 1 tADC + 2 tBus = 1 µs
    • BCT = 25 tADC = 6.06 µs
    • LSTAdder = 3 tADC = 0.73 µs
    • Single Conversion Time = 1 µs + 1 x (6.06 µs + 0.73 µs) = 7.79 µs = 128 kHz

After further adjusting the sample time (LstAdder) and the AverageNum, you should be able to get something around 64 kHz (but only approximately, not exactly).

> 2. preferably this is done on both ADC inputs simultaneously

One ADC cannot convert multiple channels simultaneously. Depending on the i.MX6UL(L) model you are using, you may have to ADCs. These ADCs are not coupled in hardware, but you should be able to start conversions on both ADCs with only some CPU cycles delay. For instance the SDMA is clocked with 66 MHz. Even if you would need 10 SDMA clock cycles to start the 2nd channel, this would be 0.15 µs (about 1% of the conversion time).

> 3. the length of the time-waveform would be max. 2 seconds = 128k samples

The count field in a SDMA buffer descriptor is limited to 16 bit (65535). But in a custom script this wouldn't matter. Only the size of the memory allocated by kmalloc must be big enough, that shouldn't be a problem.

> 4. I've been reading the nxp manual on this chip but didn't read about the sdma also able to work with the ADC.

In IMX6ULLRM.pdf, section 3.3 – "SDMA event mapping", you can see that both ADCs have event lines connected to the SDMA. I think the SDMA scripts provided by NXP are not usable for ADC, but you could write you own ones. In my current project, I use ADC1 together with the SDMA.

> 5. I also haven't found a ready driver which can pick-up complete time-waveforms at a high frequency

Similar answer as for question 4: The provided driver (vf610_adc) is not suitable for this. If you have some experience in writing Linux drivers, you could write you own driver which receives the 2x128k samples from the SDMA (after the conversion has been completed).

> 6. We would want to pick-up such a time waveform once / minute.

If you are able to process the data within this time, this shouldn't be an issue.

Conclusion:

I assume that your application can be implemented using both ADCs together with the SDMA. There is no pre-built solution for your task, so you would have to build you own. If I would do the task myself, I would calculate about 2 weeks full time for this (I have already some experience with Linux device drivers and also with SDMA). If you start from zero, I would calculate much more.

If you want to go this way, for SDMA development you have 3 options:

  1. Ask NXP for paid support.
  2. Use the assembler provided by Eli Billauer.
  3. Ask me for development tools! I have ported GNU binutils (as, ld, objcopy, ...) for SDMA. I'm willing to mainline this work soon, but I'm still looking for someone who wants to sponsor this work. Additionally I have ported Lauterbach's Trace32 debugger for SDMA. Without using this debugger, none of my scripts would work today!

regards

Christian

0 Kudos

2,024 Views
jonasnyberg
Contributor III

Hi again,

Anyone have any experience with this?

I also saw that a newer driver version of the Vf610 adc should be compatible with the continuous capture mode now? 

Would it then be faster if the driver and adc capture would work independently and your own program would only read the results at a set read rate, for example 20KHz. Although not via sysfs.

Kind regards and all help appreciated,

Jonas

0 Kudos

2,024 Views
igorpadykov
NXP Employee
NXP Employee

Hi Jonas

in general one can also consider option with EIM connection. Using sysfs may be slow,

for reducing delays one can try to write small adc application in assembler.

Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

2,024 Views
jonasnyberg
Contributor III

Hi Igor,

Thanks for your reply. Yes I have noticed that sysfs is very slow. How about accessing the memory/registers that holds the values directly from my C++ program?

Or does a sysfs read first trigger a read command and then store the value and then read it? I read somewhere that the current driver doesn't support continous read.

Br,

Jonas

0 Kudos