While developing an embedded, read-only test system for a Pi Zero W WLAN port modification we have done for a customer, I ran into an interesting issue.
The Pi Zero W suddenly stopped connecting to our router.
After some investigation, I managed to find the reason, and fix.
The reason: WLAN regulatory domains
In different countries, different WiFi “channels” (= frequencies) are available for usage.
Wikipedia has a good overview:
For 2,4 GHz channel 12 and 13 are not available in the USA, but they are in most other countries.
If you leave your WLAN devices / Raspberry Pi’s on default settings, they will assume that they are not allowed to connect to these channels. They have no way of knowing where they are until you tell them, and thus choose the safe “worldwide” option in your interest.
If your router, on the other hand, is configured on channel 12 or 13, your Raspberry Pi Zero W (or any other Pi for that matter, including the Pi 3 B+) will not be able to see your router.
But I did not set up my router to use this channel
Neither did I. Everything was working fine until about 4 am – then the router suddenly decided it wanted to switch to this channel, since there’s less interference on it from neighbours.
Your router might switch suddenly, and you will find yourself investigating a difficult issue.
How can I determine if this is my issue?
Use a WLAN scanning tool.
I use inSSIDer for Home. Unfortunately it doesn’t seem to be free anymore, but there are alternatives out there.
As you can see in this screenshot our network uses channels 13 and 9. (Because it is a 802.11 n network which uses channel bonding for two 20 MHz wide channels).
Channel 13 is not available in the US, and thus not on the Raspberry Pi by default.
The solution: CRDA
You need to install some packages, and set them up appropriately, in order to set the WiFi country.
On Raspbian, this is very easy and straightforward, since all necessary packages have been pre-installed for you.
Use sudo raspi-config as a tool to set the WiFi country.
On Alpine Linux, some more work is necessary. I will guide you through it step by step in this blogpost, to share what I have learned, and what took me about a full day of work to learn. Hopefully, you will be done in 20 minutes or less.
There will be further blog posts about Alpine Linux on the Raspberry Pi, for now we focus on this specific WiFi connectivity issue for European citizens.
Running as root
In the following tutorial, I assume that you run the operations as user root.
If you are not root, become root as appropriate.
A note about the RAM-only file system of Alpine
Alpine Linux has the big advantage of being able to run completely read-only from your SD card. This means, for example, that you can unplug the Raspberry Pi during operation without corrupting the file system.
Of course there must be a possibility to apply your changes to the base system during development.
The command is:
lbu commit -d
Important: lbu commit might need to be set up to save specific subdirectories which are modified (using lbu include – refer to the link below for details).
Refer to the following page for more details:
Set up Repositories
note: by default only vi is installed on Alpine Linux. If you want to add nano, use the following command:
apk add nano
Edit the repositories (switch vi with nano if you have installed it):
Add / replace the following (read the comment at the bottom for more info):
All three edge repositories are necessary, as different packages reside in different repositories.
Install necessary packages
Run the following command:
apk add wireless-regdb crda iw
- wireless-regdb contains the wireless regulatory database binaries.
- crda is the userspace tool which updates regulatory information for the kernel
- iw are wireless configuration utilities, which you will use to set the regulatory domain (country)
Check current regulatory domain
iw reg get
This will show the current domain (most probably country 00: DFS-UNSET). Here’s a screenshot of what we are aiming for (in our case DE for Germany):
Edit mdev rules
In the following, the position of the new entry is very important – it must be at the very top, just before the $MODALIAS line. Otherwise this will not work!!
insert the following new line just before the $MODALIAS line:
$COUNTRY=.. root:root 0660 */sbin/crda
Here’s a screenshot of the edited file:
- (unfortunately does not mention the location of the new mdev.conf line – had me debugging for several hours!)
Create new modprobe.d entry
Insert the following line (if necessary adjust DE to your country – two letter code):
options cfg80211 ieee80211_regdom=DE
Save the file.
This file will ensure that your regulatory domain is applied correctly upon boot.
- https://linux.die.net/man/8/crda – says that the country code is an ISO / IEC 3166 alpha2 country code
You can alternatively set the regulatory domain using iw (might be necessary in addition to the above? My test shows that this does not stick, though.)
iw reg set DE
Here’s a screenshot:
Run (if necessary):
lbu commit –d
Reboot. Your Pi Zero W should now also be able to connect to channel 12 and channel 13!
A note on crda
crda is not supposed to be run by you, the user. It is run as a helper application by iw.
A crude hack which “might” work when debugging follows. It works, sometimes. Rarely, actually.
iw reg set DE ; COUNTRY=DE /sbin/crda
often it would fail for me with the following output:
failed to set regulatory domain -22
Even now, after I can set the country properly, this command will fail most of the time … I assume it is due to race conditions.
As far as I understand it, iw sets certain environment variables, which in turn trigger mdev to run /sbin/crda, to send these changes to the kernel.
iw is not the only tool which can change the regulatory domain for the kernel; wpa-supplicant is also supposed to be able to do it.
And, as you have seen, cfg80211.conf is also able to do it.
The regulatory.bin is installed in /usr/lib/crda.
You do NOT need the package crda-dev for the solution described in this blog post.
A note on the repository file
If you remove / comment the repository sources which were added in the beginning, packages “disappear” from your system.
I will need to investigate this further, as I have just started to work with Alpine Linux.
For now, do not remove repository lines for packages you installed to your system.