電気回路/zynq/Device Tree Overlay のバックアップの現在との差分(No.3)

更新


  • 追加された行はこの色です。
  • 削除された行はこの色です。
[[公開メモ]]

#contents

* リブートしなくても Device Tree を変更できるらしい [#f4a6ef00]

Device Tree Overlay という機能を使うと、
Linux をリブートしなくても Device Tree を変更できるらしいです。

http://qiita.com/ikwzm/items/ec514e955c16076327ce

さらに、FPGA のロードまで Linux の起動後に行うようにすれば、
Linux をリブートせずともロジックの書き換え&利用が可能になります???

PetaLinux で利用可能な Xilinx Linux Kernel 4.6.0 では、
menuconfig からチェックを付けるだけで Device Tree Overlay 
が使えるようになります。
[[電気回路/zynq/Petalinux のカスタマイズ#u43d03eb]]

ということで、試してみます。

* 情報 [#vff0dbb9]

dtc に -@ を付けて、unresolved reference を許可できる話など~
https://www.raspberrypi.org/documentation/configuration/device-tree.md ~
ん? "dtc: invalid option -- '@'" となる???(Version: DTC 1.4.0)~


* configfs だけで使える? [#wa82a16c]

http://qiita.com/ikwzm/items/ec514e955c16076327ce

では configfs だけで使えればいいのに、といいつつ独自の dtbocfg 
こちら↑では configfs だけで使えればいいのに、といいつつ独自の dtbocfg 
を作って使っていたのですが、4.6.0-xilinx ではどうか、まず試してみました。

menuconfig の File System ---> Pseudo filesystems ---> {M} Userspace-driven configuration filesystem
で configfs を有効にして、

 LANG:console
 $ sudo modprobe configfs
 $ mount | grep configfs
  configfs on /sys/kernel/config type configfs (rw,relatime)
 $ ls /sys/kernel/config
  /sys/kernel/config
 $ sudo mkdir -p /sys/kernel/config/device-tree/overlays/test
  mkdir: cannot create directory ‘/sys/kernel/config/device-tree’: Operation not permitted

どうやらまだできないようです?

* dtbocfg のビルド [#e7739276]

そこで、

http://qiita.com/ikwzm/items/ec514e955c16076327ce

の dtbocfg を使わせてもらうことにします。

ビルドにカーネルソースを必要とするので、PetaLinux のクロスコンパイル環境を
使ってビルドしました。

 LANG:console
 $ cd ~/z-turn
 $ git clone https://github.com/ikwzm/dtbocfg.git
 $ cd dtbocfg
 $ ls
  Makefile  Readme.md  dtbocfg.c  dtbocfg.rb
 $ cat Makefile
  ARCH            := arm
  KERNEL_SRC_DIR  ?= /lib/modules/$(shell uname -r)/build
  ifeq ($(shell uname -m | sed -e s/arm.*/arm/),arm)
  else
    CROSS_COMPILE  ?= arm-linux-gnueabihf-
  endif
  
  obj-m := dtbocfg.o
  
  all:
          make -C $(KERNEL_SRC_DIR) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) modules
  
  clean:
          make -C $(KERNEL_SRC_DIR) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) M=$(PWD) clean
 $ petalinux-setup
 $ arm-linux-gnueabihf-gcc --version
  arm-linux-gnueabihf-gcc (Linaro GCC 5.2-2015.11-2) 5.2.1 20151005
  Copyright (C) 2015 Free Software Foundation, Inc.
  This is free software; see the source for copying conditions.  There is NO
  warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 $ ls ~/z-turn/zturn-v2016.4/kernel-source
  COPYING        Makefile        block     include  modules.builtin  sound
  CREDITS        Module.symvers  certs     init     modules.order    tools
  Documentation  README          crypto    ipc      net              usr
  Kbuild         REPORTING-BUGS  drivers   kernel   samples          virt
  Kconfig        System.map      firmware  lib      scripts          vmlinux
  MAINTAINERS    arch            fs        mm       security         vmlinux.o
 $ make KERNEL_SRC_DIR=~/z-turn/zturn-v2016.4/kernel-source
  make -C /home/osamu/z-turn/zturn-v2016.4/kernel-source ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- M=/home/osamu/z-turn/dtbocfg modules
  make[1]: ディレクトリ '/home/osamu/z-turn/zturn-v2016.4/kernel-source' に入ります
    CC [M]  /home/osamu/z-turn/dtbocfg/dtbocfg.o
    Building modules, stage 2.
    MODPOST 1 modules
    CC      /home/osamu/z-turn/dtbocfg/dtbocfg.mod.o
    LD [M]  /home/osamu/z-turn/dtbocfg/dtbocfg.ko
  make[1]: ディレクトリ '/home/osamu/z-turn/zturn-v2016.4/kernel-source' から出ます
 $ ls
  Makefile        Readme.md  dtbocfg.ko     dtbocfg.mod.o  dtbocfg.rb
  Module.symvers  dtbocfg.c  dtbocfg.mod.c  dtbocfg.o      modules.order
 $ sudo cp dtbocfg.ko (path)

* dtbocfg を組み込む [#h7d3cdd8]

[[電気回路/zynq/Petalinux のカスタマイズ#u43d03eb]] でビルドしたカーネルと、
PetaLinux で作られた標準の .dtb を使って z-turn ボードを起動し、dtbocfg.ko
の読み込みを試しました。

 LANG:console
 $ uname -a
  Linux xenial-zynq 4.6.0-xilinx #1 SMP PREEMPT Fri Feb 24 07:17:45 JST 2017 armv7l armv7l armv7l GNU/Linux
 $ ls dtbocfg.ko
  dtbocfg.ko
 $ sudo insmod dtbocfg.ko
  insmod: ERROR: could not insert module dtbocfg.ko: Unknown symbol in module
 $ # 肝心の symbol 名が表示されない???
 $ sudo tail /var/log/kern.log
  Mar  2 15:54:08 xenial-zynq kernel: dtbocfg: Unknown symbol config_group_init (err 0)
  Mar  2 15:54:08 xenial-zynq kernel: dtbocfg: Unknown symbol configfs_register_group (err 0)
  Mar  2 15:54:08 xenial-zynq kernel: dtbocfg: Unknown symbol configfs_unregister_subsystem (err 0)
  Mar  2 15:54:08 xenial-zynq kernel: dtbocfg: Unknown symbol configfs_register_subsystem (err 0)
  Mar  2 15:54:08 xenial-zynq kernel: dtbocfg: Unknown symbol config_group_init_type_name (err 0)
  Mar  2 15:54:08 xenial-zynq kernel: dtbocfg: Unknown symbol config_item_init_type_name (err 0)
  Mar  2 15:54:08 xenial-zynq kernel: dtbocfg: Unknown symbol config_item_put (err 0)
  Mar  2 15:54:08 xenial-zynq kernel: dtbocfg: Unknown symbol configfs_unregister_group (err 0)
 $ sudo modprobe configfs
 $ sudo insmod dtbocfg.ko
 $ ls -d /sys/kernel/config/device-tree/overlays
  /sys/kernel/config/device-tree/overlays

うまくいった。

* dtbo の準備 [#eed5a9a6]

[[電気回路/zynq/AXI4-LiteスレーブIPの動作テスト#ee317ba8]]
で試した accesstest IP に対する uio ブロックを設定します。

 LANG:console
 $ cat > accesstest-uio.dts
  /dts-v1/;
  /{
      fragment@0 {
           target-path = "/amba";
          __overlay__ {
              #address-cells = <0x1>;
              #size-cells = <0x1>;
              accesstest@43c00000 {
                  compatible = "generic-uio";
                  reg = <0x43c00000 0x1000>;
                  interrupts = <0 57 0>;
                  interrupt-parent = <3>;
              };
          };
      };
  };
  ^D
 $ dtc -O dtb -o accesstest-uio.dtbo accesstest-uio.dts
 $ ls
  accesstest-uio.dtbo  accesstest-uio.dts  dtbocfg.ko

* dtb の組み込み [#w4c2fbb9]

 LANG:console
 $ sudo mkdir /sys/kernel/config/device-tree/overlays/accesstest
 $ ls /sys/kernel/config/device-tree/overlays/accesstest
  dtbo  status
 $ sudo cp accesstest-uio.dtbo /sys/kernel/config/device-tree/overlays/acesstest/dtbo
 $ sudo echo 1 > /sys/kernel/config/device-tree/overlays/accesstest/status
  -bash: /sys/kernel/config/device-tree/overlays/accesstest/status: Permission denied
 $ sudo bash -c "echo 1 > /sys/kernel/config/device-tree/overlays/accesstest/status"
 $ ls /dev/uio*
  ls: cannot access '/dev/uio*': No such file or directory
 $

あれ?うまくいかない。

* まずは普通に組み込めるかテスト [#ia616ad7]

 LANG:console
 $ dtc -I dtb -O dts -o devicetree.dts /boot/devicetree.dtb
 $ jed devicetree.dts
  amba {
    compatible = "simple-bus";
    #address-cells = <0x1>;
    #size-cells = <0x1>;
    interrupt-parent = <0x3>;
    ranges;
 
 +  accesstest@43c00000 {
 +      compatible = "generic-uio", "uio", "uio_pdrv";
 +      reg = <0x43c00000 0x1000>;
 +      interrupts = < 0 57 0 >;
 +      interrupt-parent = <0x3>;
 +  };
 $ sudo dtc -O dtb -o /boot/devicetree.dtb devicetree.dts
 $ sudo reboot
 ...
 Login: osamu
 Password: ************
 $ ls /dev/uio*
  ls: cannot access '/dev/uio*': No such file or directory
 $ grep uio /lib/modules/4.6.0-xilinx/modules.builtin
  kernel/drivers/uio/uio.ko
  kernel/drivers/uio/uio_pdrv_genirq.ko
  kernel/drivers/uio/uio_xilinx_apm.ko
 $ ls -ld /sys/class/uio/
  drwxr-xr-x 2 root root 0  3月  2 16:50 /sys/class/uio/

こっちの問題か orz

カーネルドライバは入っているし、/sys には uio クラスが登録されているけれど、
/dev/uio* が見つからない。

https://forum.digilentinc.com/topic/2719-how-to-register-my-device-as-uio-on-petalinux/#comment-9553

> bootargs に uio_pdrv_genirq.of_id=generic-uio を追加しないとね

なんだって?

 LANG:console
 $ sudo jed /boot/uEnv.txt
  - bootargs=console=ttyPS1,115200 root=/dev/mmcblk0p2 noinitrd rw earlyprintk rootfstype=ext4 devtmpfs.mount=0
  + bootargs=console=ttyPS1,115200 root=/dev/mmcblk0p2 noinitrd rw earlyprintk rootfstype=ext4 devtmpfs.mount=0 uio_pdrv_genirq.of_id=generic-uio
 $ sudo reboot
 ...
 Login: osamu
 Password: *********
 $ ls /dev/uio*
  /dev/uio0

うまく行ったけど・・・これは何のおまじないなんだぜ?

ググってみると、Linux Kernel 全体との整合性のために
最近の kernel では uio モジュールで compatible が使えなくなったため、
その対応がこれなんだとか?~
結局、何を言っているのかわからない。

https://forums.xilinx.com/t5/Embedded-Linux/generic-UIO-broken/td-p/564259 ~
https://github.com/Xilinx/linux-xlnx/commit/7ebd62dbc727ef343b07c01c852a15fc4d9cc9e5 ~

overlay を試すため、一旦 /boot/devicetree.dtb を元に戻す。

 LANG:console
 $ jed devicetree.dts
  amba {
    compatible = "simple-bus";
    #address-cells = <0x1>;
    #size-cells = <0x1>;
    interrupt-parent = <0x3>;
    ranges;
 
 -  accesstest@43c00000 {
 -      compatible = "generic-uio", "uio", "uio_pdrv";
 -      reg = <0x43c00000 0x1000>;
 -      interrupts = < 0 57 0 >;
 -      interrupt-parent = <0x3>;
 -  };
 $ sudo dtc -O dtb -o /boot/devicetree.dtb devicetree.dts
 $ sudo reboot
 Login: osamu
 Password: *********
 $ ls /dev/uio*
  ls: cannot access '/dev/uio*': No such file or directory

* うまくいった [#q4ed734b]

 LANG:console
 $ sudo modprobe configfs
 $ sudo insmod dtbocfg.ko
 $ sudo mkdir /sys/kernel/config/device-tree/overlays/accesstest
 $ sudo dtc -O dtb -o /sys/kernel/config/device-tree/overlays/accesstest/dtbo accesstest-uio.dts
 $ sudo bash -c "echo 1 > /sys/kernel/config/device-tree/overlays/accesstest/status"
 $ ls /dev/uio*
  /dev/uio0
 $ sudo bash -c "echo 0 > /sys/kernel/config/device-tree/overlays/accesstest/status"
 $ ls /dev/uio*
  ls: cannot access '/dev/uio*': No such file or directory

おお、自由自在!

* dtbocfg.rb を使う [#l12bda56]

 LANG:console
 $ jed dtbocfg.rb
  - CONFIG_OF_OVERLAY_PATH = "/config/device-tree/overlays/"
  + CONFIG_PATH = "/sys/kernel/config/"
  + CONFIG_OF_OVERLAY_PATH = "/sys/kernel/config/device-tree/overlays/"
  + DTBOCFG_KO_PATH = File.join(File.expand_path(File.dirname(__FILE__)), 'dtbocfg.ko')
  ...
    def initialize(device_name)
  +   insmod unless File.exists? CONFIG_OF_OVERLAY_PATH
  +
      @device_name              = device_name
      @device_tree_overlay_path = CONFIG_OF_OVERLAY_PATH + device_name
      @debug                    = false
    end
  
  + def insmod
  +   system "modprobe configfs" unless File.exists? CONFIG_PATH
  +   system "insmod #{DTBOCFG_KO_PATH}" unless File.exists? CONFIG_OF_OVERLAY_PATH
  + end
  +
    def create
 $ chmod u+x dtbocfg.rb
 $ sudo dtbocfg.rb --install accesstest -dts accesstest-uio.dts
  sudo: dtbocfg.ko: command not found
 $ ruby 
  -bash: ruby: command not found
 $ sudo apt install ruby
 $ sudo dtbocfg.rb --install accesstest -dts accesstest-uio.dts
 $ sudo ruby dtbocfg.rb --install accesstest --dts accesstest-uio.dts
 $ ls /dev/uio*
  /dev/uio0
 $ sudo ruby dtbocfg.rb --stop accesstest
 $ ls /dev/uio0
  ls: cannot access '/dev/uio0': No such file or directory
 $ sudo cp dtbocfg.rb /usr/local/bin
 $ sudo cp dtbocfg.ko /usr/local/bin
 $ alias dtbocfg="sudo ruby /usr/local/bin/dtbocfg.rb"
 $ dtbocfg --start accesstest
 $ ls /dev/uio0
  /dev/uio0
 $ cat >> ~/.bashrc
 alias dtbocfg="sudo ruby /usr/local/bin/dtbocfg.rb"
 ^D
 $

コマンド一発で直接 dts を読み込めて、とても便利


* カーネルに含めてしまいたい? [#xaa1ba5a]

modprobe や insmode をしたくなければカーネルに含めてしまえば良い
modprobe や insmod をしたくなければカーネルに含めてしまえば良い

configfs の modprobe が必要になるのは、
カーネル設定でモジュールを選ぶ際に {M} としていたため。
これを {*} にしたところ、modprobe configfs は必要なくなります。
カーネル設定でモジュールを選ぶ際に {M} としていたため。~
これを {*} にすれば、modprobe configfs は必要なくなります。

dtbocfg をカーネルモジュールとするには、~
同様に dtbocfg をカーネルモジュールとするには、、、~
http://manual.atmark-techno.com/dist/atmark-dist_developers_guide_ja-1.0.7/ch11 ~
のようにすればいいみたい。
のようにすればいいみたい?

Makefile が黒魔術だ。

後で調べる。
* コメント・質問 [#ta227d68]

#article_kcaptcha


Counter: 9549 (from 2010/06/03), today: 2, yesterday: 2