I wanted to use 1-wire temperature sensors (DS18B20) with my Cubietruck board, running Debian. The only page I could find documenting this is for the sunxi kernel, not the mainline kernel Debian uses. After a couple of hours of research I got it working, so here goes.
wiring
First you need to pick a GPIO pin to use for the 1-wire signal. The
Cubietruck's GPIO pins are
documented here,
and I chose to use pin PG8. Other pins should work as well, although
I originally tried to use PB17 and could not get it to work for an unknown
reason. I also tried to use PB18 but there was a conflict with something
else trying to use that same pin. To find a free pin,
cat /sys/kernel/debug/pinctrl/1c20800.pinctrl/pinmux-pins
and look for
a line like: "pin 200 (PG8): (MUX UNCLAIMED) (GPIO UNCLAIMED)"
Now wire the DS18B20 sensor up. With its flat side facing you, the left pin goes to ground, the center pin to PG8 (or whatever GPIO pin you selected), and the right pin goes to 3.3V. Don't forget to connect the necessary 4.7K ohm resistor between the center and right pins.
You can find plenty of videos showing how to wire up the DS18B20 on youtube, which typically also involve a quick config change to a Raspberry Pi running Raspbian to get it to see the sensor. With Debian it's unfortunately quite a lot more complicated, and so this blog post got kind of long.
configuration
We need to get the kernel to enable the GPIO pin. This seems like a really easy thing, but this is where it gets really annoying and painful.
You have to edit the Cubietruck's device tree. So apt-get source linux
and in there edit arch/arm/boot/dts/sun7i-a20-cubietruck.dts
In the root section ('/'), near the top, add this:
onewire_device {
compatible = "w1-gpio";
gpios = <&pio 6 8 GPIO_ACTIVE_HIGH>; /* PG8 */
pinctrl-names = "default";
pinctrl-0 = <&my_w1_pin>;
};
In the '&pio` section, add this:
my_w1_pin: my_w1_pin@0 {
allwinner,pins = "PG8";
allwinner,function = "gpio_in";
};
Note that if you used a different pin than PG8 you'll need to change that. The "pio 6 8" means letter G, pin 8. The 6 is because G is the 7th letter of the alphabet. I don't know where this is documented; I reverse engineered it from another example. Why this can't be hex, or octal, or symbolic names or anything sane, I don't know.
Now you'll need to compile the dts file into a dtb file. One way is to
configure the kernel and use its Makefile; I avoided that by
first sudo apt-get install device-tree-compiler
and then running,
in the top of the linux source tree:
cpp -nostdinc -I include -undef -x assembler-with-cpp \
./arch/arm/boot/dts/sun7i-a20-cubietruck.dts | \
dtc -O dtb -b 0 -o sun7i-a20-cubietruck.dtb -
You'll need to install that into /etc/flash-kernel/dtbs/sun7i-a20-cubietruck.dtb
on the cubietruck. Then run flash-kernel
to finish installing it.
use
Now reboot, and if all went well, it'll come up and the GPIO pin will finally be turned on:
# grep PG8 /sys/kernel/debug/pinctrl/1c20800.pinctrl/pinmux-pins
pin 200 (PG8): onewire_device 1c20800.pinctrl:200 function gpio_in group PG8
And if you picked a GPIO pin that works and got the sensor wired up
correctly, in /sys/bus/w1/devices/
there should be a subdirectory for the
sensor, using its unique ID. Here I have two sensors connected, which
1-wire makes easy to do, just hang them all off the same wire.. er wires.
root@honeybee:/sys/bus/w1/devices> ls
28-000008290227@ 28-000008645973@ w1_bus_master1@
root@honeybee:/sys/bus/w1/devices> cat *-*/w1_slave
f6 00 4b 46 7f ff 0a 10 d6 : crc=d6 YES
f6 00 4b 46 7f ff 0a 10 d6 t=15375
f6 00 4b 46 7f ff 0a 10 d6 : crc=d6 YES
f6 00 4b 46 7f ff 0a 10 d6 t=15375
So, it's 15.37 Celsius in my house. I need to go feed the fire, this took too long to get set up.
future work
Are you done at this point? I fear not entirely, because what happens when there's a kernel upgrade? If the device tree has changed in some way in the new kernel, you might need to update the modified device tree file. Or it might not boot properly or not work in some way.
With Raspbian, you don't need to modify the device tree. Instead it has support for device tree overlay files, which add some entries to the main device tree. The distribution includes a bunch of useful overlays, including one that enables GPIO pins. The Raspberry Pi's bootloader takes care of merging the main device tree and the selected overlays.
There are u-boot patches to do such merging, or the merging could be done
before reboot (by flash-kernel
perhaps), but apparently Debian's
device tree files are built without phandle based referencing needed for
that to work. (See http://elektranox.org/2017/05/0020-dt-overlays/)
There's also a kernel patch to let overlays be loaded on the fly using configfs. It seems to have been around for several years without being merged, for whatever reason, but would avoid this problem nicely if it ever did get merged.