Best way to interface the AD7691 ADC to AT91SAM9RL ARM processor running Linux

Hello,

I would like to interface five AD7691 18-bit ADCs to a Atmel ARM processor (AT91SAM9RL) running the Linux operating system. The processor will be clocked at a speed of ~200 MHz, and I would like to sample the ADCs at a rate of 10 kHz.

The AD7691 ADC

formatting link
has a conversion pin CNV. A conversion is triggered by a rising pulse on this pin. The data is then read from each ADC using an SPI interface.

The AT91SAM9RL processor has only one SPI bus without FIFO.

What is the best way to do this using a Linux kernel driver? Two likely scenarios:

(1) All ADCs are wired to the SPI bus, and each ADC has a /CS pin wired to the AT91SAM9RL processor. The AT91SAM9RL toggles the CNV pin so that the ADCs are read at a 10 kHz sampling rate. The AT91SAM9RL then selects each /CS pin of the five ADCs, and reads each slave in order.

BUT, does writing a Linux kernel driver guarantee that the processor can toggle the CNV pin and then read the five ADCs in sequential order at a rate of 10kHz?

(2) The AD7691 can be daisy chained. Would it be possible to daisy-chain all five ADCs and then read the data as a big (18 bit)(5) =

90 bit transfer?

What type of kernel driver would be most appropriate, and what would be the best way to wire up the ADCs if I am to use a kernel driver for the AD7691 ADC running on a AT91SAM9RL Linux board?

Nicholas

Reply to
Nicholas Kinar
Loading thread data ...

The AT91SAM9RL has DMA as well. Each SPI channel has it's own PDC.

--
Stef    (remove caps, dashes and .invalid from e-mail address to reply by mail)

Understanding is always the understanding of a smaller problem
in relation to a bigger problem.
		-- P.D. Ouspensky
Reply to
Stef

Some of the ST ARM chips might be more suitable. They have double-buffered DMA.

I suspect you're going to need that.

Reply to
Clifford Heath

Thanks, Clifford; I will take a look at the ST ARM parts: they look interesting.

Nicholas

Reply to
Nicholas Kinar

DMA.

Thanks, Stef; DMA does indeed look like the way to go with these transfers.

Nicholas

Reply to
Nicholas Kinar

The last time I faced a challenge like that, I put an MSP430 CPU in between the ARM CPU and the ADC. The MSP430 handled all the ADC timng and SPI transfers, and sent async serial packets to the ARM. However, I didn't have quite as high a data rate. If you followed the same method, you would need 10,000 x 5 x 3 bytes per second, or 15,000 bytes/sec. To do that, you would need to use 230KB async comms. OTOH, with the DMA capability of the ARM and good LINUX serial port drivers, you wouldn't have to do any kernal programming----just suck up the data from the serial port.

Do you think you'll be able to get true 18-bit resolution from your ADC when it's directly connected to the CPU? If noise limits to you 16 bits or less, you could cut the data transfer requirements by 1/3 by using only the 16 MSBs. (It's generally difficult to program 18-bit SPI transfers unless you have something like the Moto Queued Serial Peripheral. Been there, done that--- it was never much fun.)

Mark Borgerson

Reply to
Mark Borgerson

Thanks for your response, Mark! This sounds really interesting, and it is a very neat solution. So suppose that we have the following setup. The five ADCs are connected as SPI slaves to a small microcontoller master such as an ATmega. Each ADC has a separate /CS connected to the ATmega. The ATmega handles the sampling of data at a rate of 10 kHz. Each sample is simply sent over the serial port to the ARM. A user-space program is used to read the serial port.

Alternately, perhaps a small FPGA could be used to read all of the ADCs at the same time. The FPGA might also be able to read the ADCs in daisy-chain mode. Then the FPGA could send the data over the serial port to the ARM.

Could the ATmega or the FPGA be connected to a GPIO on the ARM chip, and after every sample, the GPIO could be toggled to send an interrupt? I am concerned about using synchronous transfers since I don't know if a Linux kernel driver could handle this. Async transfers seem to be a much better way to do this.

Could the ATmega or the FPGA be connected to the ARM SPI bus, and the transfers sent in an synchronous fashion? I may have to write a kernel driver for this, but I don't know if the Linux kernel can handle the interrupt that quickly.

Sure, 16 MSBs would probably be good as well; I would have to experiment and see if this fits my data requirements. Could I do 18 bit transfers with a small micro such as the ATmega? IMHO, 18-bit transfers would probably be simpler with a FPGA.

Thanks, Mark.

Reply to
Nicholas Kinar

Linux kernal questions are way over my head.

I think an FPGA might be simpler if you absolutely need 18-bit transfers. On a small micro, you could transfer 18 bits from the ADC, but would only need to send two 8-bit bytes async to the Linux machine if 16-bit resolution is adequate.

On one system where I used an MSP430 and two ADCs, I bypassed the MSP430 hardware SPI, and connected each SPI output on the ADC to a separate MSP430 input pin. I then used bit-banging on output pins to clock both ADCs at once. After each clock, the input port was read and the appropriate bit shifted into a data word for each ADC. (Actually, for each ADC channel, since I was using

4-channel ADCs and using more output pins to select the appropriate channel.)

While the bit-banging wasn't as fast as hardware SPI, it allowed be to do whatever number of bits I required and collect pairs of channels simultaneously. In your case, you would have to bit-bang 18 clocks and roll in 5 data words, then set up a DMA async serial output for 10 or 15 bytes once every

100microseconds.

That could be challenging, even on a 25MHz MSP430. It should easily be possible on an FPGA if you are not worried about power consumption. I was running my whole 8 channels x 100Hz system on about 15-20mA at 3.3V. If you're running a Linux system, I doubt that a few hundred extra milliwatts are much of a problem!

One think I always worry about with async transfers on Linux systems is the possibility of internal buffering delays-- especially if there are hardware FIFOs on the UART ports. It may be that when you read the serial data has only a loose relationship to when the data actually arrived at the serial port. Not the best of conditions if you have to evaluate the data for real-time control---especially at high data rates.

Mark Borgerson

Reply to
Mark Borgerson

Thanks, Mark; this makes a lot of sense to me, and I think that the best way to do this would be to use a small uP such as the MSP430. For me, this seems to be the best way to go, especially for the smaller sampling rates that I am working with.

Nicholas

Reply to
Nicholas Kinar

According to the AD7691 data sheet, there is no problem shifting more than

18 bits, so it should be possible to use h/w spi for shifting 3 bytes and then manipulate in s/w.

--------------------------------------- Posted through

formatting link

Reply to
RockyG

That sounds good, Robert; thank you for pointing this out in the context of my application.

Nicholas

Reply to
Nicholas Kinar
2010-11-03 01:40, Nicholas Kinar skrev:

I think you may want to look at the AT91SAM9G45 instead of the AT91SAM9RL64. This part has dual SPI, and on top of that, each USART has a an SPI Master mode for a total of 6 SPI Masters. It also supports DDR-2 memories which will make the memory subsystem much cheaper than that of the SAM9RL64 which will have to use SDRAM.

An alternative , probably better, is to use the SSC. This should allow you to use the daisy chain mode of the ADCs on a single serial interface with DMA support.

The rising edge of the TX framesync is connected to CNV, The RX Framesync, can be connected to the SPI chip selects

Best Regards Ulf Samuelsson

Reply to
Ulf Samuelsson

Thanks, Ulf; this is greatly appreciated, and I have to admit that the AT91SAM9G45 part looks very interesting!

I also like the idea of daisy-chaining the ADCs and connecting them all to the SSC bus.

Looking again at the AD7691 datasheet

formatting link
how might I wire up the daisy-chained ADCs to the SSC bus?

Pages 22-23 of the AD7691 datasheet shows the connections required for daisy-chain mode. Taking into consideration your recommendation, I think that the following pin mapping table would work.

TABLE:

Processor SSC bus ==> ADC

------------------------------ TX-FRAMESYNC ==> CNV RX ==> SDO of last ADC CLK ==> CLK

Could I use a GPIO as an interrupt (IRQ), as shown on page 23 of the AD7691 datasheet?

How would I set up a Linux driver to take a sample at a 1 kHz rate? I suppose that TX-FRAMESYNC would be toggled and then allowed to stay high while the data would be read from the ADCs. The data would then be transferred directly into memory using DMA.

Is there support for this type of operation in the Linux kernel? Is it possible to read arbitrary-length words from the SSC bus?

Nicholas

Reply to
Nicholas Kinar

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.