Default ADC configuration by Linux drivers

I am using a BeagleBone Black Wireless.

When reading an analog sensor using AIN0 with PRU0 with code written in C, we have started to see a DC offset that drifts up when the program starts to read the sensor voltage and remains steady throughout program execution. However, when we read this same sensor on the same channel using code written in C and executed on the ARM under Linux, we do not experience this drift. We’ve dug through all our custom electronics, which have not been changed, and have not found a hardware cause for this.

I am not a Linux expert and not experienced at all in DTO or kernel particulars but I found a descriptive file (not sure if its an overlay or a kernel driver) that sets the Open Delay to 0x98, SampleDelay to 0x0, averaging to 16 and channels to 8 for the ADC. We only have three steps and use three channels and accept the defaults on the Open Delay and Sample Delay with the PRU code.

If I wanted to have the Linux / ARM side change the ADC configuration to match how the PRU configures the ADC, how do I do this? Is there a primer I can use to learn how to do this safely?

Here’s the particulars of our configuration.

sudo /opt/scripts/tools/

dogtag:[ Debian Buster IoT Image 2021-02-15]
bootloader:[eMMC-(default)]:[/dev/mmcblk1]:[U-Boot SPL 2019.04-00002-gc9b3922522 (Aug 24 2020 - 16:42:18 -0500)]:[location: dd MBR]
bootloader:[eMMC-(default)]:[/dev/mmcblk1]:[U-Boot 2019.04-00002-gc9b3922522]:[location: dd MBR]
UBOOT: Booted Device-Tree:[am335x-boneblack-uboot-univ.dts]
UBOOT: Loaded Overlay:[AM335X-PRU-RPROC-4-19-TI-00A0.kernel]
UBOOT: Loaded Overlay:[BB-ADC-00A0.kernel]
UBOOT: Loaded Overlay:[BB-BONE-eMMC1-01-00A0.kernel]
/boot/uEnv.txt Settings:
pkg check: to individually upgrade run: [sudo apt install --only-upgrade <pkg>]
groups:[debian : debian adm kmem dialout cdrom floppy audio dip video plugdev users systemd-journal input bluetooth netdev i2c gpio admin spi iio docker tisdk weston-launch xenomai cloud9ide pwm eqep remoteproc]
cmdline:[console=ttyO0,115200n8 bone_capemgr.uboot_capemgr_enabled=1 root=/dev/mmcblk1p1 ro rootfstype=ext4 rootwait coherent_pool=1M net.ifnames=0 lpj=1990656 rng_core.default_quality=100 quiet]
dmesg | grep remote
[   94.869351] remoteproc remoteproc0: wkup_m3 is available
[   94.903950] remoteproc remoteproc0: powering up wkup_m3
[   94.903986] remoteproc remoteproc0: Booting fw image am335x-pm-firmware.elf, size 217148
[   94.904292] remoteproc remoteproc0: remote processor wkup_m3 is now up
[   97.324082] remoteproc remoteproc1: is available
[   97.326433] remoteproc remoteproc2: is available
dmesg | grep pru
[   97.324082] remoteproc remoteproc1: is available
[   97.324253] pru-rproc PRU rproc node pru@4a334000 probed successfully
[   97.326433] remoteproc remoteproc2: is available
[   97.326622] pru-rproc PRU rproc node pru@4a338000 probed successfully
dmesg | grep pinctrl-single
[    1.027460] pinctrl-single 44e10800.pinmux: 142 pins, size 568
dmesg | grep gpio-of-helper
[    1.040967] gpio-of-helper ocp:cape-universal: ready
Bus 001 Device 002: ID 0bda:c811 Realtek Semiconductor Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

1 Like


Are you using the librobotcontrol library?


P.S. The reason I ask…

  1. It shows.
  2. There are a bunch of ideas that do not match.
  3. and w/ Debian, no guarantee

The issue seems that you are using a lot of tasks, I have no clue how many pins you are allocating, in systemd that may or may not prevent or help you. Of course, I have no clue as to what you are doing but…

There is a PRU Cookbook w/ some hints.

i am not using the librobotcontrol library. Until recently, we didn’t have any motion to control and now that we do, our mechatronics guy, to save some time, used Arduinos.

We do use quite a few GPIOs with the PRU and ARM. Our prototype has an ARM program and PRU0 program. We don’t use PRU1 - yet.

I am very familiar with the PRUCookbook. It has helped me immensely.

We’re working on an autonomous agricultural field system. Patent-pending.

1 Like

Okay…and Good Enough,

You seem to have librobotcontrol listed in your packages. Now, w/ a separate board that has the same kernel, image, and u-boot, try to disable librobotcontrol w/: sudo systemctl disable librobotcontrol.service

I do not know exactly the service that the system package is using right now. Maybe give some output on: ls -la /etc/systemd/system/*

The issue is this idea to me so far w/out knowing everything…

  1. You are either using too many total milliwatts, e.g. meaning too many pins allocated at once during a use case in time…
  2. LibRobotControl is “harvesting” some pins you need in the long run… ADC, RPROC, and others…
  3. or and this may be a kicker, the PRU (only one) is overloaded w/ too many bits.

So, say you are utilizing a similar set up w/ another dummy board that you do not mind breaking compatibility, test it on it.

Of course, it needs the am335x or SiP from Octavo Systems on it…

I really hate saying this idea but…

The kernel and Buster image picked may be coinciding w/ one another in a negative way. Buster was 4.14.x I thought. I cannot be sure, i.e. as I have not been using it lately. It has been since four to five years back.


P.S. But for real, if you are not using it, stop it w/ systemctl to test and then start it back before rebooting on the dummy board to not break it. Getting logs in b/t sessions of starting and stopping will provide some key limelight too.

If any of this makes sense, okay. If it does not, I am sorry. I will try to be more technical.

The default driver is from the iio stack… ti_am335x_adc.c « adc « iio « drivers - kernel/git/torvalds/linux.git - Linux kernel source tree

The recommend defaults and tunning options, are well documented in this overlay: src/arm/overlays/BB-ADC-00A0.dts · v5.10.x-ti-unified · / BeagleBoard-DeviceTrees · GitLab


@RobertCNelson ,

He is using the 4.19.x kernel. Does this still apply?


it’s just a dpkg check to report on version installed… nothing to worry about…

1 Like

the internal of the iio/adc are the same, going way back to 3.8.x, as they are actual hardware knobs users can play with… They existed in the first version of the driver going way back… @zmatt spent a good amount of timing documenting these knobs…


1 Like

Nice…I was unaware.


P.S. I thought people would change the SS in time as most things temper or mature. @WalterCEden, can this source help you? Say you are using C/C++ instead of Python3 like below, it may be easy for you to change. I found the below source here: Sensors — BeagleBoard Documentation

pin = "0"


the driver got fixes and enhancements… but even in 4.19.x it was pretty mature.

1 Like

I made a snippet from the BeagleBone Cookbook.


@RobertCNelson , I appreciate the education. I knew very little of Linux in the beginning, i.e. '91. I was kicking soccer balls on stick-a-burrow fields. Ouch.

1 Like

that’s a documented part of the abi going back to 2.6.35: sysfs-bus-iio « testing « ABI « Documentation - kernel/git/torvalds/linux.git - Linux kernel source tree

why would that change?


I appreciate the good info you’ve supplied. We’ve been using 4.19 for around 18 months to 2 years I think. It’s our goto at this prototyping stage. I just have not had time to move up to Bullseye but hope to this fall.
In case it helps, here’s the output from systemd-analyze

debian@beaglebone:/sys/firmware/devicetree/base/chosen/overlays$ systemd-analyze blame
         46.957s generic-board-startup.service
         41.820s dev-mmcblk1p1.device
          4.374s loadcpufreq.service
          3.885s nginx.service
          3.619s systemd-udev-trigger.service
          2.312s networking.service
          1.861s ssh.service
          1.585s systemd-logind.service
          1.513s systemd-journald.service
          1.332s wpa_supplicant.service
          1.312s systemd-timesyncd.service
          1.293s connman.service
          1.114s dnsmasq.service
          1.077s avahi-daemon.service
           929ms cpufrequtils.service
           816ms systemd-user-sessions.service
           763ms rsyslog.service
           602ms fake-hwclock.service
           578ms kmod-static-nodes.service
           578ms systemd-sysusers.service
           554ms systemd-random-seed.service
           554ms keyboard-setup.service
           528ms dev-mqueue.mount
           515ms systemd-modules-load.service
           491ms systemd-remount-fs.service
           470ms systemd-udevd.service
           469ms systemd-update-utmp.service
           464ms systemd-tmpfiles-setup.service
           434ms systemd-journal-flush.service
           419ms systemd-sysctl.service
           376ms systemd-tmpfiles-setup-dev.service
           353ms sys-fs-fuse-connections.mount
           341ms sys-kernel-debug.mount
           301ms sys-kernel-config.mount
           212ms console-setup.service
           207ms systemd-update-utmp-runlevel.service
           126ms systemd-tmpfiles-clean.service
           122ms ifupdown-pre.service
            89ms proc-sys-fs-binfmt_misc.mount
            85ms cloud9.service

Not to change the subject, but I would really like to improve our boot-up time by trimming unused stuff out of here.

1 Like

This is very similar to what I do in C to use the ADC with code running on the ARM. I just haven’t found a way to adjust any of the settings. For example, I’d rather have 4 averages, and 3 steps in one-shot mode and then trigger them.


// define file handle to read analog input
		  FILE* fAIN_0 = fopen("/sys/bus/iio/devices/iio:device0/in_voltage0_raw", "r");
		  fread(&AIN_0_str, 6, 1, fAIN_0);
		  AIN_0_fl = atof(AIN_0_str);
		  mvolts_AIN_0 = AIN_0_fl/4096*1.8;

kick out cloud9 if you do not need it. I think there are no longer any people actively pursuing the tech. as a service (AWS).

Anyway, that is only if you are not using it. There was once a person that built a machine w/ a quick boot time. Now, was it in Buster, I cannot tell you. I cannot remember. I think maybe late Buster or early Bullseye (10/11) of Debian Distros, Bootlin had their hand in making a good boot time… I will try to track it down.


You want analog reads to handle output too? I mean…read from ADC, transfer the ADC reads to output, and then whatever?


@RobertCNelson This is a great link. Thanks. I recognize some of the labels and this is useful to help know what some of the more obscure ones mean.

I skimmed it, did some searches in the doc, and didn’t come up with anything that lets me set any of the parameters for the ADC, like steps or channels to read. I only need 3 steps and 3 channels. Does this mean that it isn’t ‘natively’ supported to do this on the ARM side? If so, can you point me to info on how to do it? Am I going to have to resort to bit banging to do it?


in most cases you can just remove that, this was one of the big things removed in our Bullseye images… (it did all the usb0/usb-cdc/usb-flash configurations, Debian bulleye’s version of systemd added usb-gadget trigger)…


yeap, that’s right here… src/arm/overlays/BB-ADC-00A0.dts · v5.10.x-ti-unified · / BeagleBoard-DeviceTrees · GitLab so you just need to update your overlay UBOOT: Loaded Overlay:[BB-ADC-00A0.kernel] … with what functions you want…

there should be an original version of that file located in this sub-directory…


For example: voodoo@bbai64-02:/opt/source/dtb-5.10-ti$ (then it’s a simple, edit, make ; sudo make install )