Using ADC on AT91SAM9G20 based products

Table of Contents


This HOW-TO covers a general description getting userspace access to ADC on PortuxG20/Stamp9G20/NanosG20 using our provided driver.

The driver was tested on these kernels:

  • 2.6.29
  • 2.6.31
  • 2.6.35

Sources are attached to this document.


The AT91SAM9G20 CPU provides an ADC with various features supported by the driver.

  • Up to four channels
  • Selectable resolution of eight or ten bit
  • Single measurements
  • Data streaming

Applying the patch

In order to use the driver kernel sources need to be patched. This patch adds ADC driver's source.

patch -p1 -F3 < ../at91-adc.110419.patch

This command is assumed to be executed from $(KERNELDIR) with the patch located in the parent directory.


The driver uses Atmel's AT32/AT91 Timer/Counter Library. It is necessary to enable "Device Drivers"->"Misc devices"->"AT32/AT91 Timer/Counter Library" and "Device Drivers"->"Misc devices"->"Embedded ADC on AT91" in menuconfig. Asure that "Device Drivers"->"Misc devices"->"TC Block Clocksource" and "Kernel Features"->"High Resolution Timer Support" are both disabled. Now re-compile the kernel. The driver can be compiled as module (using option 'M' to enable the driver in menuconfig) that can be loaded via insmod. Source and kernel object are located at $(KERNELDIR)/drivers/misc/at91-adc.c and $(KERNELDIR)/drivers/misc/at91-adc.ko.

Note: A description of configuring and compiling the linux kernel can be found in our linux guide.

ADC's sysfs interface

After the driver is loaded (-> insmod) the directory /sys/class/misc/adc containing a set of sysfs-files is added to your system. These files are used to configure the driver and to make single value measurements.

File Description
chn_enable Enables/disables channel n (0 -> disable; 1 -> enable)
chn_value Read a single value from channel n (Note: pure decimal value - no conversion according to Vref)
highres Selects resolution (0 -> 8bit; 1 -> 10bit)
frequency Set trigger frequency for data streaming in Hz

All files are at least readable. The behaviour of frequency differs a bit when read back. This is described in section "Data streaming".

Data streaming

Besides reading single values through the sysfs interface, the driver provides a data streaming mode what was the main intention of this work. The key to this feature is using the "normal" device file /dev/adc instead of /sys/class/misc/adc/chn_value. Once this device file is opened the driver starts continuous measurements on all enabled channels with respect to selected resolution and frequency. A read from /dev/adc returns binary data from alternating channels. A stream of four channels at eight bit would look like:

<8-bit value ch0><8-bit value ch1><8-bit value ch2><8-bit value ch3><8-bit value ch0>...

Ten bit measurements result in streams with 16 bit channel data. Streaming is stopped when the device is closed.

Internally, measurements are triggered by TC0 and transferred using PDC - thus sparing CPU resources. The device uses a double buffering technique and supports blocking as well as non-blocking read and poll.

Note: The driver's sysfs files become read-only as long as the device is open. During this time /sys/class/misc/adc/frequency provides information about the real frequency generated by TC0. Maximum thoughput is limited by conversion time, meaning trigger frequency is not equal to output frequency in all cases.

Sample program

The attached sample program test.c demonstrates the use of ADC driver in blocking (with and without poll) or non-blocking manner. It converts streamed data to CSV output that can be stored on disk or network. The program first makes use of sysfs to determine selected channels and data size then starts measurement, converts data and prints some statistics to stderr. IO method, output format and data destination can be controlled at command line.

./test format dest
format = int/hex
dest = file to store data

Originally used as test program during driver development it offers some features that won't be expected in a sample program. So, IO method can be chosen according to file's name that is executed.

  • ./test - program uses blocking reads without poll
  • ./test_poll - program uses blocking reads with poll
  • ./test_nb - program uses non-blocking reads

Just set up symbolic links to ./test to test these input methods.

test.c3.68 KB
at91-adc.110419.patch19.29 KB