Mr_Blonde Posted April 17, 2017 Posted April 17, 2017 (edited) Hey there,I am having trouble with SPI on my Banana Pro. I am trying to access the SPI interface via WiringPI (the Lemaker Banana Pro version). But whenever I try to access it, it tells me: Unable to open SPI device: No such file or directory The message is correct, as there are no /dev/spi* files present. The question is: How do I get them?(according to http://linux-sunxi.org/Linux_mainlining_effort#Status_Matrix it should be available since 3.15)For the 3.4.x, one had to load modules (spidev, etc.) but this doesn't seem to work for 4.9.x. There is a 'spidev' module which loads fine (according to lsmod) but with no recognizable outcome. Is there anything special I have to load/enable/etc.? Unformtunately I didn't find anything usefull on the web regarding this topic. Which either means, it is working for everyone else or I do not know what to look for. :-(Any help is appriciated!This is my welcome string with OS and kernel version: Welcome to ARMBIAN 5.25 stable Debian GNU/Linux 8 (jessie) 4.9.12-sunxi PS: This is a cross-post from the Lemaker forum - no answer over there so far, however. -------- Thanks to zador.blood.stained I was able to enable SPI/SPIDEV for the mainline kernel (4.10.). For people with the same problem: This post contains a working device tree blob file (.dtb) which needs to be put into /boot/dtb folder. Additionally, an overlays=bananapro needs to be added to /boot/armbianEnv.txt Post containing compiled device tree blob Edited April 21, 2017 by Mr_Blonde Solved remark added
martinayotte Posted April 17, 2017 Posted April 17, 2017 The fact that you are seeing spidev in lsmod doesn't mean nothing wrong occured. Check the kernel logs with "dmesg | grep spidev" 1
zador.blood.stained Posted April 17, 2017 Posted April 17, 2017 Device Tree modifications are currently required to enable SPIdev on stable Armbian images with mainline kernel. 1
Mr_Blonde Posted April 19, 2017 Author Posted April 19, 2017 Thanks for your response! I found this wiki entry regarding overlays: https://docs.armbian.com/User-Guide_Allwinner_overlays/ However, for the Banana Pro there is no nightly build and an update to the current development kernel (4.10) did not bring overlays with it. :-( Does that mean I have to setup my own build environment? Since I am not familiar with overlays, device trees, etc. Wouldn't it be easier for me to "simply" configure the kernel with SPI support build in and compile it on the device instead of setting up a complete build environment (acknowledging that the build will take quit some time on the ARM board)?
zador.blood.stained Posted April 19, 2017 Posted April 19, 2017 I specifically said "modifications" because overlays require some work to apply on current stable builds. You still can edit the DT manually (without recompiling the whole kernel or setting up a build environment), there were some posts here related to it. The trickiest part will be adding pinctrl configuration (by label or phandle), I'm not sure if it was described or documented here.
Mr_Blonde Posted April 20, 2017 Author Posted April 20, 2017 Thanks to your comments, I looked a bit further into this. As a first step, I disassembled/decompiled the appropriate device tree blob: dtc -I dtb -O dts /boot/dtb-4.10.0-sunxi/sun7i-a20-bananapro.dtb > sun7i-a20-bananapro.dts Then I tried to figure out how to modify it in order to get SPI and SPIDEV to work. That's, however, where I got stuck. :-( I read http://linux-sunxi.org/SPIdev but couldn't make much out of it since it seems that the device tree entries are very specific for each board. For me it seams that SPI0 is already enabled: soc@01c00000 { spi@01c05000 { compatible = "allwinner,sun4i-a10-spi"; reg = <0x1c05000 0x1000>; interrupts = <0x0 0xa 0x4>; clocks = <0x2 0x14 0x20>; clock-names = "ahb", "mod"; dmas = <0x1f 0x1 0x1b 0x1f 0x1 0x1a>; dma-names = "rx", "tx"; status = "okay"; #address-cells = <0x1>; #size-cells = <0x0>; pinctrl-names = "default"; pinctrl-0 = <0x21 0x22 0x23>; }; }; and a ls /sys/class/spi_master/spi32766/ device of_node power statistics subsystem uevent seems to confirm that there is "something". The neighboring spidev folder is empty, though. There are pin definitions for the spi0 and chip select (+ for spi1) as well: soc@01c00000 { pinctrl@01c20800 { spi0@0 { allwinner,pins = "PI11", "PI12", "PI13"; allwinner,function = "spi0"; allwinner,drive = <0x0>; allwinner,pull = <0x0>; linux,phandle = <0x21>; phandle = <0x21>; }; spi0_cs0@0 { allwinner,pins = "PI10"; allwinner,function = "spi0"; allwinner,drive = <0x0>; allwinner,pull = <0x0>; linux,phandle = <0x22>; phandle = <0x22>; }; spi0_cs1@0 { allwinner,pins = "PI14"; allwinner,function = "spi0"; allwinner,drive = <0x0>; allwinner,pull = <0x0>; linux,phandle = <0x23>; phandle = <0x23>; }; }; }; What is missing is a mentioning of spidev, however. So my guess is that I have to add it somewhere. The question is how and where. The two examples on http://linux-sunxi.org/SPIdev do not shed much light on this - at least for me. :-( Has someone already done it for the Banana Pro (A20) boards? In case not, is there a more generic description out there on how to configure/write the device tree? Furthermore: What is next after adding spidev and compiling the device tree? Is having an entry in armbianEnv.txt such as: overlays=bananapro enough?
zador.blood.stained Posted April 20, 2017 Posted April 20, 2017 34 minutes ago, Mr_Blonde said: The neighboring spidev folder is empty, though. You have to add spidev child node to the controller node spi@01c05000 { compatible = "allwinner,sun4i-a10-spi"; reg = <0x1c05000 0x1000>; interrupts = <0x0 0xa 0x4>; clocks = <0x2 0x14 0x20>; clock-names = "ahb", "mod"; dmas = <0x1f 0x1 0x1b 0x1f 0x1 0x1a>; dma-names = "rx", "tx"; status = "okay"; #address-cells = <0x1>; #size-cells = <0x0>; pinctrl-names = "default"; pinctrl-0 = <0x21 0x22 0x23>; spidev@0 { compatible = "spidev"; status = "okay"; reg = <0>; /* Chip select 0 */ spi-max-frequency = <1000000>; }; }; In the future it will be solved with DT overlays, but for now it's not implemented on the stable images. 1
zador.blood.stained Posted April 20, 2017 Posted April 20, 2017 41 minutes ago, Mr_Blonde said: Furthermore: What is next after adding spidev and compiling the device tree? You just have to replace the old file with your modified one. 1
Mr_Blonde Posted April 21, 2017 Author Posted April 21, 2017 It worked! :-) Thank you very much for your help! Attached are the .dts and compiled .dtb files for reference. I aslo added an alias in order to have proper /dev/spidev0.0 instead of an /dev/spi32755.0. Here is the corresponding .dts snipped: aliases { spi0 = "/soc@01c00000/spi@01c05000"; }; There is one strange thing though. I am using WiringPi on the device (the version from Lemaker) and on top a Java program with Pi4J library (which uses WiringPi to access the GPIOs). To give you some background: My program is getting some information and is then updating an eInk display via the SPI interface. In order to update the display I am reading some status bytes from it and sending a complete new image for each update. Before refreshing the display I am querying the display's internal temperature sensor. Sending the command to query the sensor is the very first byte my program is transmitting on the SPI bus. With the old legacy kernel, the program worked without any problems. Now, however, I get a java.io.IOException: Failed to write data to SPI channel: 0 exception. Subsequent writes on the SPI bus work nevertheless (and the display is refreshed properly). In order to track down the problem, I tried to get the eInk display info before retrieving the temperature (which is done by sending another command byte and waiting for the response). The result: Now, retrieving the display information causes the before-mentioned exception and reading the temperature sensor works. As an executive summary: I now have the problem that the very first write to the SPI bus fails with java.io.IOException: Failed to write data to SPI channel: 0 exception whenever I execute my program. All subsequent writes (and inherent reads on the bus) work like a charm. The weird thing is that its not only the very first bus access after a reboot but always when I execute my program. With the legacy kernel 3.4.x my code worked without this issue. Its a 'minor' issue but maybe some else has come across the same issue and can shed some light on this. Java code SPI init (via Pi4J library) PlatformManager.setPlatform(Platform.BANANAPRO); spi = SpiFactory.getInstance(SpiChannel.CS0, 1000000, // default spi speed 1 MHz SpiMode.MODE_0); // default spi mode 0 sun7i-a20-bananapro.dtb sun7i-a20-bananapro.dts
Holger Posted June 19, 2017 Posted June 19, 2017 Hello, thank you for supplying these great instructions! I confirm it is working, I got SPI running on Banana Pro with Kernel 4.9.32, following these steps on device tree blob and so on. But: There is strange system behaviour when using SPI and usleep or msleep or QThread::msleep()... SPI stops working when thread is suspended with sleep after or before SPI command Simplified example code: for (Adresse=1; Adresse<8; Adresse++) { SPI_RW(Adresse, 10); msleep(1); } This results in sometimes sending, sometimes not sending SPI-message, I checked that with an Oscilloscope. My code worked perfectly on Kernel 3.4.10! Could it be that SPI-Module and Thread-Timing access the same timer settings and overwrite them? Thanks!
Mr_Blonde Posted June 24, 2017 Author Posted June 24, 2017 Just a quick note: It also works with kernel 4.12.0 One either has to redo the changes or copy the old dtb file over to the new dtb-4.12.0-sunxi folder, though (which on the other hand shouldn't be very surprising).
Recommended Posts