iP Solutions has created a Serial Peripheral Interface (SPI) command-line utility for the Raspberry Pi (www.raspberrypi.org) platform. The utility, spincl, is licensed under Open Source GNU GPLv3 and is being offered by iP Solutions as a free download with source included.
Although a C library exists for the Broadcom bcm2835 with an SPI Application Programming Interface (API) among other things, there are reasons to have a command-line utility, which can be invoked from a shell command line or from within a script. A command-line utility allows easy testing and debugging of SPI slave devices without having to develop a C executable. Additionally, it provides a simple way for bash and python scripts to access the SPI master of the BCM2835 on Raspberry Pi. Although the raspian distribution provides GPIO libraries with the included python installation it doesn’t include an SPI library. spincl, on the other hand, can be invoked from a python (or bash) script.
Description
spincl is a command-line utility for executing SPI commands with the Broadcom bcm2835 from a shell command line (or script). The utility is based on the bcm2835 C library developed by Mike McCauley of Open System Consultants, http://www.open.com.au/mikem/bcm2835. It was built with version 1.17 of the bcm2835 library and tested on a Raspberry Pi single-board computer model B with an iP Solutions designed I/O board, which contains SPI accessible ADC and digital I/O expansion.
Invoking spincl results in a full-duplex SPI transfer. Options include the the SPI clock frequency, SPI Mode, chip select designation, and chip select polarity. Invoking spincl requires root privilege. If no command-line arguments are included or if there are any command-line argument errors, a “usage statement” will be printed on stdout similar to the Usage documentation below.
Usage
spincl [options] len [xmit bytes]
Invoking spincl results in a full-duplex SPI transfer of a specified number of bytes. Additionally, it can be used to set the appropriate GPIO pins to their respective SPI configurations or return them to GPIO input configuration. Options include the SPI clock frequency, SPI Mode, chip select designation, chip select polarity and an initialization option (spi_begin and spi_end).
spincl must be invoked with root privileges. However, as of version 1.3.0, although the make install target included in the Makefile installs spincl with a root owner, it also sets the suid bit so that users other than root may invoke spincl without a sudo prefix.
The following are the options, which must be a single letter preceded by a ‘-’ and followed by another character:
- –ix where x is the SPI init option, b[egin] or e[nd]. The begin option must be executed before any transfer can happen. It may optionally be included with a transfer. The end option will return the SPI pins to GPIO inputs. It may also optionally be included with a transfer.
- –mx where x is the SPI mode, 0, 1, 2, or 3
- –cx where x is the exponent of 2 of the clock divider. Allowed values are 0 through 15. Valid clock divider values are powers of 2. Corresponding frequencies are specified in bcm2835.h.
- –sx where x is 0 (CS0), 1 (CS1), 2 (CS1&CS2), or 3 (None)
- –px where x is chip select polarity, 0(LOW) or 1(HIGH)
len: The number of bytes to be transmitted and received (full duplex).
xmit bytes: The bytes to be transmitted if specified. If none are specified, 0s will be transmitted, which may be the case when only the received data is relevant.
Examples
Use spincl to just intialize the SPI pins: spincl –ib
Use spincl to intialize the SPI pins and read three bytes (note xmit bytes are not specified). Mode is 2, clock frequency is 15.625Mhz (see bcm2835.h), chip select is 0, and polarity is active low: spincl –ib –m2 –c4 –s0 –p0 3
Use spincl to transmit 2 bytes (specified) and read back 2 bytes, which may or may not be relevant. Mode is 1, clock frequency is 7.8125MHz, chip select is 1, and polarity is active high. Note that no initialization has been specified so SPI pins must have been previously initialized: spincl –m1 –c5 –s1 –p1 2 0x5c 0x13
Use spincl to read two byte with mode 3, clock frequency of 15.625Mhz, and no chip select (done by user some other way). When the SPI tranfer has been completed, the SPI pins will be returned to GPIO inputs: spincl –ie –m3 –c4 –s3 2
Use spincl to just return the SPI pins to GPIO inputs: spincl –ie
Build
Of course the spincl executable will work as is. However, if you want to make edits to the source, a Makefile is included to rebuild the executable. The Makefile assumes that the bcm2835 library has been installed. In other words, bcm2835.h is in /usr/local/include and libbcm2835.a is in /usr/local/lib. To “make” the executable, type make at the command-line prompt from the spincl directory. Again, the version of the bcm2835 library that was used to build the executable included in the download is 1.17. You may wish to try building spincl with the most current version. An example “install” target is included in the Makefile, which installs spincl in /opt/bin with root ownership and group with appropriate privileges, including setting the suid bit. Edit them as required for your application.
Get Free Download
Click here to download latest update of spincl.tar.gz Download
Place the tarball file in the desired directory and then execute:
- tar –xzvf spincl.tar.gz (spincl_1_3_1.tar.gz as of 7/31/13)
to get the expanded source directory.
Updates
- Version 1.3.0, 5/19/24:
- Bug Fix: A bug in the way the number of trasmit bytes was calculated was fixed. Previously, if the total byte length of the transfer was greater than the number of specified xmit bytes then an attempt to access command-line arguments beyond the number available would occur, which causes a segmentation fault.
- suid bit is now set in the install target of Makefile.
- Version 1.3.1, 6/25/13:
- This version was built with the bcm2835-1.25 library. All previous versions were built with bcm2835-17.
- This version was tested on 2013-02-09 raspian wheezy. The 2012-10-28 raspian wheezy was used for all previous versions.
iP Solutions in no way warrants or guarantees correctness of the downloaded code or that it’s bug-free.
Thank you for this useful utility! Do you have plan to improve this utility to run it without root privilege?
Thank you Bill for your question. I had not considered the option of running the utility without root privilege because generally an embedded application that needs to access kernel resources needs to have root privilege. In this case, the SPI core on the bcm2835 chip is programmed by it’s registers that are memory mapped with very specific hardware addresses, which can only be accessed by kernel (device driver) code. The driver in this case is /dev/mem.
You might be able to create a “work-around” for this, but it would go against the “Linux privilege model”. I should also say that most embedded applications run as root. That’s not to say that there isn’t a role for user’s with non-root privilege on embedded systems. For example, I have a user (developer) on my primary Raspberry Pi development system that owns all the source code, etc. Also, you might want users with different levels of access to various types of data/information, etc.
I hope this was useful.
Thank you Gary for explain to me in detail. I’m a newbie to embedded Linux, and doesn’t have much experience to device driver or peripheral control programming. I could fully understand your explanation. I just feel curious that the utility “gpio” coming with “wiringPi” doesn’t require me to “sudo” first, and I think maybe this useful utility could have such feature. Anyway, thank you for your great job!
Bill, I have not used “wiringPi”, but I checked it out. There are a couple of points made by the creator, which speak to the issue:
1. “The gpio command is designed to be installed as a setuid program and called by a normal user without using the sudo command (or logging in as root).“
2. The gpio utility supports GPIO exports to /sys/class/gpio.
The first technique (setuid) can just as easily be done with spincl. Simply use chmod to set the bit:
chmod +s /path/spincl.
Or edit the “install” target in the Makefile to set the permissions as 4755 instead of 755:
sudo chmod 4755 /opt/bin/spincl.
I should point out that using setuid is consistent with my point about root privileges. In other words, because spincl is owned by root and the setuid bit transfers the owner’s privileges to the process that is executing spincl, then that user has root privileges for that process.
The second technique (/sys/class/gpio) is an embedded Linux method of transferring GPIO resources from kernel space to user space. I don’t know if there is any equivalent for SPI.
If you need users other than root to use spincl (I would be cautious about this), then your best bet is to set the ‘s’ bit (technique 1 above).