內容目錄

3. WSL2 連接USB裝置篇(usbipd)

詳細内容參考:微軟官網WSL教學-如何連接USB裝置、以及 基于 usbip 实现共享 usb 设备 博文。

  • 需求1: Win11 build 22000 版之後,只支持 x86機器,只支持 WSL2 功能虛擬機。至於Win10請查找官網教學看可行性。
  • 需求2:Lunux Kernel在 5.10.60.1 版之後。

Windows主機透過 usbipd-win 套件,可以將多種USB周邊裝置,分享給Hyper-V從機、WSL2從機、或遠端的Linux服務器、遠端OpenWRT路由器。從機只要安裝 linux-tools (網路工具)和 usbip 套件,就可以發現被宿主機分享給他的 USB設備。

usbipd/usbip 透過網路或虛擬網路IP協議,將USB設備映射給近端的Hyper-V或WSL,或遠端的客戶端linux、OpenWRT機器。舉凡UART、JLink、STLink、OpenOCD、CAN、LAN、PRINTER、Secure KEY等USB裝置都可以映射。這裏主要操作USB裝置到WSL客戶端機器的映射。

  • linux 是用 usbipd -D & 啓動 usbipd 服務,用 usbip bind 命令將自己的USB 裝置綁定到 usbipd 服務,用 usbip attach 連接遠端(-r ip_addr)的 USB裝置。
  • windows 是用 usbipd server 啓動 usbipd 服務,用 usbipd bind 命令將自己的USB 裝置綁定到 usbipd server。
  • windows 額外提供 usbipd wsl attach 的近端命令,不透過 usbipd server,直接將 USB 裝置提供給(-d 指定的) WSL客戶端,客戶端不必再用 usbipd 命令連接宿主裝置。
  • WSL客戶端仍然可以采用遠端模式,只要知道宿主機的ip,仍可沿用 usbip attach 連接宿主機/其他主機的 usbipd server所提供的USB裝置。

3.1 usbipd 安裝

  • Windows主機: 到usbipd-win 項目的最新發布頁面。下載 usbipd-win_x.x.x.msi安裝 usbipd。可能需要重啓主機生效。

  • WSL2從機:Ubuntu/Debian 系統的從機可以執行下面兩條命令安裝 usbip:

    sudo apt install linux-tools-5.4.0-77-generic hwdata
    sudo update-alternatives --install /usr/local/bin/usbip usbip /usr/lib/linux-tools/5.4.0-77-generic/usbip 20
    

    or

    sudo apt install linux-tools-virtual hwdata
    sudo update-alternatives --install /usr/local/bin/usbip usbip `ls /usr/lib/linux-tools/*/usbip | tail -n1` 20
    

3.2 usbipd 使用

  • #### 主機查看目前 usbipd/wsl 連綫:
usbipd wsl list

Pyboard 目前挂在 BUSID 2-4 上:

BUSID  VID:PID    DEVICE                                                    STATE
2-4    f055:9800  USB 大容量存储设备, USB 串行设备 (COM7)                      Not attached
2-8    2808:a658  FocalTech Fingerprint Reader                             Not attached
2-9    3277:0016  Integrated Camera                                        Not attached
2-10   8087:0033  英特尔(R) 无线 Bluetooth(R)                                Not attached
2-13   090c:1000  USB 大容量存储设备                                          Not attached
  • #### 把 Pyboard 連接到 WSL 從機上:
# 將裝置連接到 wsl:
usbipd wsl attach -b 2-4

再查看:

BUSID  VID:PID    DEVICE                                                        STATE
2-4    f055:9800  USB 大容量存储设备, USB 串行设备 (COM7)                       Attached - Ubuntu-20.04
2-8    2808:a658  FocalTech Fingerprint Reader                                  Not attached
2-9    3277:0016  Integrated Camera                                             Not attached
2-10   8087:0033  英特尔(R) 无线 Bluetooth(R)                                   Not attached
2-13   090c:1000  USB 大容量存储设备                                            Not attached

看到 Pyboard 挂在Ubuntu-20.04上了。

  • #### 從機查看已連接的 USB裝置:
# 查看已連接的 USB裝置:
lsusb

Pyboard 已經連接上了:

Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 002: ID f055:9800 MicroPython Pyboard Virtual Comm Port in FS Mode
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

3.3 usbipd參考

其他 WSL2 從機參考:其他發行版的 usbip 客戶端包

安裝設定完成後,主機可以以管理員身份執行 Powewrshell,下 usbipd 命令,將選定的USB裝置交付給WSL2從機。

命令用法舉例如下:

  • usbipd -? / usbipd wsl -?: 查看命令幫助説明 / 針對 WSL客戶端的命令幫助説明。

  • usbipd wsl list: 查看Windows11主機可以提供給WSL的USB裝置,以及裝置在WSL的連接狀態。

  • usbipd wsl attach -b xx-xx: 將 BUSID為 xx-xx 的裝置連接到WSL。

    若添加 -a 參數則此命令會 hold住,持續監視並重連裝置到WSL,直到按下Ctrl+C

    若要連到非預設的WSL子系統,可用 -d WSL_NAME 指定子系統。(可用wsl -l查系統有的子系統)

  • usbipd wsl attach -i VID:PID: 將裝置類別為 VID:PID 的裝置連接到WSL。

    若添加 -a 參數則此命令會 hold住,持續監視並重連裝置到WSL,直到按下Ctrl+C
    若要連到非預設的WSL子系統,可用 -d WSL_NAME 指定子系統。(可用wsl -l查系統有的子系統)

  • usbipd wsl detach -b xx-xx:斷開 BUSID為xx-xx 的WSL連接。

  • usbipd wsl detach -i VID:PID:斷開 裝置類別為 VID:PID 的WSL連接。

3.4 WSL從機掛載驅動或安裝工具套件

通用的Linux内核有標準的USB類裝置驅動程式,如VCP(USB串口),可以直接使用。若有特殊的裝置,就要額外安裝驅動程式。有的提供了安裝程式,有的需要自行編譯。

3.4.1 VCP 驅動

VCP是標準的 USB Class,是虛擬串口硬件,Ubuntu提供通用驅動。虛擬串口一種是支持 V.25標準 Modem的類型,會被Linux枚舉成 /dev/ttyACM* 樣式的裝置,一種是普通的 UART命令類型,模擬16550 串口控制器,會被Linux枚舉成 /dev/ttyUSB*樣式的裝置。

使用橋接器的MCU需要在 screen 連接時設定baudrate,使用自帶USB VCP的MCU可以不設定。

安裝uart 工具:

sudo snap install serial-monitor --edge

測試

  • CH340: ID:1a86:7523
  • CP210x: ID:10c4:ea60
  • PL2303: ID:067b:2303

3.4.2 CDC – ACM 裝置(ttyACM)

與VCP不同,CDC-ACM 裝置是 USB下虛擬的一套 Modem協議,雖然和 VCP一樣是序列通信,但不會有硬體流控和波特率的設定。CDC裝置會被枚舉在 /dev/ttyACM* 中。
STM32在 microPython下的 USB 被枚舉成MSC+CDC 複合設備,在管理員Powershell 下,用 usbipd.exe wsl list 可以看到其 VID:PID 是 f055:9800 。

$ usbipd.exe wsl list
BUSID  VID:PID    DEVICE                                                STATE
2-4    f055:9800  USB 大容量存储设备, USB 串行设备 (COM3)                   Not attached
。。。

usbipd wsl attach -a -i f055:9800 將其連接到 WSL,並持續監視重連:

PS C:\Users\cyue1> usbipd wsl attach -a -i f055:9800
usbipd: info: Device with hardware-id 'f055:9800' found at busid '2-4'.
usbipd: info: Starting endless attach loop; press Ctrl+C to quit.
Attached

在Linux下用 lsusb查看裝置信息:

$ lsusb
。。。
Bus 001 Device 002: ID f055:9800 MicroPython Pyboard Virtual Comm Port in FS Mode
。。。

用 screen 連接STM32 的 VCP 時,可以不設定 baudrate。

3.4.3 DFU UTIL 套件

​ 許多MCU會提供DFU(device firmware updates)模式,此模式可透過RS232界面或USB界面升級MCU的Firmware。

​ Ubuntu 下的 DFU工具在 apt 的 dfu-util 套件中,可以直接使用。

sudo apt install dfu-util

但 ubuntu20.04 提供的 0.9版有些老舊,目前最新的是 0.11版。建議從DFU UTIL官網直接下載最新dfu工具的執行檔包,解壓後,將linux-amd64/ 下的dfu-xxx 文件,複製到 /usr/local/bin ,以取代 apt 提供的版本。另外可參考dfu build 説明,自行編譯自己的版本。

​ STM32 進入DFU 模式的方法是拉高 BOOT0 pin,再 reset MCU,這時 USB 看到的STM32F407 的 VID:PID 會是 0483:df11 。

​ 可用下面的 PowerShell 指令將 DFU模式的STM32 接到 WSL:

usbipd wsl attach -a -i 0483:df11

3.4.4 OpenOCD DEBUG工具

OpenOCD是通用的 Debugger 工具。可以連接多家的 DEBUGGER(詳情參考這裏)。Ubuntu可以直接 apt 安裝。

sudo apt install openocd

JLink也可由 OpenOCD控制。

3.4.5 JLink DEBUG工具

除了OpenOCD,對於JLink裝置,可以從 https://www.segger.com/downloads/jlink/JLink_Linux_x86_64.deb 下載 JLink。點Accept 後下載。

我當前下載到的包是 JLink_Linux_V784f_x86_64.deb,下載後在 WSL ubuntu中用 sudo dpkg -i命令安裝此安裝包:

sudo dpkg -i JLink_Linux_V784f_x86_64.deb

驗證:

Host 提供 jlink給WSL:

usbipd wsl attach -a -i 1366:0101

連接 STM32F407 開發板到 JLink,然後在WSL 執行JLinkSTM32

$JLinkSTM32

SEGGER J-Link Unlock tool for STM32 devices
Compiled Feb  7 2023 16:54:18
(c) 2009-2015 SEGGER Microcontroller GmbH, www.segger.com
              Solutions for real time microcontroller applications

This program is designed to reset the option bytes of a STM32 device to their factory settings。If read protection of the device is enabled, reset the option bytes will cause a mass erase.

Options:
  [0] Exit
  [1] STM32F0xxxx
  [2] STM32F1xxxx
  [3] STM32F2xxxx
  [4] STM32F3xxxx
  [5] STM32F4xxxx
。。。
Please select the correct device family: 5
Connecting to J-Link via USB...O.K.
Using SWD as target interface.
Target interface speed: 1000 kHz.
VTarget = 3.300V

連接成功。

3.4.6 STLink V2 DEBUG工具

Ubuntu下的stlink-v2需要編譯。

3.4.6.1、安裝編譯依賴

sudo apt-get install git make cmake libusb-1.0-0-dev -y
sudo apt-get install gcc build-essential -y

3.4.6.2、編譯安裝stlink工具

git clone https://github.com/stlink-org/stlink
cd stlink
cmake
make
sudo make install

3.4.6.3 stlink的 st-xxx 命令舉例:

st-flash erase

st-flash reset

st-info --probe

st-flash read out.bin 0x8000000 0x40000

st-flash write xxx.bin 0x8000000

3.5 讓 WSL2 支持 Mass Storage Class(MSC)

STM32 在 microPython 下是被枚舉成 CDC+MSC,可以直接用 隨身碟模式來修改 microPython 的文件,速度比其他的 microPython 透過 CDC虛擬串口快速而知覺了。然而,WSL2 內核不支持 MSC。

找到 https://github.com/jovton/USB-Storage-on-WSL2 的方案是編譯內核,增加 iSCSI 來透過網路連接。但對於 CDC+MSC 合成裝置,我們已經用 usbipd 把 USB 連給 WSL2,直接讓內核支持 MSC 就好了。

kernel 編譯安裝方法:

  • 安裝 kernel 下載和編譯環境:
sudo apt install build-essential flex bison libssl-dev libelf-dev libncurses5-dev git bc -y
  • git clone取得 Microsoft WSL2 內核:
git clone https://github.com/microsoft/WSL2-Linux-Kernel.git
  • 進入內核目錄,選擇 wsl 的config檔案,修改選項:
cd WSL2-Linux-Kernel
export KCONFIG_CONFIG=Microsoft/config-wsl
make menuconfig

修改需求:

  1. Device Drivers 的 USB 支持USB Mass Storage 。
  2. (可選) File System 的 DOS/FAT/EXFAT/NTFS 支持 FAT UTF-8 和 支持 exFAT。
  3. Kernel hacking 的編譯時檢查,關閉生成 BTF 訊息 (編譯報錯,省麻煩關了) 。

因為開發環境常用,我直接編進內核,不做內核模塊加載:

Device Drivers  --->
    [*] USB support  --->
        <*>   USB Mass Storage 

File systems  --->
    DOS/FAT/EXFAT/NT Filesystems  --->
        [*] Enable FAT UTF-8 option by default
        <*> exFAT filesystem support

Kernel hacking  --->
    Compile-time checks and compiler options  --->
        [ ]   Generate BTF typeinfo
  • 保存配置退出後,編譯:(分工給CPUx2=40個task協同工作)
time make KCONFIG_CONFIG=Microsoft/config-wsl -j40

我的 12700H 筆記本大約花5分鐘編譯:

real    3m45.713s
user    56m28.891s
sys     5m22.852s
  • 安裝新構建的模塊:
sudo make modules_install

似乎模塊有工具相依問題,先不管了,我要的功能都直接進 kernel 了.

arch/x86/Makefile:142: CONFIG_X86_X32 enabled but no binutils support
  INSTALL /lib/modules/5.15.90.1-microsoft-standard-WSL2+/kernel/drivers/usb/storage/usb-storage.ko
  INSTALL /lib/modules/5.15.90.1-microsoft-standard-WSL2+/kernel/fs/exfat/exfat.ko
  DEPMOD  /lib/modules/5.15.90.1-microsoft-standard-WSL2+
  • 將新的內核映像bzImage 複製 Windows 主機中(cyue1 是我的 Windows帳戶,請改成你的):
cp ./arch/x86_64/boot/bzImage /mnt/c/Users/cyue1/
  • 在 Windows 主機的用戶目錄下建立 .wslconfig 文件。設定 wsl2 的參數。(cyue1 是我的 Windows帳戶,請改成你的)
pico /mnt/c/Users/cyue1/.wslconfig

內容如下:

[wsl2]
memory=24GB
kernel=C:\\Users\\cyue1\\bzImage

(我的筆記本有 32GB RAM,指定24GB給 wsl2 使用。內核指定為剛剛編譯好複製過來的)

參考 https://learn.microsoft.com/zh-tw/windows/wsl/wsl-config 設定wsl成為你想要的.

  • 關閉 wsl ,之後再重啟,以使用新內核和設定.
sudo shutdown now
  • wsl2開機後驗證。power shell 下:
usbipd wsl list
BUSID  VID:PID    DEVICE                                                        STATE
2-4    f055:9800  USB 大容量存储设备, USB 串行设备 (COM7)                       Not attached
2-8    2808:a658  FocalTech Fingerprint Reader                                  Not attached
2-9    3277:0016  Integrated Camera                                             Not attached
2-10   8087:0033  英特尔(R) 无线 Bluetooth(R)                                   Not attached
  • 將 microPython 裝置 (2-4) 連接到WSL上:
usbipd wsl attach -b 2-4
  • wsl 中察看usb連接:
lsusb
Bus 002 Device 002: ID 090c:1000 Silicon Motion, Inc。- Taiwan (formerly Feiya Technology Corp.) Flash Drive
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID f055:9800 MicroPython Pyboard Virtual Comm Port in FS Mode
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
  • wsl 中察看 /dev,看到多了 /dev/sdd/dev/sdd1
ls /dev/sd* -ls /dev/sd*
/dev/sda  /dev/sdb  /dev/sdc  /dev/sdd  /dev/sdd1
  • mount sdd1 並查看內容:
sudo mount /dev/sdd1 /mnt/d
ls /mnt/d

看到是我的 pyboard 內容:

 boot.py   main.py   myApp.py   polar.py   pybcdc.inf   README.txt  'System Volume Information'   testVCP.py

成功灑花。

最後修改日期: 2023 年 3 月 29 日

作者

留言

撰寫回覆或留言

發佈留言必須填寫的電子郵件地址不會公開。