2021/04/11

WSL2で仮想I2C通信

  WSL2でLinuxカーネルのI2Cのテスト機能を使って仮想I2C通信をできるようにします。

●今回の環境

 Windows10


 ディストリビューション

 カーネルバージョン

 環境はこれまでと同じです。

 Linuxカーネルをビルドできる環境が必要です。下記を参考にしてビルド環境を用意してください。

●方法

 まず、I2C機能、I2Cスタブ機能を有効にしたカスタムカーネルをビルドします。
 カスタムカーネルができれば、あとはI2C通信のモジュールをロードし、仮想I2Cデバイスを作成すれば、I2Cデバイスが無くてもPC内でI2C通信ができるようになります。

●カスタムカーネルの設定手順

 menuconfigを立ち上げます。
$ make menuconfig

手順1:Device Drivers に入ります


手順2:I2C Support へ入る


手順3:I2C Support の3項目を有効にする


 I2C support を有効にすると、さらに項目が表示されるので、I2C device interface と I2C/SMBus Test Stub を有効にします。
 そのほか2つがデフォルトで有効ですが、そのままにします。

手順4:設定を保存して終了する

 ここまでできたら、忘れずに設定を保存して menuconfig を終了します。
 また、Linuxカーネル名を変えておくとよいでしょう

手順5:カーネルをビルドし、I2C通信のLKMをインストールする

$ make
$ sudo make modules_install
 → /lib/modules の下に、カーネル名でディレクトリができます。
  この下の kernel ディレクトリ以下にI2C通信に必要な*.ko ファイルが格納されます。

手順6:udevのルールにI2Cのアクセス権を設定する(必要な場合のみ)

 ※udevルールが無いと、I2Cデバイスのアクセス権が root:root になってしまいます。

 まず、i2cグループを作り、ユーザーをi2cグループへ追加します。
$ sudo groupadd i2c
$ sudo gpasswd -a %USER i2c

 /etc/udev/rules.d に 以下の内容のファイルを 99-i2c.rule のファイル名で保存します。
SUBSYSTEM=="i2c-dev", GROUP="i2c", MODE="0660"

手順7:カスタムカーネルでWSL2を起動する

 今作った vmlinux ファイルでWSL2を再起動します。
 やり方は、以下の手順6~を参考にしてください。

手順8:I2C通信を有効にしたカーネルで起動できていることを確認する

$ uname -a
Linux earth 5.4.72-microsoft-standard-WSL2-i2c #1 SMP Wed Apr 10 23:11:51 JST 2021 x86_64 x86_64 x86_64 GNU/Linux

 ここまでが、I2C通信を有効にしたカスタムカーネルの作り方でした。

手順9:udevを起動する(必要な場合のみ)

 ※udevルールが無いと、I2Cデバイスのアクセス権が root:root になってしまいます。
$ /etc/init.d/udev start


 ここまでが、I2C通信を有効にしたカスタムカーネルの作り方でした。

●仮想I2Cデバイスを作成する

以下のコマンドを実行します。
$ sudo modprobe i2c-dev
$ sudo modprobe i2c-stub chip_addr=(slave addr)
 ※slave addr にはI2Cスレーブデバイスのスレーブアドレスを指定します。
  スレーブアドレスは10個まで指定できます。
   chip_addr=0x20            0x20 のI2Cデバイスが接続
   chip_addr=0x20,0x55    0x20 0x55 の2つのI2Cデバイスが接続

 → /dev の下に、i2c-* の名前で仮想I2Cデバイスができます。


 あとは、ふつうにI2Cの通信ができます。
 I2C Tools も使えます。

 SMBus stub driver となっているのが、仮想I2Cデバイスです。


2021/04/04

WSL2で仮想GPIOのアクセス権設定

 WSL2では、systemdが動かないのでudevが動いていないため、sysfsのGPIOのアクセス権が設定がされません。

 このため、GPIO操作するために毎度rootになるか、いちいちchmod,chownしないといけません。
 これは結構面倒なので、何とかしたいと思います。

 その前に、sysfsのgpio周りを、RaspberryPIと同じアクセス権設定にしたいと思います。
 まず準備として、gpioグループを作り、ログインユーザーをgpioグループへ追加します。
$ sudo groupadd gpio
$ sudo gpasswd $USER gpio

 idコマンドでgpioグループに入ったことが確認できます。

 そして、udevを使う場合は、gpio用のルールファイルを作っておきます。
 以下のファイルを /etc/udev/rules.d に 99-gpio.rules の名前で保存します。
SUBSYSTEM=="gpio", GROUP="gpio", MODE="0660"
SUBSYSTEM=="gpio*", PROGRAM="/bin/sh -c '\
        chown -R root:gpio /sys/class/gpio && chmod -R 770 /sys/class/gpio;\
        chown -R root:gpio /sys/devices/virtual/gpio && chmod -R 770 /sys/devices/virtual/gpio;\
        chown -R root:gpio /sys$devpath && chmod -R 770 /sys$devpath\
'"


 さて、それでは、アクセス権の設定方法は以下のいずれかが考えられます。
  1. daemonizeとgenieをインストールし、systemdをPID=1で動かす
  2. udevだけ無理やり動かす
  3. スクリプトを作ってexport/unexportで毎回設定する
 1の方法は、インターネットで「WSL2 systemd」で検索するとやり方がでてきます 。
 でも、なんか、ゴチャゴチャ入れたくないなぁ、と思います。

 2の方法ですが、試してみると、PID=1でなくても、動作するようです。
$ /etc/init.d/udev start


 すると、「インタラクティブシェルから実行されてます。多分、意図したことではないので、60秒待ちます。Ctrl+Cで止めてね。」というような文言がでてきますが、かまわず60秒待ちます。その後、

となってudevの起動が成功します。
後は gpio-mockup を modprobe で起動すれば、RaspberryPI で操作するのと同じ感じにできます。

udev起動時に60秒止められるのが嫌なら、/etc/init.d/udev スクリプト内で sleep(60)しているところを消してしまえばいいです(自己責任でお願いします)
 /etc/init.d/udev スクリプトから一部抜粋


 3の方法は、export/unexportするときに、全てのアクセス権を1つずつ設定していくようなスクリプトを作ればよいのでしょうが、そこまでするなら、sysfsインターフェースのgpioは使うのをやめたほうが良いでしょう。新しいgpioインターフェースにしましょう。

 以上が私なりの方法でした。
 まさか、WSL2がsystemd動いていないとは、思いませんでした。
 dockerはどうなんでしょうね。WSLやめてdockerにしようか。。。

2021/04/03

WSL2で仮想GPIO

   WSL2でLinuxカーネルのgpio-mockup機能を使って仮想GPIOを使えるようにします。


●今回の環境

 Windows10


 ディストリビューション

 カーネルバージョン

 今回の環境はまっさらなWSLで説明しますが、前回の仮想CANのカスタムカーネルの環境でもできます。

 Linuxカーネルをビルドできる環境が必要です。下記を参考にしてビルド環境を用意してください。

●方法

 GPIO機能、GPIO-MOCKUP機能を有効にしたカスタムカーネルをビルドします。
 カスタムカーネルができれば、あとはgpio-mockupモジュールをロードし、仮想GPIOデバイスを作成すれば、GPIOが無いPC上でGPIO操作ができるようになります。

●カスタムカーネルの設定手順

 menuconfigを立ち上げます。
$ make menuconfig

手順1:Device Drivers に入ります



手順2:GPIO Support を有効にする

 Device Drivers 内へ入り(リターンで入る)、GPIO Support を有効にします。


手順3:GPIO Testing Driver を有効にする

 GPIO Support 内へ入り、GPIO Testing Driver を有効にする。


 GPIO Testing Drivber が仮想GPIOドライバです。
 また、GPIOのsysfsインターフェースが必要なら、「/sys/class/gpio/... (sysfs interface)」も選択します。
 利用できるGPIOの数は「Maximum nuber of GPIOs for fast path」で設定します。

手順4:設定を保存して終了する

ここまでできたら、忘れずに設定を保存して menuconfig を終了します。
また、Linuxカーネル名を変えておくとよいでしょう。


手順5:カーネルをビルドし、仮想GPIOのLKMをインストールする

$ make
$ sudo make modules_install
 → /lib/modules の下に、カーネル名でディレクトリができます。
  この下の kernel ディレクトリ以下に仮想GPIOの gpio-mockup.ko ファイルが格納されます。

手順6:カスタムカーネルでWSL2を起動する

 今作った vmlinux ファイルでWSL2を再起動します。
 やり方は、以下の手順6~を参考にしてください。

手順7:GPIOを有効にしたカーネルで起動できていることを確認する

$ uname -a
Linux earth 5.4.72-microsoft-standard-WSL2-gpio #1 SMP Wed Mar 2 20:32:16 JST 2021 x86_64 x86_64 x86_64 GNU/Linux

 ここまでが、GPIOを有効にしたカスタムカーネルの作り方でした。


●仮想GPIOデバイスを作成する

gpio-mockupドライバをmodprobeコマンドで読み込みます。

書式:
    # modprobe gpio-mockup gpio_mockup_ranges=[x,y](,…,[x,y]) (gpio_mockup_named_lines)

    x:lineの開始番号、または、-1
    y:lineの終了番号、または xが-1のときlineの個数
 ※x = -1 のとき、割り当ては後ろからになるので注意

例1:gpio0~gpio7 の8つのGPIOを割り当てる
$ sudo modprobe gpio-mockup gpio_mockup_ranges=0,8
 → /dev の下に、gpiochip0 ができ、8line が使用できる
  また、sysfsインターフェースがある場合は、gpio0~7 までexportできる

例2:gpiochip0に4つ、gpiochip1に8つのGPIOを割り当てる
$ sudo modprobe gpio-mockup gpio_mockup_ranges=0,4,8,16
 → /dev の下に、gpiochip0 と gpiochip1 ができ、それぞれ 4line と 8line が使用できる
  また、sysfsインターフェースでは、gpio0~3 と gpio8~15 までexportできる

例3:gpiochip0とgpiochip1に後ろから8つずつGPIOを割り当てる
$ sudo modprobe gpio-mockup gpio_mockup_ranges=-1,8,-1,8
 → /dev の下に、gpiochip0 と gpiochip1 ができ、それぞれ 8line が使用できる
  また、sysfsインターフェースでは、gpio504~511 と gpio496~503 までexportできる

例4:各ラインにラベルを付ける
$ sudo modprobe gpio-mockup gpio_mockup_ranges=0,8,8,16 gpio_mockup_named_lines
 → 各ラインにラベル名が gpio-mockup-A-*、gpio-mockup-B-* という名前が付く
  また、sysfsインターフェースでは、gpio-mockup-A-*、gpio-mockup-B-*というような名前でexportされる


以上で仮想GPIOが使えるようになります。
libgpiod tools も普通に使えます。


●sysfsインターフェースのアクセス権について

 WSLでは、initプロセスが動いていないので、udevが動作していないため、/sys/class/gpio 以下のアクセス権がすべて root:root になってしまいます。
これらの対処法は次回まとめます。

2021/03/27

WSL2で仮想CAN通信

  WSL2でLinuxカーネルのSocketCAN機能を使って仮想CAN通信をできるようにします。

●今回の環境

 Windows10


 ディストリビューション

 カーネルバージョン

 環境は前回と同じです。

 Linuxカーネルをビルドできる環境が必要です。下記を参考にしてビルド環境を用意してください。

●方法

 まず、SocketCAN機能、VCAN機能を有効にしたカスタムカーネルをビルドします。
 カスタムカーネルができれば、あとはCAN通信のモジュールをロードし、仮想CANデバイスを作成すれば、CANデバイスが無くてもPC内でCAN通信ができるようになります。

●カスタムカーネルの設定手順

 menuconfigを立ち上げます。
$ make menuconfig

手順1:Networking suportを有効にする


 ※選択は、項目まで↑↓キーで移動して、スペースキーを押すとできます。

手順2:CAN bus subsystem support を有効にする

 Networking support 内へ入り(リターンで入る)、CAN bus subsystem support を有効にします。


手順3:CAN通信機能の3項目を有効にする

 CAN bus subsystem support 内へ入り、さらに下記の3項目を有効にする。


 デフォルトで既にこれらの項目が有効になっていると思いますが、念のために確認しておきます。

手順4:CAN Device Drivers 内の項目を有効にする

 CAN Device Driversの中へ入り、さらに以下の設定を行います。

 Virtual Local CAN Interface (vcan) が仮想CANドライバです。
 そのほか2つがデフォルトで有効ですが、そのままにします。

手順5:設定を保存して終了する

 ここまでできたら、忘れずに設定を保存して menuconfig を終了します。
 また、Linuxカーネル名を変えておくとよいでしょう。

手順6:カーネルをビルドし、CAN通信のLKMをインストールする

$ make
$ sudo make modules_install
 → /lib/modules の下に、カーネル名でディレクトリができます。
  この下の kernel ディレクトリ以下にCAN通信に必要な*.ko ファイルが格納されます。

手順7:カスタムカーネルでWSL2を起動する

 今作った vmlinux ファイルでWSL2を再起動します。
 やり方は、以下の手順6~を参考にしてください。

手順8:CAN通信を有効にしたカーネルで起動できていることを確認する

$ uname -a
Linux earth 5.4.72-microsoft-standard-WSL2-can #1 SMP Wed Mar 27 14:20:57 JST 2021 x86_64 x86_64 x86_64 GNU/Linux

 ここまでが、CAN通信を有効にしたカスタムカーネルの作り方でした。


●仮想CAN通信デバイスを作成する

以下のコマンドを実行します。
$ sudo modprobe can
$ sudo modprobe can_raw
$ sudo modprobe vcan
$ sudo ip link add dev vcan0 type vcan
$ sudo ip link set up vcan0
 → /sys/class/net の下に、vcan0 の名前で仮想CANデバイスができます。


あとは、ふつうに仮想CAN通信をすることができます。
can-utilsも普通に使えます。

※仮想CANデバイスは、PCを再起動すると消えてしまうので、また modprobe からコマンド実行してください。

  


2021/03/21

WSL2のカーネルをカスタムビルドする

 WSL2のLinuxカーネルを、コンフィグ設定してビルド・使用します。

●今回の環境

 Windows10


 ディストリビューション

 カーネルバージョン

 環境は前回と同じです。
 前回のビルド環境をそのまま使う場合は、下記の手順3から始めてください。

●ビルド手順

手順1:カーネルソースをダウンロード

 カーネルのソースコードはGitHubのMicrosoft公式のものを使用します。
$ curl -OL https://github.com/microsoft/WSL2-Linux-Kernel/archive/linux-msft-5.4.72.tar.gz
 → linux-msft-5.4.72.tar.gz ファイルができる

 解凍します。
$ tar -zxf linux-msft-5.4.72.tar.gz
 → WSL2-Linux-Kernel-linux-msft-5.4.72 ディレクトリができる

手順2:カーネルのビルドに必要なソフトをインストール

 カーネルソース内の README-Microsoft.WSL2 ファイルの2に書かれているツールをインストールします。
 ただし、これaptでインストールするのに、sudo とinstall の間に apt が抜けているので、aptを追記して実行すること(昔から抜けてる。いいかげん直しなよ。。。)
$ sudo apt install build-essential flex bison libssl-dev libelf-dev

手順3:.configファイルの準備

 ソースのディレクトリへ入り、Microsoft/config-wsl ファイルをコピーする
$ cd WSL2-Linux-Kernel-linux-msft-5.4.72
$ cp Microsoft/config-wsl .config


手順4:.configファイルを編集

 方法はいくつかありますが、今回はmenuconfigを使ってGUIで編集します。

 事前にmenuconfig用ツールのインストールが必要
$ sudo apt install libncurses-dev

 上記のツールが入っていれば、以下のコマンドを実行
$ make menuconfig


 ここで、カーネルに組込む、またはカーネルモジュールの有効・無効を切り替えます。

 今回は、カーネルの名前を変えることとします。
 以下の項目を設定します。

 General setup   --->
   Local version - append to kernel release

 WSL2のデフォルトは「-microsoft-standard-WSL2」なので、この名前を適当に変えます。
 今回は例として「-microsoft-standard-WSL2-custom」とします。
 この設定は、「uname -r」 で表示される名前が変ります。

 書き換え出来たら、セーブして終了します。

手順5:カーネルをビルド

$ make
 → vmlinuxファイルができる

 前回はコンフィグファイルを指定しましたが、今回は先ほど作った .config を使います。

手順6:vmlinuxファイルをWindows側へコピー

 コピー先は任意の場所を使用できるが、Windowsの領域へコピーする。
 今回の例では、Windowsの%USERPROFILE%ディレクトリの下にwsl2/5.4.72-microsoft-standard-WSL2-customディレクトリを作って、そこへコピーすることにします。
 ※(Windowsのユーザー名)は各環境で変えること
 ※%USERPROFILE%ディレクトリ = c:\Users\(Windowsのユーザー名) のディレクトリ
$ mkdir -p /mnt/c/Users/(Windowsのユーザー名)/wsl2/5.4.72-microsoft-standard-WSL2-custom
$ cp vmlinux /mnt/c/Users/(Windowsのユーザー名)/wsl2/5.4.72-microsoft-standard-WSL2-custom

手順7:.wslconfigファイルで使用するlinuxカーネルを指定する

 %USERPROFILE%ディレクトリの直下に .wslconfigファイルを、以下の内容で作る。
 ※"\"はエスケープシーケンスになるので2つ続けること
[wsl2]
kernel = c:\\Users\\(Windowsのユーザー名)\\wsl2\\5.4.72-microsoft-standard-WSL2-custom\\vmlinux

手順8:wslをシャットダウンする

 PowerShellで、wslをシャットダウンする。
PS > wsl --shutdown

手順9:wslを起動し、unameでバージョンを確認する

$ uname -a
Linux earth 5.4.72-microsoft-standard-WSL2-custom #1 SMP Wed Mar 21 15:20:57 JST 2021 x86_64 x86_64 x86_64 GNU/Linux

 ビルド日時などから、今作ったカーネルで起動できていることを確認する。


以上で、カーネルのカスタムビルドから起動するまででした。

次回は、Linuxカーネルの仮想CAN通信を有効にします。

2021/03/18

WSL2のカーネルを自分でビルドして使う

 WSL2でubuntuをインストールすると、/lib/modules以下がカラなので、PC上で仮想CAN、仮想GPIOなどのドライバが使えなかったり、ローダブルカーネルモジュール(LKM)のビルドができません。
 このため、Linuxカーネルのコンフィグからこれらのオプションを有効にしたり、LKMをビルドできる環境を用意する必要があります。
 まずは、WSL2のLinuxカーネルを自分でビルドして使えることを確認します。

●今回の環境

 Windows10


 ディストリビューション

 カーネルバージョン

今回はカーネルのコンフィグはWSL2デフォルトのままビルドします。
今のカーネルバージョンが5.4.72なので、同じ5.4.72を使います。
仮想CANを有効にしたカスタムビルドは次回行います。

●ビルド手順

手順1:カーネルソースをダウンロード

 カーネルのソースコードはGitHubのMicrosoft公式のものを使用します。
$ curl -OL https://github.com/microsoft/WSL2-Linux-Kernel/archive/linux-msft-5.4.72.tar.gz
 → linux-msft-5.4.72.tar.gz ファイルができる

 解凍します。
$ tar -zxf linux-msft-5.4.72.tar.gz
 → WSL2-Linux-Kernel-linux-msft-5.4.72 ディレクトリができる

手順2:カーネルのビルドに必要なソフトをインストール

 カーネルソース内の README-Microsoft.WSL2 ファイルの2に書かれているツールをインストールします。
ただし、これaptでインストールするのに、sudo とinstall の間に apt が抜けているので、aptを追記して実行すること(昔から抜けてる。いいかげん直しなよ。。。)
$ sudo apt install build-essential flex bison libssl-dev libelf-dev

手順3:カーネルをビルド

$ cd WSL2-Linux-Kernel-linux-msft-5.4.72
$ make KCONFIG_CONFIG=Microsoft/config-wsl
 → vmlinuxファイルができる

手順4:vmlinuxファイルをWindows側へコピー

 コピー先は任意の場所を使用できるが、Windowsの領域へコピーする。
 今回の例では、Windowsの%USERPROFILE%ディレクトリの下にwsl2/5.4.72-microsoft-standard-WSL2ディレクトリを作って、そこへコピーすることにします。
 ※(Windowsのユーザー名)は各環境で変えること
 ※%USERPROFILE%ディレクトリ = c:\Users\(Windowsのユーザー名) のディレクトリ
$ mkdir -p /mnt/c/Users/(Windowsのユーザー名)/wsl2/5.4.72-microsoft-standard-WSL2
$ cp vmlinux /mnt/c/Users/(Windowsのユーザー名)/wsl2/5.4.72-microsoft-standard-WSL2

手順5:.wslconfigファイルで使用するlinuxカーネルを指定する

 %USERPROFILE%ディレクトリの直下に .wslconfigファイルを、以下の内容で作る。
 ※"\"はエスケープシーケンスになるので2つ続けること
[wsl2]
kernel = c:\\Users\\(Windowsのユーザー名)\\wsl2\\5.4.72-microsoft-standard-WSL2\\vmlinux

手順6:wslをシャットダウンする

 PowerShellで、wslをシャットダウンする。
PS > wsl --shutdown

手順7:wslを起動し、unameでバージョンを確認する

$ uname -a
Linux earth 5.4.72-microsoft-standard-WSL2 #1 SMP Wed Mar 17 20:42:16 JST 2021 x86_64 x86_64 x86_64 GNU/Linux

ビルド日時などから、今作ったカーネルで起動できていることを確認する。

以上で終わりです。

次回は、カーネルのカスタムビルドを行います。