summaryrefslogtreecommitdiff
path: root/hw/rpi6lowpan.mdwn
blob: 284f8e6a49a184619e3b9d110eff50984f42633c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# 6LoWPAN on a Raspberry Pi

The aim is to get [6LoWPAN][1] running on a Raspberry Pi using a
[Raspberry Pi 802.15.4 radio from openlabs][2] (based on the Atmel
at86rf233) so we can later use it as a e.g. border router.

[[!img rpiradio.jpg size="x150" alt="Raspberry Pi with 802.15.4 radio"]]

The default Raspberry Pi kernel lacks support for recent
[wpan-tools][3]. So we cross build a custom
built kernel via tftp.

In the following we assume the Raspberry Pi is at IP address 192.168.1.2 and
does DHCP during boot.

This is mostly a combination of information from different sites like
[linux-wpan][3], [openlabs][4] and [eLinux.org][5]. For details head over to
these sites. They have more details and less errors.

The source code of this page is available here:

    https://honk.sigxcpu.org/gitweb/?p=piki.git;a=summary

Send fixes.

## Setup the build environment and the RPi
Since the kernel build would take a long time on the Raspberry Pi we're using a
Debian System to crossbuild the kernel.

### Prepare cross toolchain for Debian Jessie + Sid
If you're running a RPi 2 you should be able to use the armhf
toolchain provided by Debian already.

    $ dpkg --add-architecture armhf
    $ apt-get update
    $ apt-get install make ncurses-dev gcc-arm-linux-gnueabihf build-essential

    $ arm-linux-gnueabihf-gcc -v
    Using built-in specs.
    COLLECT_GCC=arm-linux-gnueabihf-gcc
    COLLECT_LTO_WRAPPER=/usr/lib/gcc/arm-linux-gnueabihf/4.9/lto-wrapper
    Target: arm-linux-gnueabihf
    Configured with: ../src/configure -v --with-pkgversion=' 4.9.2-10' --with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs --enable-languages=c,c++,fortran --prefix=/usr --program-suffix=-4.9 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.9 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libitm --disable-libquadmath --enable-plugin --with-system-zlib --enable-multiarch --disable-sjlj-exceptions --with-arch=armv7-a --with-fpu=vfpv3-d16 --with-float=hard --with-mode=thumb --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=arm-linux-gnueabihf --program-prefix=arm-linux-gnueabihf-
    Thread model: posix
    gcc version 4.9.2 ( 4.9.2-10)

I don't have a Model 2 yet so I we have to grab the toolchain externally.

### Linaro
For the Raspberry Pi 1B and 1B+ use the Linaro toolchain:

    $ cd ~
    $ git clone https://github.com/raspberrypi/tools
    $ export PATH=~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin:$PATH

If you clone to another location be sure to adjusts the PATHs below too.

### The Linaro toolchain is 32bit and 64bit
Lots of the examples are using the 32bit one so lets use this too:

    $ apt-get install lib32stdc++6 lib32z1
    $ arm-linux-gnueabihf-gcc -v
    Using built-in specs.
    COLLECT_GCC=arm-linux-gnueabihf-gcc
    COLLECT_LTO_WRAPPER=/home/agx/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/../libexec/gcc/arm-linux-gnueabihf/4.8.3/lto-wrapper
    Target: arm-linux-gnueabihf
    Configured with: /cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/src/gcc-linaro-4.8-2014.01/configure --build=i686-build_pc-linux-gnu --host=i686-build_pc-linux-gnu --target=arm-linux-gnueabihf --prefix=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/install --with-sysroot=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/install/arm-linux-gnueabihf/libc --enable-languages=c,c++,fortran --disable-multilib --enable-multiarch --with-arch=armv6 --with-tune=arm1176jz-s --with-fpu=vfp --with-float=hard --with-pkgversion='crosstool-NG linaro-1.13.1-4.8-2014.01 - Linaro GCC 2013.11' --with-bugurl=https://bugs.launchpad.net/gcc-linaro --enable-__cxa_atexit --enable-libmudflap --enable-libgomp --enable-libssp --with-gmp=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static --with-mpfr=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static --with-mpc=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static --with-isl=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static --with-cloog=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static --with-libelf=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/.build/arm-linux-gnueabihf/build/static --enable-threads=posix --disable-libstdcxx-pch --enable-linker-build-id --enable-plugin --enable-gold --with-local-prefix=/cbuild/slaves/oorts/crosstool-ng/builds/arm-linux-gnueabihf-raspbian-linux/install/arm-linux-gnueabihf/libc --enable-c99 --enable-long-long --with-float=hard
    Thread model: posix
    gcc version 4.8.3 20140106 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2014.01 - Linaro GCC 2013.11)

### Crossbuild an upstream kernel for the RPi
For 6LoWPAN the bluetooth-next tree is a good starting point since it
contains the latest WPAN code (as of 4.0 you can also use Linus Tree for
basic support):

    $ git clone --depth=1 git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git
    $ export PATH=~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin:$PATH
    $ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2835_defconfig
    $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- chrt -i 0 make -j 4

#### On the tftp server
Move the necessary files to the tftp server (${TFT_IP} being the address of your tftp server):

    $ TFTP_IP=192.168.1.1
    $ scp bluetooth-next/arch/arm/boot/zImage ${TFTP_IP}:/tftpboot/rpi.img
    $ scp bluetooth-next/arch/arm/boot/dts/bcm2835-rpi-b-plus.dtb ${TFTP_IP}:/tftpboot/

If you're using another PI model copy the corresponding device tree (dtb) file.

### U-Boot
We want to boot the kernel using U-Boot so we can conveniently swap out kernels using TFTP.
This is mostly copied from [http://elinux.org/RPi_U-Boot](http://elinux.org/RPi_U-Boot) .

#### On the build host
Crossbuild U-Boot

    $ git clone --depth=1 git://git.denx.de/u-boot.git
    $ export PATH=~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin:$PATH
    $ export CROSS_COMPILE=~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-
    $ export USE_PRIVATE_LIBGCC=yes
	$ cd u-boot
    $ make rpi_defconfig
    $ make -j4 -s

#### On the RPi
Now configure the RPi to use the just built U-Boot (${PI_IP} being the
address of your Raspberry Pi). First on copy U-Boot to the Pi:

    $ PI_IP=192.168.1.2
    $ scp u-boot.bin root@${PI_IP}:/boot/u-boot.bin

and on the Raspberry Pi boot it by default:

    $ echo "kernel=u-boot.bin" >> /boot/config.txt
    $ poweroff

#### First Boot
(Again mostly from  http://elinux.org/RPi_U-Boot). Attach to the serial
console of your rpi:

    $ screen /dev/ttyUSB0 115200

This assumes you're using a USB-serial adapter that shows up as
*/dev/ttyUSB0*.  Then power on the RPi and once U-Boot starts do a

    $ setenv fdtfile bcm2835-rpi-b-plus.dtb
    $ setenv bootargs earlyprintk console=ttyAMA0 console=tty1 root=/dev/mmcblk0p2 rootwait
    $ usb start
    $ dhcp ${kernel_addr_r} rpi.img
    $ tftp ${fdt_addr_r} ${fdtfile}
    $ bootz ${kernel_addr_r} - ${fdt_addr_r}

#### Automate the boot
Copy the above commands into a file called *boot.src* and do a

    sudo apt-get install uboot-mkimage
    mkimage -A arm -O linux -T script -C none -n boot.scr -d boot.scr boot.scr.uimg

move that to /boot on your Raspberry Pi. Booting will from now on
happen automatically.

## 6LoWPAN
Now that we can quickly change and build kernels lets move to the 6LoWPAN part.

### Configuring the kernel and patching the DTS
In order to enable support for the at86rf233 and 802.15.14 radio we
need to change some kernel configuration. Since the board is connected
vie SPI we change the DTS so it gets properly detected. This is
readily done in my wpan-next (based on Alexanders repo) git repo which
you can add to the *bluetooth-next* repo you alread cloned above:

    $ git remote add agx git://github.com/agx/linux-wpan-next.git
    $ git fetch rpi-6lowpan
    $ git checkout -b rpi-6lowpan -b agx/rpi-6lowpan

Now lets rebuild DTS and kernel

    $ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2835_defconfig
    $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- chrt -i 0 make -j 4
    $ ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make dtbs

Transfer the files to the TFTP server again as described above.

### Build the linux-wpan tools
Head over to your RPi. We build the wpan-tools there since they're small:

    $ git clone https://github.com/linux-wpan/wpan-tools
    $ sudo apt-get install automake autotools-dev libltdl-dev libnl-genl-3-dev
	$ cd wpan-tools && ./autogen.sh && ./configure && make

Now we have all the tools:

    $ src/iwpan list
    wpan_phy phy0
    supported channels:
            page 0: 11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26
            current_page: 0
            current_channel: 13
            cca_mode: 1
            tx_power: 0

Make sure there's no ifplugd that brings the interface up. Kill it,
if it's there. Then make sure the interface is down, set a pan_id and
and add create the 6LoWPAN interface:

    $ kill $(ps awux | grep "[i]fplugd.*wpan0" | awk '{print $2}')
    $ ifconfig wpan0 | grep -qs UP && ifconfig wpan0 down
    $ src/iwpan dev wpan0 set pan_id 0xbeef
    $ ip link add link wpan0 name lowpan0 type lowpan
    $ ifconfig wpan0 up
    $ ifconfig lowpan0 up

You can now (hopefully) ping the other device:

    $ ping6 fe80::f836:9287:905c:a684%lowpan0
    PING fe80::f836:9287:905c:a684(fe80::f836:9287:905c:a684) from fe80::cb23:b779:742d:4fd2 lowpan0: 56 data bytes
    64 bytes from fe80::f836:9287:905c:a684: icmp_seq=4 ttl=64 time=16.6 ms
    64 bytes from fe80::f836:9287:905c:a684: icmp_seq=11 ttl=64 time=30.6 ms
    64 bytes from fe80::f836:9287:905c:a684: icmp_seq=12 ttl=64 time=16.3 ms
    --- fe80::f836:9287:905c:a684 ping statistics ---
    67 packets transmitted, 8 received, 88% packet loss, time 66025ms

The packet loss reduces when moving the devices closer together. In order to permanently
disable ifplugd you can edit */etc/default/ifplugd*.

Upstream info on wpan-tools is at http://wpan.cakelab.org/

[1]: https://en.wikipedia.org/wiki/6LoWPAN
[2]: http://openlabs.co/store/Raspberry-Pi-802.15.4-radio
[3]: http://wpan.cakelab.org/
[4]: http://openlabs.co/
[5]: http://elinux.org/