SPI on beagle bone black and beagle bone black wireless

I’m posting this here hoping to save others some frustration/pain that I’ve gone through as a noobie trying to get SPI working on the beagle bone black wireless.

The documentation for this is a shambles currently, with conflicting and out of date information all over the internet.

So, for those who find this post via google, let me explain what’s going on and how we got to here. SPI on the BBB is actually really easy, it just may not seem like it.

Ok, for starters when you google this, you’ve probably found a bunch of information on dts, overlays, capemgr, slots, etc…

I’ll take a sec to explain the history of this first.

So, linux traditionally used kernel modules (drivers) for every piece of hardware that you might want to use. This strategy didn’t work very well when all these ARM devices like the beagle bone started showing up because there were so many devices with different configurations, and it really didn’t make sense to add all that to the kernel. As a solution to this, Linus came up with this idea for a level of abstraction called a device tree.

The device tree is basically a way to describe the mapping and purpose of physical hardware to the kernel. This is done via a ‘dts’ file, which is a source code file that lists the specific properties of the hardware. This source code file is compiled into a binary that the kernel can understand, a ‘dtb’ or ‘dtbo’ file. So, early on in beagle bone history, this was how things were done. There were lots of dts and dtbo files that were made for all sorts of different purposes, and you, as the user could swap these out depending on how you want pins configured. You can also create your own. This is where some of the older articles you see that have instructions about creating a dts file and compiling it to enable SPI come from.

Well, that whole thing was pretty spiffy, but there were some drawbacks. One, it wasn’t very approachable for new folks. You basically had to learn a new language and toolchain just to configure pins. While better than writing a kernel module, that still wasn’t great. Also, all of this configuration happened at boot time, so every time you wanted to make a change you had to reboot. This really doesn’t work well for a device where you want to be able to hot swap extension boards and reconfigure things at runtime. Third, this all happened in kernel space, which as an industry we try not to do. It’s better to keep as much as possible in user space.

To address those issues: enter the Cape Manager. The cape manager is a pretty fancy piece of kernel module software that has the ability to dynamically load and swap out device tree overlays, and the tools live in userspace. When you see instructions on the web about adding lines to uEnv.txt like:

optargs=quiet drm.debug=7 capemgr.enable_partno=BB-SPIDEV0

This is telling the cape manager to load the SPI device tree overlay at boot time. Everywhere you look on the internet, this is the recommended solution for enabling SPI on ‘current’ devices. But, it doesn’t work.

Why? Well, to explain that requires one more step.
Even though the cape manager is neat software from an engineering perspective, and really accomplished its goals well, it still leaves something to be desired from a new user perspective. Folks who are just getting into the whole maker scene are reasonably confused by all this.

To address that, some new software was created (which is enormously fancy), called universal io.

Basically what this is, is a device tree overlay that’s loaded by the cape manager at boot time that has the ability to dynamically configure all of the pins at runtime using a tool called config-pin.

You can see it and read more about it here: https://github.com/cdsteinkuehler/beaglebone-universal-io

So, with this utility all of the pins that aren’t reserved for HDMI can be hot configured by using the simple config-pin command, and this includes SPI!

So, finally after that long bit of history, here’s how you actually set up and use SPI on a new beagle bone black wireless with a current image:

#data out
config-pin P.18 spi
#clock out
config-pin P.22 spi

Rinse, repeat if you need other pins like CS, or MISO.

After days of learning all of the above, and figuring all this out, I’m finally able to see a beautiful output waveform on my oscope.

I hope this helps someone else new to all this!

Thanks for taking the time to post this summary.
— Graham

Why the repost ? Wasn’t it you who alread posted this exact same information 2 days ago ?

Hi William, I got a weird error on my original post, and I couldn’t find it anywhere, so I reposted it. If you can find the original, I’ll delete one. Thanks!

Switch from threads to list all in the Google groups interface.

But it’s email based on the back end, so you can’t change what you already emailed it to thousands of subscribers.


Hi Clayton, what you have written is correct and the Device Tree is a significant barrier to entry.
The Universal IO is a good solution to this, and I’ve had good luck with it while keeping in mind my requirements to manipulate the Device Tree have been minimal.

The Beagleboard is driven by the community, and it is a wonder such a complex piece of technology is accessible at all!
The Linux kernel has something like 8000 developers contributing, making it perhaps the largest engineering project in human history.
The complexity of this technology is breathtaking! I very much appreciate what the community has done and I have learned a great deal and also had fun.

In looking about, Github appears to be the de-facto standard for sharing information in electronic form, and the Beagleboard related stuff is there.
But not all of it, especially documentation, is located in several wiki pages. These pages are not reliable.

So what I am getting at, is that Github is an accepted means of publishing documentation, and you can get a public account for free.
If you could tidy up your post, and put it in publishable form, I think it would be a good contribution to the community.
As far as what “publishable form” means, that could be as simple as Markdown, or better yet a PDF file, which Github can display in the browser.

Just a suggestion, good luck with your projects and please let us know how it is going.


Just to be clear . . . The Hadron collider in Genva is the biggest engineering “feat” in the world . . .Involving over 10,000 scientists from over 100 countries, and I’m not sure how many engineers.

Passed that, it’s not surprising the Beaglebone works at all. For instance, you do realize that most of the packages, that you, I, or anyone else uses from Debian, actually comes from the Debian team Repo’s right ? Then all of the embedded subsystems such as spidev, and all that predate this specific hardware ?

So, the real surprise would be if the hardware DID NOT work.

Then you have many, many people, who are just part of this community, Or part of this community, as well as others. Of whom I’ll refrain of trying to name anyone, least I forget someone. I can think of at least one person who is constantly working in this community, and probably at least 10 others who contribute a bit here and there, As needed.

Additionally, I’ve been thinking this the whole time after this post, but . . . the information given here. Isn’t exactly the best. I wasn’t going to say anything, but now that I’m already posting . . However I can pretty much say with 99% certainty this is because of the lack of experience from the OP. spidev’s been around, and I happen to know someone who is very familiar with Linux, and got it working in a matter of minutes, from nothing. That is, to say. He was also new to the Beaglebone black, at that time. So . . .

By the way, for me the key to understanding device tree was not to read any of the garbage on the internet about it. But to actually go into several device tree files, then learning about each subsystem used. Experimenting, and all that. Plus I still don’t know everything, but do know enough to at least create my own overlay based off of existing overlays.

Hi William, if you could point to an easily discoverable source which says that Universal IO is available in the latest images and encouraged to be used, then you could be correct.
Being able to successfully manipulate the SOC multiplexer is fundamental to getting a Beagleboard project off the ground.

If there is no such info, which should be right at the top, then Clayton’s post is a pretty good version 1.0 guide for newbies.

That’s a great idea Greg, I’ll do that, thanks!

Ok, here’s the first draft: https://github.com/claytongulick/beagle_bone_black_spi/blob/master/README.md

Corrections and additions are welcome!

Nice! I will add this as a reference to my project documentation.

Regarding the fact that you have to run config-pin after each boot, you can add a section that the config-pin commands can be added
to whatever start-up configuration is most appropriate.

The way I am doing this currently is to simply list the commands in a text file like:

config-pin P8.30 pruout
config-pin P9.31 pruout

Then add this to the .bashrc file in the home directory:

source (path to the above file)

Then the configuration is done automatically!
Check this discussion for some other interesting info on Device Tree:


The impression I have gotten, and I could be wrong, is that adding or subtracting overlays at the command
line is a not guaranteed to work operation. The overlays should be reliably controlled via uEnv.txt and the eeprom.

Here is the thing.

The way things are right now, one could, but perhaps should not be editing
the first stage environment file. That is to say: /uEnv.txt. Instead we
could argue that "we" should be using /boot/uEnv.txt. In other words,
optargs. So from that perspective, this is outdated information, which will
definitely contribute to the confusion for new comers. Coming from a
different angle, the first stage environment file is definitely not newb
friendly and should be avoided. One simple typo, or mis-pressed key, and
the system will no longer boot. In addition to the above.

So, after that, there are multiple ways to load an overlay file. One of
which would be more consistent with using universal IO. Which is to use the
universal IO script 'config-pin'. So . . .

$ config-pin overlay <overlay file name>

Which also means this could be loaded about 3 different ways at boot
through rc.local, a cron job, or as a service.

Another thing of importance is that if your device tree overlay is not
stock, it won't load at boot, through the second stage environment file.
Robert wrote a script to remedy this issue. But basically you need to
inject your overlay binary into the initramfs. This script makes an
otherwise tedious job, very simple.

Anyway, if one were to examine the contents of /bootuEnv.txt, it would, or
at least should become very clear how it is expected to load an overlay
file at boot. There is an example for 3.8.x, and another for 4.x kernels.

As for me providing instructions as to how I believe this should be done
properly. Well I have not exactly used SPI on this platform, or any
embedded platform period. For this platform specifically because, in the
case of a gpio multiplexer, SPI would be the furthest thing from my mind.
Because it would tie up too many extra pins. Which if I'm using an expander
/ multiplexer . .. I must need pins. So, I would probably go for using one
of the already used I2C buses . . . Which I would say, at least from my
own perspective. Is much easier to deal with than spidev. Also do keep in
mind that I do have hands on with SPI, but only from a bare metal MCU
perspective. I do however believe I could set SPI up on this platform no
problem. Granted I do have ~4 years hands on with this platform . . .

So the point in short is this. While I do appreciate that Clayton was
trying to help others like himself who may have problems getting SPI
working on the beaglebone. In actuality the information provided by this
post is not exactly correct. Even though it works. Which I think will in
the end add the the confusion of beginners to the platform.

Maybe I'll write something up for 4.x myyself, as I get time, As I did buy
myself a logic analyzer. But there would be no guarantee as to when,
assuming even *if*.

I meant to say I’ve not used SPI on any embedded Linux platform. I do have plenty of experience with SPI on bare metal MCU’s.

So, if you think “ah this is confusing . . .” it does get worse.

The new future way( I suspect) to load overlays at boot will likely be through uboot. Robert has recently added this functionality into uboot, I’ve tested it, and it does seem to work great. But I think this is for 4.1.x kernels and above only. However, this pretty much renders the need to inject your overlays into the initramfs moot. It may also be a little faster, but I can not see it being hugely faster. It has been said however it will make other issues with various devices at boot - Better.

You can read about it some here: https://groups.google.com/forum/#!searchin/beagleboard/HERE$20THERE$20BE%7Csort:relevance/beagleboard/W0QPDee5u2s/c1cbhzN4FAAJ

Ok so here is the quick skinny( untested ) to setup spidev on kernel 4.x. By untested, I mean I have not actually tested the signal generated, or received by the device. I was reading however, there is a “spidev_test” bit of code you can use to test send / receive by shorting MISO to MOSI( I’m supposing at it’s the only way that makes sense ). However I want to read more about this code, I’ve not seen yet. Information is rather sparse from my source. Here: http://elinux.org/BeagleBone_Black_Enable_SPIDEV

I will say however that the information was rather plain, and easy for me to understand anyway. But I also know there are already pre-made overlays included with most, if not all images now days. Official images that is . . . But if you do need other pins than what’s used in these overlays. You’d have to write your own overlay, and include it in /lib/firmware. With that said, I’m not exactly sure how that works, or technically if it’s even possible. My understand of spidev is that it is a software only driver for SPI, but I’m not 100% sure if you need physical hardware to be used with spidev, or not. Anyway . . .

Test for already functioning spidev interfaces:
debian@beaglebone:~$ ls /dev |grep spi
Check which spidev overlays come with stock image:
debian@beaglebone:~$ ls /lib/firmware/ |grep SPI

Edit /boot/uEnv.txt to load chosen overlay at boot:
##BeagleBone Black: HDMI (Audio/Video) disabled:

The above requires a little extra explanation. enable_uboot_overlays=1 is required to enable uboot loading of overlays. The line after that loads the device tree board file I want loaded at boot. It disables both forms of HDMI. Which strictly speaking I’m not sure is necessary for the given overlay im loading. But is something I personally always do. Since I never use HDMI. dtb_overlay=/lib/firmware/BB-SPIDEV0-00A0.dtbo loads the overlay I want through uboot, at boot.

Rebot required to take effect:
debian@beaglebone:~$ sudo reboot

Test again for functioning spidev interfaces:
debian@beaglebone:~$ ls /dev |grep spi

Profit !

Do keep in mind that this is the very newest way to load overlays at boot. However, with that said, this would also work nearly exactly the same with the previous method with one exception. Instead of using:


You would use
. . .
##Example v4.1.x

Pretty straight forward, and it’s been this way a while now. There is one caveat however. If you’re loading a custom overlay( one not included with the stock image ), you need to inject it into the initramfs. This is done by. . .

debian@beaglebone:~$ cd /opt/scripts/tools/developers/
debian@beaglebone:/opt/scripts/tools/developers$ git pull
debian@beaglebone:/opt/scripts/tools/developers$ sudo ./update_initrd.sh

AFTER You make sure your custom overlay is located in /lib/firmware

Hi William, great inputs and perhaps we can ask Clayton to push these additional details to the repository.

There should be a clear delimiter between the current and experimental improvements.

I wonder if there is going to be a distinct cut-over to the revised Uboot process? Maybe too soon to determine.

Another thing:

  1. dtb-rebuilder

  2. bb.org-overlays

Perhaps not a newbie concern, as I think 1 and 2 above are at the intermediate level.
I think these should at least be mentioned as they are important bits for dealing with the Beagleboard Device Tree ecosystem.


Yeah, I dont know. For me, it’s all a moot point. The biggest hurdle to understanding devices on the beaglebone, is first understanding the hardware period. Then you need to understand the subsystems for each device type - On Linux. After that, device trees, and device tree overlays all start to make sense. Device tree files after all are only hardware descriptions.

Anyway, to answer your question, about universal IO. No I don’t have a problem with it at all. But at some point, you’ll realize that universal IO is a generic set of device tree overlays, with a tool(config-pin) to make pix muxing much simplier. e.g. an abstraction layer. At some point, you may actually find yourself not wanting to use it. For me, part of my nature is that I have to understand how things work, after which sometimes things may become redundant. . .

I have configured the pins for SPI 0 using the config-pin using the universal cape overlay, however I do not see any spi devices within my /dev/ folder. How do I access spi after I have muxed these pins at runtime?



Definitely a must read about SPI, however with the IoT image ( Debian 9.2 2017-10-10 4GB SD IoT ) as is I was not able to configure the pins. what I did and what I get:

$config-pin P9.18 spi
P9_18 pinmux file not found!
bash: /sys/devices/platform/ocp/ocpP9_18_pinmux/state: No such file or directory
Cannot write pinmux file: /sys/devices/platform/ocp/ocp

Can anyone know how to solve this issue?

Best regards

Nuno F.

sábado, 31 de Dezembro de 2016 às 19:23:13 UTC, Clayton Gulick escreveu: