Unlike most of my posts on this blog, the title of this post is neither clever nor funny. I'm feeling serious today. Why? I have a Rev B BeagleBone Black (BBB) and I have a love / hate relationship with it. And I suspect I'm not the only one.
|It's Not Me - It's You|
On the other hand, I hate that the 'Bone can be such a bastard to get working to its full potential. One problem is the Imagination Technologies SGX530 graphics core. This company is open-source hostile, and their closed-source graphics binary blob works only with certain kernels. All attempts to reverse-engineer an SGX driver have unfortunately failed. The Raspberry Pi has both more powerful graphics hardware and Broadcom is (amazingly) supporting the development of an open source driver. Incidentally, the upcoming Beagleboard-X15 will also have an SGX graphics core in it, and they will not be getting my money for this reason alone. Huge win for the Pi here.
The other problem I've had is with getting wifi going. One dongle was crashing the kernel. I wasn't the only one having problems, either. I spent a ridiculous amount of time on this in the fall with no luck. I thought the best way to fix the problem was to just drive over the 'Bone with my car and get a Pi.
But I'm stubborn. I've got some time over the Christmas break and I thought I'd give it one more shot. Amazingly, I seem to have something working using the Jessie snapshot I got from here named BBB-eMMC-flasher-debian-jessie-lxqt-armhf-2014-12-19-2gb.img.xz and running kernel 3.14.26-ti-r42. I also learned a bit about systemd along the way. Systemd is fairly new to Debian, and that fact makes a lot of the wireless tutorials out there obsolete. So how did I get wifi working on the Beaglebone Black with systemd? Read on, McDuff...
First of all, get the latest Jessie snapshot from the link above and flash it to the eMMC (flash) memory on the 'Bone. I'm not going to go into the details of doing that, because lots of other people have. That is what Google is for.
OK, so you've flashed the 'Bone with the Jessie image and want to get wireless networking going. I'm going under the assumption that you have console access to the 'Bone, either via a USB to Serial connection or SSH over a hard-wired connection. No fancy Graphical User Interface stuff for me.
Next thing to know is that a lot of wifi dongles need some kind of firmware loaded into them. My TP-Link TL-WN722N already has its firmware on the image linked above (from the ath9k_htc package) so no need to download anything in this case just yet. Other dongles like those based on the ZD1211 or RaLink chipsets will need you to install a firmware package with the old "apt-get update; apt-get install... " dance. Here, the dmesg command and good ole' Google are your friend, helping you to figure out what you need.
Now you've got a 'Bone with a dongle plugged in and its firmware loading up. After that, the thing that trips people up is that recent kernels "soft block" (disable) things like wifi and bluetooth by default. A program called rfkill is necessary to enable them. rfkill is part of the image above (and because I politely asked Robert C. Nelson to put it in) so you should be good to go without having to download something over a hardwired ethernet connection first.
Let's kick things off by checking to see if the wifi is blocked, and enable it if it is.
root@beaglebone:~# rfkill list wifiGood start. "Soft blocked" changed from "yes" to "no" after we unblocked it.
0: phy0: Wireless LAN
Soft blocked: yesHard blocked: noroot@beaglebone:~# rfkill unblock wifi
root@beaglebone:~# rfkill list wifi
0: phy0: Wireless LAN
Soft blocked: noHard blocked: no
Next thing we need to do is bring the wifi interface up using the ip command. Note a couple things. First, Blogger hates me. The square brackets below are supposed to be angle brackets, but the Blogger editor gets confused when you switch back and forth between "Compose" mode and "HTML" mode (and yes, I tried coding in the HTML entities and no, that didn't work).
Before getting into that, how do we know the name of our wireless interface? Assuming your dongle is plugged in, do...
root@beaglebone:~# ip linkThere we go. My dongle is wlan1 and I'll be using that in the examples that follow. I'll also strip out other interfaces in the output going forward. Numbers I'd rather you didn't see have been replaced by "xx".
1: lo: [LOOPBACK,UP,LOWER_UP] mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:002: eth0: [NO-CARRIER,BROADCAST,MULTICAST,UP] mtu 1500 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff3: can0: [NOARP,ECHO] mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
link/can4: can1: [NOARP,ECHO] mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
link/can5: wlan1: [BROADCAST,MULTICAST] mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
Now let's bring the wlan1 interface up and check its status.
root@beaglebone:~# ip link set wlan1 upSee how the status changes from [ BROADCAST,MULTICAST ] to [ NO-CARRIER,BROADCAST, MULTICAST,UP ] once the link is up?
root@beaglebone:~# ip link
5: wlan1: [ NO-CARRIER,BROADCAST,MULTICAST,UP ] mtu 1500 qdisc mq state DOWN mode DEFAULT group default qlen 1000
link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
The next thing we'll do is associate the dongle to a wireless router. This example is for the connection to my router that is wide open. If yours is not open or not WEP encrypted, you'll need to do something different like bringing wpa_supplicant to the party (or just skip ahead to the automatic stuff below). My router connection is named Abby_Slow, so you'll have to substitute the name of your access point below. The really important thing to note in the following is that older command line tools like iwconfig have been deprecated and will probably not work anymore. The new tool in town is called iw. We will first use iw query the status of the link, and then make a connection.
root@beaglebone:~# iw wlan1 linkSo now we have a link, but that isn't going to get us as far as we need to go...
root@beaglebone:~# iw wlan1 connect Abby_Slow
root@beaglebone:~# iw wlan1 link
Connected to xx:xx:xx:xx:xx:xx (on wlan1)
SSID: Abby_Slowfreq: 2437RX: 10694 bytes (75 packets)TX: 2029 bytes (13 packets)signal: -72 dBmtx bitrate: 15.0 MBit/s MCS 0 40MHz short GI
bss flags: short-preamble short-slot-timedtim period: 0beacon int: 100
root@beaglebone:~# ping www.google.comWe need to use something called dhclient to get a DHCP address, like so...
ping: unknown host www.google.com
root@beaglebone:~# dhclient wlan1The sweet, sweet ping of success. There is just one more thing before we go automatic on this problem. Some dongles have issues going into power saving mode. Let's not take our chances and disable this. Inspired by this post, create a file called /etc/udev/rules.d/wifi_power_save.rules and add this one long line to it (no line breaks no matter what it looks like below, please).
root@beaglebone:~# ping www.google.com
PING www.google.com (184.108.40.206) 56(84) bytes of data.
64 bytes from ord31s22-in-f4.1e100.net (220.127.116.11): icmp_seq=1 ttl=50 time=75.2 ms
--- www.google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 75.251/75.251/75.251/0.000 ms
ACTION=="add", SUBSYSTEM=="net", KERNEL=="wlan*" RUN+="/usr/sbin/iw dev %k set power_save off"Here is how to check it the next time you boot the board:
root@beaglebone:~# iwconfig wlan1Now obviously you are not going to want to go through this whole process every time you boot the board. This stuff needs to be automated. But how? One thing you could do is trawl the interweb and try to understand how systemd-networkd works. Then, working from the sparse set of examples on the web, you could manually create some text files against all odds that whatever you come up with is actually going to work. You could do that, because that is what I tried to do to start with. I created a 20-dhcp.network file in /etc/systemd/network that should have automatically worked but didn't. Be smart. Don't do that. Do this:
wlan1 IEEE 802.11bg ESSID:"Abby_Slow"
Mode:Managed Frequency:2.437 GHz Access Point: xx:xx:xx:xx:xx:xx
Bit Rate=5.5 Mb/s Tx-Power=20 dBm
Retry short limit:7 RTS thr:off Fragment thr:off
Link Quality=20/100 Signal level=20/100
Rx invalid nwid:0 Rx invalid crypt:0 Rx invalid frag:0
Tx excessive retries:59 Invalid misc:48 Missed beacon:0
root@beaglebone:~# apt-get updatenmtui is the NetworkManager Text User Interface bundled into the NetworkManager package and it is very easy to use. Ugly, but easy to use.
root@beaglebone:~# apt-get install network-manager
|Ugly, But Works Beautifully|
Until this started to happen...
root@beaglebone:~# [ 2282.574398] INFO: task wpa_supplicant:485 blocked for more than 120 seconds.Then the 'Bone locked up solid.
[ 2282.581864] Tainted: G O 3.14.26-ti-r42 #1
[ 2282.592586] "echo 0 } /proc/sys/kernel/hung_task_timeout_secs" disables this message.
I tried once or twice more and the dongle kept locking up hard after a short while, taking the 'Bone along with it. This is where I started to think that maybe I've got a bad TP-Link dongle. Fortunately for me, I have another dongle, this one based on a Zydas ZD1211 chipset that is also well supported in Linux. It needs some firmware that currently isn't in the default image, so I rebooted the 'Bone and did the following before the board decided to crash again.
root@beaglebone:~# apt-get install zd1211-firmwareI plugged in the Zydas dongle and then rebooted the board so the kernel could detect it and load its firmware (might have worked if I hot-plugged it, might not have). Then I ran nmtui again, set up the dongle, and the network has been working well since then. But you better believe I'm keeping my fingers crossed.
Incidentally, some people have reported that some dongles work poorly when plugged directly into the 'Bone. A popular fix seems to be plugging it in via a USB extension cable or powered hub to get a little separation between the two of them. If you've followed this guide and still can't get things working, try giving that a shot.
This would be a good place to wrap things up with my usual "now go out and do something" line. But heck, while I'm at this, I might as well throw in some other useful things I picked up along the way to get it all into one place. If I don't put this stuff here, I'll just be looking for it myself later anyway.
How do you change the name of the dongle's device interface??? See here on the Archlinux wiki.Anyhoo, there you have it: a reasonably comprehensive and up-to-date tutorial on how to get wireless networking going on one of the more powerful little ARM boards out there. Included at no extra charge was a bunch of related systemd stuff that was previously scattered all over the net. Now get out there and make that 'Bone do something.
How do you check out NetworkManager's status?
root@beaglebone:~# systemctl status NetworkManagerHow can you see what systemd is putting into its journal for NetworkManager? (Tip: use the left and right arrow keys to move horizontally a half screen at a time to see long lines of text!)
root@beaglebone:~# journalctl -u NetworkManagerHow do I reboot the 'Bone?
root@beaglebone:~# systemctl rebootHow do I power it off?
root@beaglebone:~# systemctl poweroff