BBBではcape managerというので、周辺I/Oの設定をおこないます。BBBに限らず、マイコンボードではI/Oピンが限られているし、割込みリソースも潤沢とはいえないので、機能を必要に応じて起動、割当てすることによって、ユーザー毎に必要なI/Oを確保しようという仕組みです。
確認方法は以下の通りで、デフォルトでは次のようになっている。
root@beaglebone:~# cat /sys/devices/bone_capemgr.9/slots 0: 54:PF--- 1: 55:PF--- 2: 56:PF--- 3: 57:PF--- 4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G 5: ff:P-O-L Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI
設定変更は、/boot/uEnv.txtで行う。以下のケースではHDMIをdisableとし、UARTをenableにしている。特に、UARTに関してはコメント文に書いてないので良くわすれる。書式はv3.8.xとv4.0で若干異なる。
余談であるが、UART3は出力専用となっており、RXピンが存在しない。また、UART0はピンヘッダではなく、J1に接続されている。
slotファイルに動的にslot番号を書き込んで増やせるという情報もあるが、私はresource busyになって上手くいかなかった。
cape_enable=capemgr.enable_partno=BB-UART1,BB-UART2,BB-UART4,BB-UART5 cape_disable=capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN,BB-BONE-EMMC-2G
リブート後次のように変化していれば意図した設定になっている。上手くいかないときは起動時のlogを確認しましょう。
root@beaglebone:/lib/firmware# cat /sys/devices/platform/bone_capemgr/slots 0: PF---- -1 1: PF---- -1 2: PF---- -1 3: PF---- -1 4: P-O-L- 1 Override Board Name,00A0,Override Manuf,BB-UART1 5: P-O-L- 0 Override Board Name,00A0,Override Manuf,BB-UART2 6: P-O-L- 2 Override Board Name,00A0,Override Manuf,BB-UART4 7: P-O-L- 3 Override Board Name,00A0,Override Manuf,BB-UART5
予め用意されているdtbファイルでは、pull up/downなどは設定出来ないので、任意の設定にしたい場合は、自前で用意する必要がある。特に、boot configurationなどに利用されている一部のピンで、外部回路でpull up/downを行うと、起動しなくなったりする場合があるので、こういった場合に有用だ。
dtbファイルはdtsファイルと呼ばれるテキストファイルと、dtcコマンドを用いて相互に変換することができる。
dtb -> dts
dtc -I dtb -O dts am335x-boneblack.dtb > /root/am335x-boneblack.dts
dts -> dtb
dtc -O dtb -o BB-SPI1-01-00A0.dtbo -b 0 -@ BB-SPI1-01-00A0.dts
ちなみに、dtbファイルを読み込ませるタイミングは以下の3通りがある。1,2の方法を使う場合、mkinitramfsでinitrdを作り直しておく必要がある。
AM335xの各I/Oピンの設定はTIのPinMuxUtilityを用いて、GUIで行う事が出来る。
現在、ダウンロードして利用するソフトと、オンラインで利用するタイプがある。オンラインで利用するタイプはmyTIのアカウント登録が必要である。料金については何れも無料。
ピン割り当てがコンフリクトしているものは、その旨表示が出るので、エラーが無い状態に設定をして、outputタブを開くとgenerated filesの項目にソースファイルが出来上がっている。
Cのソースと、devicetree.txtというファイルが含まれているが、このファイルからdtsファイルに紐付ける方法が不明だったので、この方法は保留とした。
参考:http://wiki.sharedcircuits.com/index.php/BeagleBone_Black
dtsファイルを作るスクリプトや、webページが公開されているので、これを利用することにした。
1ピンづつしか指定できないので、必要なピン数分取得したのち、マージした。
作成したファイルを参考までに置いておく。
BB-MYIO-00A0.dts
BB-MYIO-00A0.dtbo
上記のように作成したdtboファイルを/etc/firmware以下に置いておき、/etc/default/capemgrで指定した。
# Options to pass to capemgr CAPE=BB-MYIO
uEnv.txtで指定する方法も試したが、エラーは出ないものの、起動後に/sys/class/gpio/exportにGPIOの番号を書き込んでも、動的にデバイスファイルが作成されなくなる不具合があった。
前述の記述は、2016年5月、多分kernel 4.0.xとかの頃のものだと思います。その後kernelを新しくした所設定方法に変更があったので主に更新点を述べたいと思う。
dtsファイルには特に変更はない。dtcコマンドで次のようにエラーが出るので、no-unit_address_vs_regオプションを指定する必要があった。これは書式の問題のような気がするがオプションで下位互換性が提供されているようなので調べていない。
root@beaglebone:~# dtc -O dtb -o BB-MYIO-00A0.dtbo -b 0 -@ BB-MYIO-00A0.dts BB-MYIO-00A0.dtbo: Warning (unit_address_vs_reg): Node /fragment@0 has a unit name, but no reg property BB-MYIO-00A0.dtbo: Warning (unit_address_vs_reg): Node /fragment@1 has a unit name, but no reg property root@beaglebone:~# dtc -W no-unit_address_vs_reg -O dtb -o BB-MYIO-00A0.dtbo -b 0 -@ BB-MYIO-00A0.dts
動的に変更は出来なくなった模様。
Kernel Overlays are going bye-bye, too many bugs, too many race conditions, no kernel maintainers interested. We've said our farewells and U-Boot Overlays is the way forward: https://elinux.org/Beagleboard:BeagleBoneBlack_Debian#U-Boot_Overlays With multiple parties working on the U-Boot infrastructure.
設定状況は次のようにして確認できるようだ。
root@beaglebone:/sys/devices/platform/bone_capemgr# /opt/scripts/tools/version.sh git:/opt/scripts/:[1aa73453b2c980b75e31e83dab7dd8b6696f10c7] eeprom:[A335BNLTEIA01609BBBK03BB] model:[TI_AM335x_BeagleBone_Black] dogtag:[BeagleBoard.org Debian Image 2018-10-07] bootloader:[eMMC-(default)]:[/dev/mmcblk1]:[U-Boot 2018.09-00002-g0b54a51eee]:[location: dd MBR] kernel:[4.14.71-ti-r80] nodejs:[v6.14.4] uboot_overlay_options:[enable_uboot_overlays=1] uboot_overlay_options:[uboot_overlay_addr0=/lib/firmware/BB-UART1-00A0.dtbo] uboot_overlay_options:[uboot_overlay_addr1=/lib/firmware/BB-UART2-00A0.dtbo] uboot_overlay_options:[uboot_overlay_addr2=/lib/firmware/BB-UART4-00A0.dtbo] uboot_overlay_options:[uboot_overlay_addr3=/lib/firmware/BB-UART5-00A0.dtbo] uboot_overlay_options:[uboot_overlay_addr4=/lib/firmware/BB-MYIO-00A0.dtbo] uboot_overlay_options:[disable_uboot_overlay_video=1] uboot_overlay_options:[disable_uboot_overlay_audio=1] uboot_overlay_options:[disable_uboot_overlay_adc=1] uboot_overlay_options:[uboot_overlay_pru=/lib/firmware/AM335X-PRU-RPROC-4-14-TI-00A0.dtbo] uboot_overlay_options:[enable_uboot_cape_universal=1] pkg check: to individually upgrade run: [sudo apt install --only-upgrade] pkg:[bb-cape-overlays]:[4.4.20180928.0-0rcnee0~stretch+20180928] pkg:[bb-wl18xx-firmware]:[1.20180517-0rcnee0~stretch+20180517] pkg:[kmod]:[23-2rcnee1~stretch+20171005] pkg:[librobotcontrol]:[1.0.3-git20181005.0-0rcnee0~stretch+20181005] pkg:[firmware-ti-connectivity]:[20170823-1rcnee1~stretch+20180328] groups:[debian : debian adm kmem dialout cdrom floppy audio dip video plugdev users systemd-journal i2c bluetooth netdev cloud9ide gpio pwm eqep admin spi tisdk weston-launch xenomai] cmdline:[console=ttyO0,115200n8 bone_capemgr.uboot_capemgr_enabled=1 root=/dev/mmcblk1p1 ro rootfstype=ext4 rootwait coherent_pool=1M net.ifnames=0 quiet] dmesg | grep pinctrl-single [ 1.107493] pinctrl-single 44e10800.pinmux: 142 pins at pa f9e10800 size 568 [ 1.181570] pinctrl-single 44e10800.pinmux: pin PIN51 already requested by ocp:bs_pinmode_pinmux; cannot claim for ocp:P8_34_pinmux [ 1.193558] pinctrl-single 44e10800.pinmux: pin-51 (ocp:P8_34_pinmux) status -22 [ 1.201021] pinctrl-single 44e10800.pinmux: could not request pin 51 (PIN51) from group pinmux_P8_34_default_pin on device pinctrl-single [ 1.224168] pinctrl-single 44e10800.pinmux: pin PIN46 already requested by ocp:bs_pinmode_pinmux; cannot claim for ocp:P8_39_pinmux [ 1.236130] pinctrl-single 44e10800.pinmux: pin-46 (ocp:P8_39_pinmux) status -22 [ 1.243591] pinctrl-single 44e10800.pinmux: could not request pin 46 (PIN46) from group pinmux_P8_39_default_pin on device pinctrl-single [ 1.267335] pinctrl-single 44e10800.pinmux: pin PIN45 already requested by ocp:bs_pinmode_pinmux; cannot claim for ocp:P8_42_pinmux [ 1.279287] pinctrl-single 44e10800.pinmux: pin-45 (ocp:P8_42_pinmux) status -22 [ 1.286747] pinctrl-single 44e10800.pinmux: could not request pin 45 (PIN45) from group pinmux_P8_42_default_pin on device pinctrl-single [ 1.310766] pinctrl-single 44e10800.pinmux: pin PIN40 already requested by ocp:bs_pinmode_pinmux; cannot claim for ocp:P8_45_pinmux [ 1.322714] pinctrl-single 44e10800.pinmux: pin-40 (ocp:P8_45_pinmux) status -22 [ 1.330177] pinctrl-single 44e10800.pinmux: could not request pin 40 (PIN40) from group pinmux_P8_45_default_pin on device pinctrl-single [ 1.352225] pinctrl-single 44e10800.pinmux: pin PIN41 already requested by ocp:bs_pinmode_pinmux; cannot claim for ocp:P8_46_pinmux [ 1.364157] pinctrl-single 44e10800.pinmux: pin-41 (ocp:P8_46_pinmux) status -22 [ 1.371615] pinctrl-single 44e10800.pinmux: could not request pin 41 (PIN41) from group pinmux_P8_46_default_pin on device pinctrl-single [ 1.393321] pinctrl-single 44e10800.pinmux: pin PIN30 already requested by ocp:bs_pinmode_pinmux; cannot claim for ocp:P9_12_pinmux [ 1.405263] pinctrl-single 44e10800.pinmux: pin-30 (ocp:P9_12_pinmux) status -22 [ 1.412723] pinctrl-single 44e10800.pinmux: could not request pin 30 (PIN30) from group pinmux_P9_12_default_pin on device pinctrl-single dmesg | grep gpio-of-helper [ 1.119393] gpio-of-helper ocp:cape-universal: ready END
uEnv.txtへの設定は次のような書式に変更となった。
uboot_overlay_addr0=/lib/firmware/BB-UART1-00A0.dtbo uboot_overlay_addr1=/lib/firmware/BB-UART2-00A0.dtbo uboot_overlay_addr2=/lib/firmware/BB-UART4-00A0.dtbo uboot_overlay_addr3=/lib/firmware/BB-UART5-00A0.dtbo uboot_overlay_addr4=/lib/firmware/BB-MYIO-00A0.dtbo
デバイスは/dev/watchdogとして見えているので、これに対して何らかの書込みを行う事でenableとなる。
以後60秒以内に次の文字を書き込まないと、システムがリセットされる。
'V'を書き込むことでWDTをdisableに設定することが出来る。
/dev/watchdogに何か文字を書き込んで、closeするときにenableのままだと次のメッセージが出る。
watchdog: watchdog0: watchdog did not stop!
shellと同様の操作に加え、ioctlによりより細かな操作を行うことが出来る。
詳しくはこちら
タイムアウト値の変更などを行う場合は、こちらの方法を使う必要がある。
例)
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <sys/ioctl.h> #include <unistd.h> #include <linux/watchdog.h> void main(){ int fd=open("/dev/watchdog", O_WRONLY); if(fd < 0) perror("open"); for (int8_t i=0; i <10; i++) { if(ioctl(fd, WDIOC_KEEPALIVE, 0) < 0) perror("ioctl"); sleep(10); } // disable WDT int opt=WDIOS_DISABLECARD; if(ioctl(fd, WDIOC_SETOPTIONS, &opt) < 0) perror("ioctl"); close(fd); }