Guide: Embedded Linux Development in WSL for BeagleBone Green (BBG)

Installing WSL

Steps taken from MS guide.

  • Open MS PowerShell as administrator
    wsl --install

Installing Debian 11.x in WSL

Using the contents of a Debian docker image, create a new WSL install for Debian. Steps taken from MS guide.

Steps for creating TAR file (optional)

You do not need to do these steps if you are able to download a TAR file for your chosen distro. Steps taken from this guide.

  1. Have a Linux distro installed for WSL2.
  2. Install Docker Desktop under Windows, enable WSL integration:
    • Docker > Settings > Docker Engine > Use the WSL 2 based engine
    • Docker > Settings > Resources > WSL Integration > Enabled > select distro.
  3. Launch WSL2's bash
  4. Start the container of interest (may fail, but that's OK)
    docker run -t debian:bullseye bash ls /
    (OK if it gives an error: "/bin/ls: /bin/ls: cannot execute binary file")
  5. Get container ID
    dockerContainerID=$(docker container ls -a | grep -i debian | awk '{print $1}')
    echo $dockerContainerID
  6. Export container to TAR file on C drive:
    docker export $dockerContainerID > /mnt/c/t/debian-bullseye.tar


Import TAR file into WSL

  1. In PowerShell:
    • Create a folder for WSL distro location
      mkdir c:\wslDistroStorage\debian-bullseye
    • Import TAR file (examples use c:\t, but you can use any folder):
      cd c:\t
      wsl --import Debian-Bullseye c:\wslDistroStorage\debian-bullseye .\debian-bullseye.tar
    • Run new distro
      wsl -d Debian-Bullseye
    • Verify correct distro:
      cat /etc/os-release
  2. Update and install sudo and other necessary packages:
    apt update
    apt upgrade
    apt install sudo usbutils lshw iproute2 iputils-ping ssh iptables
    (Critical: ensure you install sudo!)
  3. Setup default user in the newly installed Debian-Bullseye WSL distro:
    • Add new user; add to the sudo group; and set as default WSL user (change to your first name, all lower case, no spaces)
      (choose a password you'll remember; defaults for the rest OK)
      myUsername=yournamehere
      adduser $myUsername
      usermod -aG sudo $myUsername
      echo -e "[user]\ndefault=$myUsername" >> /etc/wsl.conf
  4. Close all WSL instances, set default distro, and restart. In PowerShell:
    wsl --terminate Debian-Bullseye
    wsl --set-default Debian-Bullseye
    wsl
    It should log you in as your new user.
  5. Verify running correct distro:
    cat /etc/os-release

Troubleshooting

  • If something goes wrong, you can remove the WSL distro from PowerShell:
    wsl --unregister Debian-Bullseye

Mapping USB Device to WSL

We must first tell WSL to allow our USB devices to bind to WSL. Then we can tell WSL to take control of the device (attach).

Bind USB Devices to WSL (Once)

Steps drawn from this guide.

  1. Install latest version via its .msi file from usbipd-win project
  2. Connect the BBG and Zen Cape to your computer; allow target to boot (Windows will detect it as a USB device).
  3. Open PowerShell as administrator
  4. Find the USB "BUS ID" for the Zen cape serial port and BBG:
    usbipd list
    For example:
                    BUS ID    VID:PID    Description
        Zen serial: 4-7       0403:6015  USB Serial Converter
        BBG:        4-3       1d6b:0104  Remote NDIS Compatible Device, UsbNcm Host Device, USB Se...

    Note the "BUS ID" for each of:
    a) "USB Serial Converter" = Zen cape serial port (4-7 in example)
    b) "Remote NDIS Compatible Device, UsbNcm Host Device, USB Se..." = BBG (4-3 in example)

  5. Bind each device to be shared with WSL:
    usbipd bind --busid 4-7
    usbipd bind --busid 4-3
  6. Verify each device now shows as Shared:
    usbipd list

Connect USB Devices to WSL (each time)

  1. Open PowerShell
  2. Find BUS ID for Zen serial ("USB Serial Converter") and/or BBG ("Remote NDIS Compatible Device...")
    usbipd list
    If desired devices show as "Not shared" go back to Bind USB Devices to WSL If desired devices show as "Shared", then attach the USB devices to WSL:
    usbipd attach --wsl --busid 4-3
    usbipd attach --wsl --busid 4-7
    usbipd list
    If desired devices show as "Attached", continue to next step.
  3. In WSL, check if USB devices correctly connected:
    • View USB devices:
      lsusb
      (part of usbutils package) should show:
      Bus 002 Device 001: ID 1d6b:0003 Linux 5.10.102.1-microsoft-standard-WSL2 vhci_hcd USB/IP Virtual Host Controller
      Bus 001 Device 004: ID 0403:6015 FTDI FT230X Basic UART
      Bus 001 Device 003: ID 1d6b:0104 BeagleBoard.org BeagleBone
      Bus 001 Device 001: ID 1d6b:0002 Linux 5.10.102.1-microsoft-standard-WSL2 vhci_hcd USB/IP Virtual Host Controller
    • If any issues, run dmesg.
  4. (Optional) When you want to attach the devices back to Windows, run the following from PowerShell:
    usbipd detatch --busid 4-7

Connect to BBG via Screen

  1. Attaching USB serial port to WSL, as described above, and launch WSL.
  2. Install and run screen:
    sudo apt install screen
    sudo screen /dev/ttyUSB0 115200
  3. To close screen press CTRL + A then press \. Then type 'y'.

Networking BBG inside WSL (each time)

  1. Attaching BBG to WSL, as described above, and launch WSL.
  2. Find the Ethernet adapter for the BBG:
    sudo lshw -class network
    (shows "Disabled")
  3. Enable device and check status:
    sudo ip link set dev eth1 up
    sudo lshw -class network
    (now does not show disabled)
  4. Manually set IP address for device (note it's 192.168.6.1, not 192.168.7.1)
    sudo ip addr add 192.168.6.1/24 dev eth1
  5. Check connection to target:
    ping 192.168.6.2
    ssh debian@192.168.6.2
  6. Setup internet forwarding between target and WSL Debian
    • Switch WSL Debian to using IP Tables in "legacy" mode:
      sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
    • Setup WSL Debian to route the internet to the target (eth0 connects to the internet; eth1 connects to BBG):
      sudo iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE
      sudo iptables --append FORWARD --in-interface eth1 -j ACCEPT
      echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
  7. SSH into target and enable internet forwarding to host (WSL):
    sudo route add default gw 192.168.6.1
    echo "nameserver 8.8.8.8" | sudo tee -a /etc/resolv.conf
    ping google.ca

NFS Server in WSL

Steps largely based on the NFS guide, plus some ideas from this video:

  1. Create shared folder:
    mkdir -p ~/cmpt433/public
    chmod a+rwx ~/cmpt433/public
  2. Install NFS server:
    sudo apt install portmap nfs-kernel-server
  3. Export the folder for NFS (overwrites any values in /etc/exports):
    echo "/home/$USER/cmpt433/public 192.168.6.0/255.255.255.0(rw,sync,no_subtree_check)" | sudo tee /etc/exports
    sudo exportfs -rav
  4. Start the NFS services (MUST BE DONE EACH BOOT OF THE HOST):
    sudo mkdir -p /run/sendsigs.omit.d
    sudo touch /run/sendsigs.omit.d/rpcbind
    sudo service rpcbind start
    sudo service nfs-kernel-server start
  5. SSH into the target and run:
    sudo mkdir -p /mnt/remote
    sudo chown debian /mnt/remote
    sudo mount -t nfs 192.168.6.1:/home/brian/cmpt433/public /mnt/remote

VS Code to WSL

  1. Run WSL and checkout code into WSL via git. If connecting to SFU's GitHub server, you may need to run the SFU VPN.
  2. Install necessary tools (see Quick Start Guide for details):
    sudo apt install gcc make cmake gcc-arm-linux-gnueabihf binutils-arm-linux-gnueabihf
  3. Install VS Code into Windows.
  4. Install the "WSL" extension.
  5. Connect to WSL and open a project:
    • Click green "><" button in bottom left.
    • Select "Connect to WSL using Distro..."; select "Debian-Bullseye"
    • Click "Open Folder", and select your folder that is inside WSL.
  6. Install additional extensions into VS Code now that it's connected to WSL:
    • C/C++ Extension Pack
  7. In VS Code, build your project as normal. If running CMake or Makefiles, it may deploy binary to the ~/cmpt433/public folder and therefore be accessible on the target.
  8. Run your code:
    • Open a separate WSL terminal, SSH to the target, mount the NFS folder, and run it.
    • Or, open a WSL terminal within VS Code: Terminal > New Terminal, and run as normal.
  9. Debugging works identically to when using a VM. Note that the IP address of the target/host is now 192.168.6.1 or .2

Browsing to BBG -- Graphical Linux App in WSL

Use this process to launch a graphical web browser to view a page hosted on the BBG while connected to WSL.

  1. Launch WSL
    wsl
  2. Install firefox inside WSL
    sudo apt install firefox-esr # The "Extended Support Release"
  3. Launch firefox from within WSL, opening your BBG at address 192.168.6.2 (port 8088)
    firefox 192.168.6.2:8088 &

Other useful Linux apps to install:

  • Graphical file browser
    sudo apt install nemo
    nemo
  • Gnome-terminal

    sudo apt install dconf-cli dbus-x11 locales gnome-terminal
    
    # Reinstalling terminal
    dconf reset -f /org/gnome/terminal
    sudo apt-get remove gnome-terminal
    sudo apt-get install gnome-terminal
    
    # Reconfiguring locale
    sudo locale-gen --purge
    sudo dpkg-reconfigure locales     # Select en_US.UTF-8 (opt 158?), and then set as default language (opt 3)
    
    # Exit WSL and shut it down
    exit
    wsl --shutdown   # Run in Powershell
    
    # Reload WSL and run
    gnome-terminal