3

I'm building a project using the MCP3914 8-channel analog front end (ie ADC) device connected to the Raspberry Pi's SPI peripheral.

The device has a continuous read mode where you request the value of one register then hold the CS low and it cycles through all of the registers, transmitting the value of each one, for as long as you hold CS low. I'd like to use this mode to continuously sample the values sampled by the ADC. Ideally, the transfer should be done with DMA, to keep CPU utilisation low. The SPI peripheral could write data into a circular buffer with the userspace either keeping up or losing data if it doesn't read it in time, or it could perhaps write to two buffers, passing each to a userspace program when it fills up and then switching to the other.

What are my options for implementing this? It looks like the spidev driver doesn't support reading more than about 4k from the device (1 page?). Also the documentation here points to a github project for DMA-enabled SPI, but the wiki for that project says that mainline now has DMA capability, with a link to the driver source code. So how do we do SPI DMA with the spidev driver on modern kernels?

Assuming that I can't use the spidev driver, I guess I'm stuck using the bcm2835 library to manipulate the peripheral directly. I don't know a lot about this - not even if it's going to be in user space or kernel space.

Can someone give (or point me to) some advice please?

1
  • I suspect the mainline driver has moved here. I'm trying to do something similar to what Tom describes. I have a homemade peripheral that generates data continuously, and I'd like to read it with DMA because I need to avoid the breaks in the stream that happen otherwise when the processor switches to another task. Still hunting for information on how to do this, but will post here if I manage to do anything! Dec 13, 2019 at 14:13

2 Answers 2

1

I believe the current Linux /dev/spidevx.y driver for the Pi supports DMA. I believe it automatically uses DMA if the transfer is over a certain size (below this size the overhead of setting up DMA does not save time).

I am afraid I know of no documentation other than the driver source code (available on github).

I am fairly sure it does not support buffering for continuous reads.

I'm sorry this is so vague but I have never looked at this in detail.

If the bits per second transferred is less than 500kbps you might be able to set up your own cyclic buffer (using a technique used to read multiple ADCs simultaneously).

0

A device driver isn't essential; I have posted several examples of user-mode DMA code, the first of these is here

With regard to the size limitation, the 'lite' DMA channels are limited to 64K (see the BCM2835 ARM Peripherals document for details), but there is normally at least 1 non-lite channel available that doesn't have this restriction.

You can find a project using DMA to stream data from an ADC here; it should be possible to adapt this for the MCP3914.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.