Wireless Testbed based on Raspberry Pi
Sommaire
Project's frame
- Tutors : Franck Rousseau, Etienne Dublé
- Place : FabLab Ensimag
- Students : Florian Caruel, Benjamin Doiteaux,Benjamin Fallet, Clemence Filippi
Subject's description
Introduction
When it comes to sensor networks or distributed systems, tests take an important place. To fix the dysfunctions we need to deploy an architecture of test :
- a little infrastrcuture handmade allowing us to do a few tests. But this requires time and has to be deployed each time tests have to be done.
- a public infrastructure constituted of many nodes. But this kind of architecture is not directly accessible and implies a lack of flexibility (we can't modify the deployed equipment).
Therefore the purpose of this project is to conceive a software architecture which can resolve these problems. This architecture has to be cheap, easily reusable and adaptable for every kind of network tests.
Our architecture will support two kind of configuration :
- First scenario :
In this case, the nodes (Raspberry Pi boards) are connected through the filaire architecture to be configured. They boot on an Android OS and communicate between each other through the wifi network obtained with usb wifi keys. This configuration will be able to emulate a smartphones' network.
- Second scenario :
In this case, the nodes (Raspberry Pi boards) are used as a link to one or several boards MB851 connected through USB. The nodes allow us to monitor a network of sensors, the boards MB851 which used their radio 802.15.4 to communicate one to each other. The nodes will be able to launch a Linux OS. This scenario corresponds to standard experiments in the domain of sensors' networks.
Aims
- Given that, the aim of the project is to be able to choose the operating system, we have to :
- - Install a minimal bootloader on the SD cards of each Raspberry Pi.
- Select the 2nd OS to launch among :
- - An Android distribution adapted to our Raspberry Pi and our architecture, stored on the NFS server.
- - A Linux distribution adapted to our Raspberry and our architecture, stored on the NFS server, able to flash the MB851 boards and to communicate with them.
- Propose an application (in command lines and graphical) able to :
- - Start, restart and stop each board.
- - Select the OS to boot.
- - Get the IPs of each board, so that the user may take control of the boards.
Equipment required
Herebelow the equipment required for this project :
Material | Details |
---|---|
A switch |
with PoE (Power over Ethernet) functions |
Raspberry Pi boards |
... |
Ethernet PoE to 5V USB adaptors |
one for each Raspberry Pi board |
SD cards |
one for each Raspberry Pi board |
Ethernet and USB cables |
... |
One computer |
At least one computer for the DHCP, TFTP and NFS servers |
Tools installation
The configuration described here assumes that the main computer which will hold the DHCP, TFTP, and NFS servers, is connected to the switch with its interface eth0 with the @IP 192.168.0.1.
Folders setup
Creation of the mains folders which will be shared by TFTP and NFS with the RPi
$ sudo mkdir /tftpboot $ sudo mkdir /tftpboot/kernels $ sudo chmod -R 777 /tftpboot $ sudo chown -R nobody /tftpboot $ sudo mkdir /nfs
The architecture of the tftpboot folder will be the following :
/tftpboot /kernels kernel_Debian kernel_Android kernel_Gentoo kernel
where kernel is the kernel file which will be loaded by the RPi at boot.
Consequently to select an OS, you have to select one kernel from the kernels folder and then copy it to replace the kernel file.
This task will be automatically done by a java application given at the end of this page.
The NFS folder will contain the root filesystems of each OS which will be read by the RPi
/nfs /Debian /Gentoo /Android
Compilation tools
As the RPi is a tiny computer, the compilation of the kernels will be done on a more performant machine.
Installation of the cross-compiler :
We assume here that you are using Ubuntu.
$ sudo apt-get install gcc-arm-linux-gnueabi- make ncurses-dev
The cross-compiler prefix will be
$ export CCPREFIX=arm-linux-gnueabi-
Creation of the SD-Card
You can find here the .img of the card we used, Fichier:Card.img.zip
Simply copy it on a formatted card with this command :
$ sudo dd bs=4M if=<.img file> of=/dev/sdc
Assuming /dev/sdc is your card
The following lines explain how to re-create this card :
- The bootloader
The main constraint of this project was to use a read-only SD-Card on each Rpi. The chosen solution is to put on these cards a light bootloader, uBoot which is a bootloader commonly used on embedded systems.
The port for the Raspberry Pi of this loader has already been done and the instructions to install it can be found here : http://elinux.org/RPi_U-Boot.
We will use here the following uBoot script :
set autostart yes usb start dhcp bootm
Put it in a script.txt file and you'll be able to generate the boot.scr file to copy on the SD-Card via :
$ mkimage -A arm -T script -C none -d script.txt boot.scr
- Preparation of the SD-Card
Create a 32MB FAT32 partition on the card and copy the bootloader on it.
Edit cmdline.txt with the following line :
dwc_otg.lpm_enable=0 console=tty1 ip=dhcp
DHCP Server
In order to have an automatic IP attribution for each RPi, we will install a dhcp server on the main computer.
$ sudo apt-get install isc-dhcp-server
Then, create a dhcpd.conf file :
# allow network boot allow bootp; allow booting;
# Network Setup # Subnet 192.168.0.* subnet 192.168.0.0 netmask 255.255.255.0 { # Broadcast address option broadcast-address 192.168.0.255;
# IP range range 192.168.0.10 192.168.0.100;
# kernel file to load on the TFTP Server filename "kernel";
# TFTP Server next-server 192.168.0.1;
# Check if the IP is already used ping-check = 1;
# Static IP for the switch host netgear { hardware ethernet 00:28:c6:8e:05:87:5a; fixed-address 192.168.0.10; } }
To start the dhcp server, simply use
$ sudo dhcpd -cf dhcpd.conf eth0
where eth0 is the interface connected to the switch
You can stop it with
$ sudo killall dhcpd
TFTP Server
The TFTP (Trivial File Transfer Protocol) server shares the kernel image with the Raspberry Pi at boot.
We will use tftpd
$ sudo apt-get install tftpd
Its config file is /etc/xinetd.d/tftp, create it with these lines :
service tftp { protocol = udp port = 69 socket_type = dgram wait = yes user = nobody server = /usr/sbin/in.tftpd server_args = /tftpboot disable = no }
You can now start it with
$ sudo /etc/init.d/xinetd start
NFS Server
A NFS server is used to share different folders. Here we use it to share the files from our different OS: After starting, the kernel needs to use some files to boot the system, but those files can't all be stored on the SDcard. That's why the kernel is configured to search it on the nfs server.
- Install
To install a nfs server on your computer, you need to get this packages :
$ sudo apt-get install nfs-kernel-server nfs-common
- Configuration
Then you need to modify the file /etc/exports like this :
/nfs/Android 192.168.0.0/24(rw,sync,no_root_squash,no_subtree_check) /nfs/Debian 192.168.0.0/24(rw,sync,no_root_squash,no_subtree_check) /nfs/Gentoo 192.168.0.0/24(rw,sync,no_root_squash,no_subtree_check)
This specify which folders are shared for which ip address. The last element of each line gives the right the clients have.
- Start
The first time you want to start this server the shared folder have to be known by the server, that's why you need to load the exports. Then you can start it.
$ sudo service nfs-kernel-server reload $ sudo invoke-rc.d nfs-kernel-server restart
Boot sequence
The boot sequence will be the following :
- The RPi loads and executes the bootloader uBoot from the SD-Card.
- This loader gets an IP and the kernel filename to load from the DHCP information.
- The kernel is loaded from the TFTP server
- The cmdline is read from the kernel file and gives the root filesystem location (NFS Server).
- The filesystem is mounted via NFS and then the system is ready.
Nb: See the uBoot bug descibed below.
Installation of a system
- Assuming that you have already the root filesystem of the system you want to boot on the Raspberry Pi, put it in a subfolder of the /nfs directory. Use the cp -a command to preserve the access permissions of the files.
Note that you may have to change the /etc/fstab of the system to remove the mount of SD-Card partition at boot.
General kernel compilation instructions :
- You have to recompile the kernel, including the cmdline which contains the path to the root filesystem on the nfs server</br>
All the instruction can be found at this page http://elinux.org/RPi_Kernel_Compilation.
Remember that the cross-compiler prefix is
CCPREFIX=arm-linux-gnueabi-
- Once you have set up a config file to the compilation (as explained in the previous link), you have to define the cmdline, we'll use the config menu :
$ sudo make -j2 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- menuconfig
Go to the Boot Options menu and edit the cmdline (example is given below, depending of the OS kernel you are trying to compile)
- In this menu, also change Kernel command line type to Extend bootloader kernel arguments.
You can now compile the kernel in uImage format with
$ sudo make -j2 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- uImage
- Also check that the NFS Boot is enabled in the kernel options : File Systems/Networking File Systems/NFS Client Support
- Now get the uImage generated file from the arch/arm/boot subfolder of your kernel sources and copy it to your /tftpboot/kernels folder (you can rename it).
- Don't forget to also recompile the modules (as indicated at http://elinux.org/RPi_Kernel_Compilation)
Android
CyanogenMOD 7.2 RPI
Android is an adapted OS for smartphone but not for raspberry Pi, that's why we had to found an adapted version for raspberry and supporting Ethernet connection : CyanogenMOD 7.2 is an android based OS developed under the razdroid project. This system contains a module allowing the raspberry to connect to an Ethernet network running a dhcp server.
In order to recompile the kernel we downloaded the razdroid-kernel files.
The cmdline to use in the kernel configuration is :
console=ttyAMA0,115200 root=/dev/nfs rw nfsroot=192.168.0.1:/nfs/Android,nolock,wsize=1024,rsize=1024 rootdelay=2 init=init
SSH connection
To take control of the raspberry, a ssh server has to run on the different OS. For Debian sshd is launched by default, but for Android a specific application has to be installed. We downloaded SSHDroid.apk and configured it to be launched during startup and to take an ip address thanks to the dhcp.
Debian
Kernel compilation
The used files to recompile the kernel can be found here : Debian-kernel. It's important to note that the kernel version we used is the 3.6.y. The newer version 3.8.y doesn't work with our configuration. To compile the kernel we use the following commandline :
console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/nfs rw nfsroot=192.168.0.1:/nfs/Debian,vers=3 rootfstype=nfs rootwait
Flash the mb851 cards
In order to flash your mb851 cards through the Raspberry Pi, you will need to install serialdump and the stm32w flasher on the Raspberry. These applications can be found on this git in the folder tools. This git contains the contiki tools to compile your firmwares too.
- Serialdump
Serialdump is an application used to read and send serial data on an usb port. In order to use it on the raspberry you can compile the file serial.c on the raspberry using gcc :
$ gcc -o serial serialdump.c
Now, you can easily see the informations sent by the mb851 cards specifying the rate (b115200 corresponds to the baud rate) and the device.
$ ./serial -b115200 /dev/ttyACM0
- Stm32w_flasher
In the py_files folder you can find this program for linux written in python language. This uses different packages that have to be installed.
To install this you may need an internet connection which can be get with several methods :
Use a wifi key to connect to a wifi network.
Use a connected computer as a router :
On the PC
$ sudo iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o wlan0 -j MASQUERADE $ sudo sysctl -w net.ipv4.ip_forward=1
On the RPi
$ sudo route add default gw 192.168.0.1
Then you can install the different usefull packages
$ sudo apt-get install python-serial python-ftdi $ sudo apt-get install hal
- Interface_mb851
The Fichier:Main.java is a java application developped in order to control, from a PC, the flashing of mb851 cards connected to a raspberry Pi running Debian. This application opens a ssh connection to the raspberry with the specified IP adress and runs serialdump or stm32w_flasher depending on the selected options. This uses the jsch package. To run this application we built folder with specific path and name :
/NFS/Debian/contiki-stm32w/ #contains all the flashable .bin files ~/stm32w/ #contains serialdump ~/stm32w_flasher/py_files/ #contains stm32w_flasher
This application allows you to get the different informations from serialdump or stm32w_flasher back. Here is an example :
$ java Main Connexion [host] [options] [mb851 number] [file] host : Specify the ip address of the raspberry running Debian options : -f : flash the card -r : restart the card -t : recover traces for more options : use directly the flasher on the raspberry mb851 number : the card is associated to a specific device like ttyACM0 on the raspberry Just specify 0,1 ... file : only used for flashing a .bin file on the mb851. $ java Main 192.168.0.11 -r 0 INFO: STM32W flasher utility version 2.0.1b2-20130611 for Linux INFO: Starting application from address: 08000000 INFO: Done
You can find the source code here
Gentoo
Kernel compilation
The kernel is the same than the Debian's one.
We used this command line :
console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 root=/dev/nfs nfsroot=192.168.0.1:/nfs/Gentoo,vers=3 rootfstype=nfs elevator=deadline rootwait
SSH connexion
By default there is no ssh server running on Gentoo. We need to configure it directly on the Raspberry PI once :
You need to modify the ./etc/conf.d/net :
auto_eth0="true" config_eth0="null"
You need to enable networking on boot
root # cd /etc/init.d/ root # ln -s net.lo net.eth0 root # rc-config start net.eth0 root # rc-update add net.eth0 boot
You need to enable SSH Daemon
root # rc-update add sshd default root # /etc/init.d/sshd start
Application to monitor the Raspberry Pi boards
In this part, you will find an application java that we have implemented in order to facilitate the monitoring of the boards.
The application, named Command Center, allows the user to :
- - start / restart or stop the Raspberry Pi with a remote access.
- - get the Ip addresses of each board in order to interact with the boards.
This application has been implemented with a switch Netgear GS110TP.
Installation and use
Here you can find the zip file to download, and unzip on your computer :
Fichier:Command center.tar.gz or here
Go to the unzip folder, and compile with :
$ ant
To use it you have to run the command in the folder /bin :
$ java -jar interface.jar @IP Path option
with the arguments :
- @IP : Ip address of the switch
- PATH : Path to the TFTP directory, (it is named tftpboot in our case)
- option :
- -g : for the graphical interface
- -p <PortNumber> <DesiredState> <kernelName>
The DesiredState value can be 0 to stop the board, or 1 to start/restart the board.
The application can be launched in a command line mode or with a graphical interface.
The command lines mode
You can choose to launch the same OS on the 8 ports of the switch (PortNumber=0), or to launch a different OS on each port, as you can see below :
$ java -jar interface.jar @IP PATH -p 0 1 kernelName #same OS for the 8 boards $ java -jar interface.jar @IP PATH -p 1 1 kernelName -p 2 1 kernelName2 -p 3 1 kernelName3 ... #OS for each board
You can also get all the Ip addresses of the boards with the command :
$ java -jar interface.jar @IP PATH -all
For more details, you can show the help menu with the command :
$ java -jar interface.jar -h
Warning !!
If you are not on the computer which contains the TFTP directory, you will have to mount a remote directory on your local files system.
First check that nfs-common is installed on your computer, then enter the command :
$ sudo mount -t nfs @IP_of_the_computer_with_TFTP_directory:/Path_to_the_directory
Graphical interface
To use the application in the graphical mode, launch the command :
$ java -jar interface.jar @IP PATH -g
The Ip addresses are directly visible on the interface in front of the corresponding port of the switch and are refreshed every 5 seconds.
You can make a series of start/restart instructions, no matter the port, they will be executed one after the others. The port which is actually being processed is represented in yellow with written "loading", the ports which are waiting to be processed are also represented in yellow with written "waiting". In case you press a stop button it cancels all the waiting and running actions previously selected on the corresponding port and turns this port OFF.
For other switches
- This application has been implemented for Netgear switches but you can easily use it with another switch.
For that, you have to know the OID (Object identifier) of the table which controls the PoE (Power over Ethernet) of the ports, and the OID of the MAC addresses' table.
If you encounter difficulties in finding these OID's, you can use the software, MachineEngine_opUtils installed on a Windows virtual machine.
Then you have to change these OIDs in the source code of the class snmp.java.
Link to the source code
Issues (updated by E.Duble on june 18, 2013)
Wifi on Android
We tried to make the wifi operational on Android, by adding to the Rapsberry Pi a TP-Link TL-WN722N USB wifi dongle. Unfortunately there is no driver adapted natively on our Android distribution, so we added the ATH9K driver to the kernel and the firmware to the Android filesystem, but the wifi device is unrecognised by the system. We didn't have the time to find a proper solution and to perfectly understand how the system recognizes the device.
uBoot bug
A bug in the uBoot loader prevents it to directly get its DHCP IP (the network card driver seems bugged and the ethernet interface doesn't react until it receives any paquet). The solution is to do a broadcast ping on the network from another computer (for example the DHCP server), to wake up the RPi's network card.
Electrical ground issues
We had problems with electrical ground when connecting several equipments. There may be a problem with our home-made cables.
Cmdline embedded in the kernel image
The fact of having to specify the command line in the kernel image is not convenient, but we did not manage to make it work in any other way.
References
- Raspberry Pi website
- Help on ubuntu
- uBoot
http://www.denx.de/wiki/U-Boot
- Port of uBoot to RPi and boot of FreeBSD over network
- Help on uBoot use and kernel compilation for the RPi
- Porting android to the RPi
http://blogs.arm.com/software-enablement/498-from-zero-to-boot-porting-android-to-your-arm-platform/
- Guide to add wifi drivers on android
http://nagaraj-embedded.blogspot.fr/2011/02/guide-on-adding-wifi-drivers-on-android.html
http://blog.linuxconsulting.ro/2010/04/porting-wifi-drivers-to-android.html
- OIDs viewer
http://www.oidview.com/mibs/2/md-2-1.html
- Javadoc of the SNMP Package used in the application command_center
http://gicl.cs.drexel.edu/people/sevy/snmp/docs/index.html
- Javadoc of the jsch version 0.1.50 used in the application interface_mb851