I wanted to learn how to use SPI on the Beaglebone Black (BBB) and I found a well done post that Ben Martin did to get me started. As a novice linux user, there were a number of hurdles I had to overcome to get everything working:
1. Understand enough about the Device Tree Compiler overlay process to enable SPI0 on the BBB.
2. Installing and using shared libraries (told you I am a linux novice)
One of the reasons I liked Ben’s article, is that it had an arduino example for the 25LC512 and I wanted to start in an environment that I knew well to test the devices to be certain they were working before moving on to the BBB and using C. I have used the Adafruit webide tools and python on the BBB before and I could have elected to use their python SPI libraries from their BBIO package, but I wanted to learn more about using C on the BBB.
After validating the 25LC512 on the arduino (wiring and code on Ben’s post), it was time to move onto the BBB.
First some basics – I did all this on the v2013.06 version of angstrom. I used this version as I am also learning about the PRU on the BBB and needed this version to install PyPRUSS from Elias Bakken from hipstercircuits.com. So for clarity, here is the output of lsb_release -a
Distributor ID: Angstrom
Description: Angstrom GNU/Linux v2013.06 (Core edition)
Codename: Core edition
I’ll bet everything related to SPI only in this post would run just fine on the standard Angstrom images, but I did not test that. Next step is to enable the SPI0 device. There is much written on how to build a DTS file that gets compiled to a DTBO file that actually gets loaded to enable a device – here are the straight forward steps to enable:
root@beaglebone: export CATS=/sys/devices/bone_capemgr.*/slots
root@beaglebone: cd /lib/firmware
root@beaglebone/lib/firmware: echo BB-SPIDEV0 > $SLOTS
root@beaglebone/lib/firmware: cat $SLOTS
4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G
5: ff:P-O-L Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI
8: ff:P-O-L Override Board Name,00A0,Override Manuf,BB-SPIDEV0
The BB-SPIDEV0-00A0.dts and the corresponding BB-SPIDEV0-00A0.dtbo file were included in my Angstrom distro. Note that in the echo command above, only BB-SPIDEV0 was specified, so the “-00A0” is assumed.
On to the next step! The C example on Ben’s site was not a complete version of the code – he later sent me the complete file, but in the interim, I found a library that simplified the interface to the spidev driver called libsoc by Jack Mitchell. The spi_test.c example in that repo is for a Micron 25LC640, which is not as recent a device as the 25LC512, but similar enough to allow me to enhace it swiftly for my purposes. Getting this library installed was somewhat of a challenge for this linux newbie, but Jack was quite patient in answering my questions. The following details my installation – might help some other newbie!
At first I attempted to clone the repo by:
root@beaglebone get clone git://github.com/jackmitch/libsoc
but I ran into ssl problems. Two solutions to this:
1) git config –global http.sslVerify false (quick and dirty, but not secure)
2) use wget versus git clone
There is a third solution which is to really fix the ssl key situation…little things like this is why debian on the Raspberry Pi seems so much easier.
Anyway, now that the library is downloaded:
At this point the library is installed in /usr/local/lib and the header files in /usr/local/include. I did not know that these shared library paths are not in the standard search paths (/usr/lib and /usr/include), so I eventually ended up with this for the compile command:
gcc -Wall -I /usr/local/include -L /usr/local/lib -lsoc gpio_test.c -o gpio
The GPIO-test program writes to and reading from a GPIO pin – a good test of whether libsoc was installed and working. But before I could run it, I had to do this export:
I discovered a very useful utility that is not installed on the BBB (but is on the Pi) – ldd (print shared library dependencies). It is easy to install:
opkg install LDD
So for instance, to check if all the libraries are defined for an executable:
libsoc.so.2 => /usr/local/lib/libsoc.so.2 (0xb6f7d000)
libc.so.6 => /lib/libc.so.6 (0xb6e42000)
libpthread.so.0 => /lib/libpthread.so.0 (0xb6e23000)
With confidence that libsoc was installed and I know how to use the shared libraries, let’s move on to testing the 25LC512. The source for this can be found at https://github.com/Maddox-zephyr/BBB-25LC512-Test
In a directory of your choice, create/get a copy of spi_25lc512x.c from the git repo.
Hook up the BBB to the 25LC512:
To compile, run, and examine the output of this program, simply:
root@bealebone gcc -Wall -I /usr/local/include -L /usr/local/lib -lsoc spi_25lc512x.c -o spi_25lc512
root@bealebone ./spi_25lc512 > output.spi
root@beaglebone more output.spi
But what about performance? A Saleae logic analyzer trace file and jpg are in the git repo. If you load the trace file into the Saleae application, you can examine the timings yourself. (I love this little tool!).
Here is a jpg of a one byte read, just after the chip is erased:
There are more jpgs of the logic analyzer traces in the repo.
What did I learn (beside remedial linux stuff)? SPI through libsoc can issue commands every ~100 usec (observed between 77 and 125 usec). Random 1 byte reads can complete every ~100 usec as well. 128 bytes can be transferred from the BBB to/from the 25LC512 in ~200 usec. A long block of sequential reads run at about 640 KB/s. Not bad for a $45 computer with a $2 serial flash chip!