Build Thread: HaLow for Raspberry Pi OS

Buddy! We are live with meshing between my pi5 and OPENManet. The final bit of info I found was setting BATMAN routing algorithm to match OPENManet which is running V instead of IV. Additional steps to join mesh were:

batctl ra BATMAN_V # set routing algo to V instead of IV
batctl if add wlan1 # adds wlan1 to batman and creates bat0
ip link set bat0 up
ip addr add 10.41.x.x/16 # match OPENManet subnet

OPENManet verify

root@BCM2711-2067:~# batctl n
[B.A.T.M.A.N. adv 2024.3-openwrt-6, MainIF/MAC: wlan0/11:22:33:44:55:66 (bat0/11:22:33:44:55:66 BATMAN_V)]
         Neighbor   last-seen      speed           IF
11:22:33:44:55:66    0.420s (        7.1) [     wlan0]

Pi5 verify

root@pi5-halow-1:~# batctl n
[B.A.T.M.A.N. adv 2025.5-1-g35208d12, MainIF/MAC: wlan1/11:22:33:44:55:66 (bat0/11:22:33:44:55:66 BATMAN_V)]
IF             Neighbor              last-seen
11:22:33:44:55:66    1.492s (        7.1) [     wlan1]

I will now proceed with some field testing for range. I need to order another seeedstudio hat so I can actually have 3 node and testing mesh routing :winking_face_with_tongue:

I got the wpa_supplicant format from OPENManet and it works well on the pi5. I got all the opclass and channel matchups for easy switching of the wpa_supplicant_s1g file after you make a change on OPENManet.

Channel Width Channels
1 Mhz 3 - 39 (increments of 2)
op_class=68
s1g_prim_chwidth=0
s1g_prim_1mhz_chan_index=0
[u]
2 Mhz[/u] 6 - 46 (increments of 4)
op_class=69
s1g_prim_chwidth=0
s1g_prim_1mhz_chan_index=0
4 Mhz 8 / 16 / 24 / 32 / 40 / 48
op_class=70
s1g_prim_chwidth=1
s1g_prim_1mhz_chan_index=1
8 Mhz 12 / 28 / 44
op_class=71
s1g_prim_chwidth=1
s1g_prim_1mhz_chan_index=3

Final script I used

Final working script. I did not look in to further optimization of the wpa_supplicant_s1g parameters and instead stuck with what worked after copying from OPENManet
####################################
# Hardware:                        # 
# - Raspberrypi 5                  # 
# - Seeedstudio WM1302 and WM6108  # 
# OS:        Bookworm lite latest  #
####################################

# Install deps   
sudo apt install fakeroot build-essential libncurses-dev xz-utils libssl-dev flex libelf-dev bison git device-tree-compiler bc screen -y

git clone --branch stable_20250428 https://github.com/raspberrypi/linux
cd linux
git remote add morse https://github.com/MorseMicro/rpi-linux.git
git fetch morse
git cherry-pick b37a3f6bb..morse/mm/rpi-6.12.21/1.16.x

# I ran in to issues on occasion with possibly messing up my merge conflict resolutions and opted to just entirely copy/paste mesh_hwmp.c from the morse/mm/rpi-6.12.21/1.16.x branch after resolving all other conflicts

cd ~ 
git clone https://github.com/MorseMicro/morse_driver.git
cd morse_driver
git submodule update --init --recursive
cd ~
git clone https://github.com/MorseMicro/morse-firmware.git --branch 1.16


cd ~/linux
make bcm2712_defconfig
sed -r -i 's/CONFIG_LOCALVERSION=\"(.*)\"/CONFIG_LOCALVERSION=\"\1-morse\"/g' .config
make -j6 Image.gz modules dtbs

sudo make -j6 modules_install
sudo cp arch/arm64/boot/Image.gz /boot/firmware/kernel_2712-morse.img

cd ~/morse_driver
make KERNEL_SRC=~/linux/ CONFIG_WLAN_VENDOR_MORSE=m CONFIG_MORSE_SPI=y CONFIG_MORSE_USER_ACCESS=y CONFIG_MORSE_VENDOR_COMMAND=y
sudo make KERNEL_SRC=~/linux modules_install

cd ~/morse-firmware
sudo make install

cat << EOF >> wm6108-spi.dts
/dts-v1/;
/plugin/;

/ {
        compatible = "brcm,bcm2835", "brcm,bcm2836", "brcm,bcm2708", "brcm,bcm2709", "brcm,bcm2711", "brcm,bcm2712";

        fragment@0 {
                target = <&spi0>;
                frag0: __overlay__ {
                        pinctrl-0 = <&rp1_spi0_gpio9 &rp1_spi0_cs_gpio7 &morse_wake &morse_busy &morse_irq &morse_reset>;
                        cs-gpios = <&gpio 8 1>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        status = "okay";

                        mm6108: mm6108@0 {
                                compatible = "morse,mm610x-spi";
                                reg = <0>;
                                reset-gpios = <&gpio 17 0>;
                                power-gpios = <&gpio 23 0>,
                                              <&gpio 24 0>;
                                spi-irq-gpios = <&gpio 25 0>;
                                spi-max-frequency = <50000000>;
                                status = "okay";
                        };
                        spidev@0 {
                                reg = <0>;
                                status = "disabled";
                        };
                        spidev@1 {
                                reg = <1>;
                                status = "disabled";
                        };

                };
        };

        fragment@1 {
                target = <&rp1_spi0_cs_gpio7>;
                frag1: __overlay__ {
                        function = "gpio";
                        pins = "gpio8";
                        bias-pull-up;
                };
        };

        fragment@2 {
                target = <&gpio>;
                frag2: __overlay__ {
                        morse_wake: morse_wake {
                                function = "gpio";
                                pins = "gpio23";
                                output-high;
                                bias-disable;
                        };

                        morse_busy: morse_busy {
                                function = "gpio";
                                pins = "gpio24";
                                input;
                                bias-pull-down;
                        };

                        morse_irq: morse_irq {
                                function = "gpio";
                                pins = "gpio5";
                                bias-pull-up;
                                input;
                        };

                        morse_reset: morse_reset {
                                function = "gpio";
                                pins = "gpio17";
                                output-high;
                                bias-disable;
                        };
                };
        };

        fragment@3 {
                target = <&rp1_spi0_gpio9>;
                frag3: __overlay__ {
                        bias-disable;
                };
        };
};
EOF

dtc -I dts -O dtb wm6108-spi.dts -o wm6108-spi.dtbo
cp wm6108-spi.dtbo /boot/overlays/

echo "dtoverlay=wm6108-spi" | sudo tee -a /boot/firmware/config.txt
echo "dtparam=spi=on" | sudo tee -a /boot/firmware/config.txt
echo "kernel=kernel_2712-morse.img" | sudo tee -a /boot/firmware/config.txt
echo  "options morse bcf=bcf_fgh100mhaamd.bin country=US" | sudo tee -a /etc/modprobe.d/morse.conf

reboot

sudo apt update
sudo apt install -y libnl-3-dev libnl-genl-3-dev libnl-route-3-dev libusb-dev libusb-1.0-0-dev

cd ~
git clone https://github.com/MorseMicro/hostap.git
cd hostap
git checkout 1.15.3
cp wpa_supplicant/defconfig wpa_supplicant/.config
cp hostapd/defconfig hostapd/.config

# Modify wpa_supplicant/.config to enabled MESH
# Modify wpa_supplicant/.config to enabled MESH
# Modify wpa_supplicant/.config to enabled MESH
# Modify wpa_supplicant/.config to enabled MESH
# Modify wpa_supplicant/.config to enabled MESH
# Modify wpa_supplicant/.config to enabled MESH
# Modify wpa_supplicant/.config to enabled MESH

# Build wpa_supplicant
## Make
CFLAGS="-Wno-error=sign-compare -Wno-error=deprecated-declarations -I $STAGING_DIR/include/libnl3 -I $STAGING_DIR/include/" LDFLAGS="-L $STAGING_DIR/lib/ -L $STAGING_DIR/lib64/" DESTDIR="$STAGING_DIR" BINDIR=/usr/sbin make MORSE_VERSION=rel_1_15_3_2025_Apr_16 -C wpa_supplicant/
## Make install
CFLAGS="-Wno-error=sign-compare -Wno-error=deprecated-declarations -I $STAGING_DIR/include/libnl3 -I $STAGING_DIR/include/" LDFLAGS="-L $STAGING_DIR/lib/ -L $STAGING_DIR/lib64/" DESTDIR="$STAGING_DIR" BINDIR=/usr/sbin make install MORSE_VERSION=rel_1_15_3_2025_Apr_16 -C wpa_supplicant/

# Build hostapd
## Make
CFLAGS="-Wno-error=sign-compare -I $STAGING_DIR/include/libnl3 -I $STAGING_DIR/include/" \
LDFLAGS="-L $STAGING_DIR/lib/ -L $STAGING_DIR/lib64/" \
DESTDIR="$STAGING_DIR" BINDIR=/usr/sbin \
make -j6 MORSE_VERSION=rel_1_15_3_2025_Apr_16 -C hostapd/
## Make install
CFLAGS="-Wno-error=sign-compare -I $STAGING_DIR/include/libnl3 -I $STAGING_DIR/include/" \
LDFLAGS="-L $STAGING_DIR/lib/ -L $STAGING_DIR/lib64/" \
DESTDIR="$STAGING_DIR" BINDIR=/usr/sbin \
make install -j6 MORSE_VERSION=rel_1_15_3_2025_Apr_16 -C hostapd/


# morse_cli
cd ~
git clone https://github.com/MorseMicro/morse_cli.git
cd morse_cli
git checkout 1.15.3
make -j6 CONFIG_MORSE_TRANS_NL80211=1
cp morse_cli /usr/sbin/

# Start wpa_supplicant
cat << EOF >> /root/wpa_supplicant_s1g.conf
network={
        ssid="YOUR_SSID"
        sae_password="YOUR_PASSWORD"
        key_mgmt=SAE
        mode=5
        channel=46 #CHANGE AS NEEDED
        op_class=69 #CHANGE AS NEEDED
        country="US"
        s1g_prim_chwidth=0 #CHANGE AS NEEDED
        s1g_prim_1mhz_chan_index=0 #CHANGE AS NEEDED
        dtim_period=1
        mesh_rssi_threshold=-85
        dot11MeshHWMPRootMode=0
        dot11MeshGateAnnouncements=1
        mbca_config=1
        mbca_min_beacon_gap_ms=25
        mbca_tbtt_adj_interval_sec=60
        dot11MeshBeaconTimingReportInterval=10
        mbss_start_scan_duration_ms=2048
        mesh_beaconless_mode=0
        mesh_dynamic_peering=0
        pairwise=CCMP
        ieee80211w=2
        beacon_int=1000

}
EOF

# -B to background
wpa_supplicant_s1g -B -D nl80211 -i wlan1 -c /root/wpa_supplicant_s1g.conf

# BATMAN-ADV
batctl ra BATMAN_V
batctl if add wlan1
ip link set bat0 up
ip addr add 10.41.x.x/16 (IP from openmanet subnet)

# Verify neighbors
# Should see openmanet as neighbor
batctl n

    [B.A.T.M.A.N. adv 2025.5-1-g35208d12, MainIF/MAC: wlan1/11:22:33:44:55:66 (bat0/11:22:33:44:55:66 BATMAN_V)]
    IF             Neighbor              last-seen
    11:22:33:44:55:66   0.524s (        7.1) [     wlan1]

Testing results

About 20 feet of separation with no obstructions. Both devices on external battery and ever so slightly under powered.

| Channel Width | Test 1 Throughput | Test 2 Throughput | Average Throughput |

| ------------- | ----------------- | ----------------- | ------------------ |

| 1 MHz | 0.94 Mbps | 0.71 Mbps | 0.82 Mbps |

| 2 MHz | 3.53 Mbps | 3.82 Mbps | 3.68 Mbps |

| 4 MHz | 8.28 Mbps | 8.38 Mbps | 8.33 Mbps |

| 8 MHz | 4.95 Mbps | 5.36 Mbps | 5.16 Mbps |

3 Likes