= RS232C x4 Capeの作成 = [http://beagleboard.org/Products/BeagleBone%20Black BeagleBone Black]上のCPUには6個のUARTが載っていて、そのうちの1つはシリアルコンソール用、それ以外の5本が拡張IOで使用可能になっている。 (厳密には、3番ポートがTxのみなので4.5本だが、、、)[[br]] これを使って、[http://japan.moxa.com/product/NPort_5410.htm MOXAの4ポートシリアルコンバータ]の代わりにならないかということで作り始めた。+αとして単体でEPICS動作が可能なので、IOCの分散にもつながる。 == Hardware == [http://beagleboard.org/Products/BeagleBone%20Black BeagleBone Black]側はUART1,2,4,5を使うことにし、CTS/RTSはつながない。[[br]] EEPROMはつけておくことにする。 === HDMI OFF === 今回のHWでは、UART5とHDMI出力が被ってしまう。今回は画面が必要ないので、HDMI出力を停止させることにした。[[br]] HDMI出力の確認は、 {{{ root@beaglebone:/media/card# cat /sys/devices/bone_capemgr.8/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 }}} で行う。[[br]] 5にHDMIのモジュールが読み込まれているのがわかる。"P-O-L"の"L"が"Load"ということらしく、これが消えればいいらしい。[[br]] 設定は、ブートローダーで行うので、boot領域をmountして、uEnv.txtを書き換える。 {{{ root@beaglebone:~/cape/UARTx4# df Filesystem 1K-blocks Used Available Use% Mounted on rootfs 3369444 1641652 1553304 52% / /dev/root 3369444 1641652 1553304 52% / devtmpfs 255228 0 255228 0% /dev tmpfs 255356 0 255356 0% /dev/shm tmpfs 255356 232 255124 1% /run tmpfs 255356 0 255356 0% /sys/fs/cgroup tmpfs 255356 232 255124 1% /etc/machine-id tmpfs 255356 0 255356 0% /tmp /dev/mmcblk0p1 72102 59252 12850 83% /media/card root@beaglebone:~/cape/UARTx4# cd /media/card/ root@beaglebone:/media/card# ls App Drivers LICENSE.txt README.md autorun.inf uEnv.txt Docs ID.txt MLO START.htm u-boot.img root@beaglebone:/media/card# vi uEnv.txt optargs=quiet ↓ optargs=quiet capemgr.disable_partno=BB-BONELT-HDMI,BB-BONELT-HDMIN }}} 設定を書き換えたらreboot。[[br]] reboot後は、画面に何もでなくなるので注意すること。[[br]] sshで他のマシンからログインして、状態を確認。 {{{ root@beaglebone:/media/card# cat /sys/devices/bone_capemgr.8/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-- Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI 6: ff:P-O-- Bone-Black-HDMIN,00A0,Texas Instrument,BB-BONELT-HDMIN }}} この状態になっていればOK。 === Cape回路図 === 今回の回路は、各uartにRS232CのレベルコンバータとEEPROMを載せるだけの簡単なものにする。 [[Image(BBBSerialCape.png,300px)]] [[Image(BBBSerialCape_board.png,300px)]] == firmware == firmwareのひな形は/lib/firmwareにあったので、それを編集して作成。 {{{ /* * Copyright (C) 2013 Tetsuya Michikawa * * BeagleBone Black UART 1,2,4,5 used RS232c cape */ /dts-v1/; /plugin/; / { compatible = "ti,beaglebone", "ti,beaglebone-black"; /* identification */ part-number = "cape-bone-uartx4"; version = "00A0"; /* state the resources this cape uses */ exclusive-use = /* the pin header uses */ "P9.24", /* uart1_txd */ "P9.26", /* uart1_rxd */ "P9.21", /* uart2_txd */ "P9.22", /* uart2_rxd */ "P9.13", /* uart4_txd */ "P9.11", /* uart4_rxd */ "P8.37", /* uart5_txd */ "P8.38", /* uart5_rxd */ /* the hardware ip uses */ "uart1", "uart2", "uart4", "uart5"; fragment@0 { target = <&am33xx_pinmux>; __overlay__ { bb_uart1_pins: pinmux_bb_uart1_pins { pinctrl-single,pins = < 0x180 0x20 /* P9.26 uart1_rxd.uart1_rxd INPUT */ 0x184 0x20 /* P9.24 uart1_txd.uart1_txd OUTPUT */ >; }; bb_uart2_pins: pinmux_bb_uart2_pins { pinctrl-single,pins = < 0x150 0x21 /* P9.22 spi0_sclk.uart2_rxd | MODE1 */ 0x154 0x01 /* P9.21 spi0_d0.uart2_txd | MODE1 */ >; }; bb_uart4_pins: pinmux_bb_uart4_pins { pinctrl-single,pins = < 0x070 0x26 /* P9.11 gpmc_wait0.uart4_rxd | MODE6 */ 0x074 0x06 /* P9.13 gpmc_wpn.uart4_txd | MODE6 */ >; }; bb_uart5_pins: pinmux_bb_uart5_pins { pinctrl-single,pins = < /* the uart pins */ 0x0C4 0x24 /* P8.38 lcd_data9.uart5_rxd | MODE4 */ 0x0C0 0x04 /* P8.37 lcd_data8.uart5_txd | MODE4 */ >; }; }; }; fragment@1 { target = <&uart2>; /* really uart1 */ __overlay__ { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&bb_uart1_pins>; }; }; fragment@2 { target = <&uart3>; /* really uart2 */ __overlay__ { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&bb_uart2_pins>; }; }; fragment@3 { target = <&uart5>; /* really uart4 */ __overlay__ { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&bb_uart4_pins>; }; }; fragment@4 { target = <&uart6>; /* really uart5 */ __overlay__ { status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&bb_uart5_pins>; }; }; }; }}} このファイルをコンパイルして、firmwareを作成。[[br]] これを/lib/firmwareにコピーして、ロードさせてみる。 {{{ root@beaglebone:~/cape/UARTx4# dtc -O dtb -o cape-bone-uartx4-00A0.dtbo -b 0 -@ cape-bone-uartx4-00A0.dts root@beaglebone:~/cape/UARTx4# cp cape-bone-uartx4-00A0.dtbo /lib/firmware root@beaglebone:~/cape/UARTx4# cd /lib/firmware root@beaglebone:/lib/firmware# echo cape-bone-uartx4 > /sys/devices/bone_capemgr.8/slots }}} ここで何もでなければOKだけど、ロードできないとエラーが出る。エラーの内容はdmesgで出力されるので、それを確認してエラーを修正後、再度実行。 {{{ root@beaglebone:/lib/firmware# cat /sys/devices/bone_capemgr.8/slots 0: 54:PF--- 1: 55:PF--- 2: 56: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 6: ff:P-O-L Override Board Name,00A0,Override Manuf,cape-bone-uartx4 }}} == EEPROM == Capeに載せるEEPROMを作成する。 === EEPROMへのアクセス === その前に、I2C2でEEPROMが認識されるかをチェックする。今回はEEPROMにATMEL AT24C256Bを使った。BBBはIO電圧が3.3Vなので、そこにつなぐICも3.3V対応のものを使う必要があるので注意。 [[Image(http://papermint-designs.com/community/files/images/eeprom-circuit.preview.png)]] 画像の実験回路をブレッドボード等で作成して、初めはSW A0,A1,A2のプルアップ抵抗を接続せずにGNDに接続してみる。[[br]] 回路を作成後、BBBのI2C2 SCL,SDAに接続し、i2cdetectでバススキャンしてみる。 {{{ root@beaglebone:~# i2cdetect -r 1 WARNING! This program can confuse your I2C bus, cause data loss and worse! I will probe file /dev/i2c-1 using read byte commands. I will probe address range 0x03-0x77. Continue? [Y/n] y 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: 50 -- -- -- UU UU UU UU -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- }}} 回路が正しければ、上記のような表示になるはず。ならなければ、どこか回路が間違っているので修正する。[[br]] 次にEEPROMへの読み書きができるかを実験。[[br]] まず、EEPROMにアクセスするためのデバイスインターフェイス(?といえばいいのかな)を作成。 {{{ root@beaglebone:~# echo 24c256 0x50 > /sys/bus/i2c/devices/i2c-1/new_device root@beaglebone:~# ls /sys/bus/i2c/devices 0-0024 0-0050 1-0050 1-0054 1-0055 1-0056 1-0057 i2c-0 i2c-1 root@beaglebone:~# dmesg : [ 5404.713106] at24 1-0050: 32768 byte 24c256 EEPROM, writable, 1 bytes/write [ 5404.713545] i2c i2c-1: new_device: Instantiated device 24c256 at 0x50 }}} 1-0050がEEPROMにアクセスするためのインターフェイスになる。[[br]] {{{ root@beaglebone:~ # cd /sys/bus/i2c/devices/1-0050 root@beaglebone:/sys/bus/i2c/devices/1-0050# ls -la total 0 drwxr-xr-x 3 root root 0 Oct 22 02:19 . drwxr-xr-x 9 root root 0 Jan 1 2000 .. lrwxrwxrwx 1 root root 0 Oct 22 02:19 driver -> ../../../../../bus/i2c/drivers/at24 -rw------- 1 root root 32768 Oct 22 02:22 eeprom -r--r--r-- 1 root root 4096 Oct 22 02:22 modalias -r--r--r-- 1 root root 4096 Oct 22 02:22 name drwxr-xr-x 2 root root 0 Oct 22 02:22 power lrwxrwxrwx 1 root root 0 Oct 22 02:19 subsystem -> ../../../../../bus/i2c -rw-r--r-- 1 root root 4096 Oct 22 02:19 uevent root@beaglebone:/sys/bus/i2c/devices/1-0050# }}} EEPROMへのデータの書き込み、読み込みはeepromファイルにアクセスすることで行われる。 {{{ root@beaglebone:/sys/bus/i2c/devices/1-0050# echo "hoge" > eeprom root@beaglebone:/sys/bus/i2c/devices/1-0050# cat eeprom | hexdump -C 00000000 68 6F 67 65 ff ff ff ff ff ff ff ff ff ff ff ff |hoge | * }}} 今回の実験ではi2cアドレス0x50を使用して実験しているが、'''実際にcapeとして使用する場合には、i2cアドレス0x54~0x57の範囲内にしないとcapeとして認識されないので注意。''' === EEPROMの作成 === EEPROMのイメージデータは、firmwareファイルから生成することはできないので、別の定義ファイルから作成するしかないみたい。[[br]] EEPROMのフォーマットは規定されているが、それを作る方法が確立しているわけではないみたい。[[br]]色々なページでも、自作のプログラムでひな形を作ったりしている。一応、正式な方法としてはJSON形式のファイルを作成して、それをコンバートして作る方法が紹介されている。[[br]] 変換プログラム自体はjavascriptで書かれているが、OSにはインストールされていないのでどこかから持ってくる必要がある。今回は[https://bitbucket.org/intelligentagent/replicape/src/28dfc97a7230/eeprom?at=master ここ]から、eeprom.jsとbone.jsをとってきた。[[br]] このスクリプトを使って変換する。ちなみに、EEPROMの定義ファイルは、cape-bone-uartx4-00A0.jsonとした。 {{{ root@beaglebone:~/cape/UARTx4/eeprom# node ./eeprom.js -w cape-bone-uartx4-00A0.json }}} JSON形式の設定ファイルの内容は以下の通り。[[br]] 注意点として、partNumberとversionはfirmwareの設定内容(ファイル名?)と同じにしておかないといけない。これをキーにして対応するfirmwareを検索するらしい。 {{{ { "uartx4.eeprom": { "type": "cape", "header": "aa5533ee", "formatRev": "A0", "boardName": "RS232C x4 Cape", "version": "00A0", "manufacturer": "KEK cERL CTRL", "partNumber": "cape-bone-uartx4", "numPins": 8, "serialNumber": "0000-0000-0001", "currentVDD_3V3EXP": 250, "currentVDD_5V": 250, "currentSYS_5V": 1000, "DCSupplied": 1000, "mux": { "P9_26": { "used": "used", "direction": "in", "pullup": "disabled", "slew": "fast", "rx": "enabled", "mode": 0, "function": "uart1_rxd" }, "P9_24": { "used": "used", "direction": "out", "pullup": "disabled", "slew": "fast", "rx": "disabled", "mode": 0, "function": "uart1_txd" }, "P9_22": { "used": "used", "direction": "in", "pullup": "disabled", "slew": "fast", "rx": "enabled", "mode": 1, "function": "uart2_rxd" }, "P9_21": { "used": "used", "direction": "out", "pullup": "disabled", "slew": "fast", "rx": "disabled", "mode": 1, "function": "uart2_txd" }, "P9_11": { "used": "used", "direction": "in", "pullup": "disabled", "slew": "fast", "rx": "enabled", "mode": 6, "function": "uart4_rxd" }, "P9_13": { "used": "used", "direction": "out", "pullup": "disabled", "slew": "fast", "rx": "disabled", "mode": 6, "function": "uart4_txd" }, "P8_38": { "used": "used", "direction": "in", "pullup": "disabled", "slew": "fast", "rx": "enabled", "mode": 4, "function": "uart5_rxd" }, "P8_37": { "used": "used", "direction": "out", "pullup": "disabled", "slew": "fast", "rx": "disabled", "mode": 4, "function": "uart5_txd" } } } } }}} 変換したEEPROMイメージをダンプするとこんな感じ。 {{{ root@beaglebone:~/cape/UARTx4/eeprom# hexdump -C uartx4.eeprom 00000000 aa 55 33 ee 41 30 52 53 32 33 32 43 20 78 34 20 |.U3.A0RS232C x4 | 00000010 43 61 70 65 00 00 00 00 00 00 00 00 00 00 00 00 |Cape............| 00000020 00 00 00 00 00 00 30 30 41 30 4b 45 4b 20 63 45 |......00A0KEK cE| 00000030 52 4c 20 43 54 52 4c 00 00 00 63 61 70 65 2d 62 |RL CTRL...cape-b| 00000040 6f 6e 65 2d 75 61 72 74 78 34 00 08 30 30 30 30 |one-uartx4..0000| 00000050 2d 30 30 30 30 2d 30 30 a0 29 c0 09 00 00 00 00 |-0000-00.)......| 00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a0 28 |...............(| 00000070 c0 08 00 00 00 00 00 00 00 00 00 00 a0 2e c0 0e |................| 00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| * 000000c0 00 00 c0 0c a0 2c 00 00 00 00 00 00 00 00 00 00 |.....,..........| 000000d0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 000000e0 00 00 00 00 00 00 00 00 00 00 00 00 00 fa 00 fa |................| 000000f0 03 e8 03 e8 |....| 000000f4 }}} これをEEPROMに書き込んで、Capeを起動すれば、自動的に対応するfirmwareが読み込まれる。[[br]] EEPROMがI2C2の0x54に接続されている場合には、以下のコマンドで書き込みができる。 {{{ root@beaglebone:~/cape/UARTx4/eeprom# cat uartx4.eeprom > /sys/bus/i2c/devices/1-0054/eeprom }}} == 実機テスト == 実際にCapeを試作して実装してみる。 {{{ root@beaglebone:~# cat /sys/devices/bone_capemgr.8/slots 0: 54:PF--- 1: 55:PF--- 2: 56:PF--- 3: 57:P---L RS232C x4 Cape,00A0,KEK cERL CTRL,cape-bone-uartx4 4: ff:P-O-L Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G 5: ff:P-O-- Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI 6: ff:P-O-- Bone-Black-HDMIN,00A0,Texas Instrument,BB-BONELT-HDMIN }}} I2Cアドレスの設定によって、表示されるスロットは変わるが、0x57の位置に今回作成したcapeがロードされたことがわかる。[[br]] dmesgで詳細を確認。 {{{ [ 0.000000] Booting Linux on physical CPU 0x0 [ 0.000000] Initializing cgroup subsys cpu [ 0.000000] Linux version 3.8.13 (koen@rrMBP) (gcc version 4.7.3 20130205 (prerelease) (Linaro GCC 4.7-2013.02-01) ) #1 SMP Wed Aug 14 16:25:00 CEST 2013 [ 0.000000] CPU: ARMv7 Processor [413fc082] revision 2 (ARMv7), cr=50c5387d [ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache : [ 0.244885] loop: module loaded [ 0.245009] at24 0-0050: 32768 byte 24c256 EEPROM, writable, 1 bytes/write [ 0.245089] at24 1-0054: 32768 byte 24c256 EEPROM, writable, 1 bytes/write [ 0.245159] at24 1-0055: 32768 byte 24c256 EEPROM, writable, 1 bytes/write [ 0.245228] at24 1-0056: 32768 byte 24c256 EEPROM, writable, 1 bytes/write [ 0.245298] at24 1-0057: 32768 byte 24c256 EEPROM, writable, 1 bytes/write [ 0.252493] bone-capemgr bone_capemgr.8: Baseboard: 'A335BNLT,0A5C,2713BBBK6962' [ 0.252534] bone-capemgr bone_capemgr.8: compatible-baseboard=ti,beaglebone-black [ 0.252607] bone-capemgr bone_capemgr.8: Skipping disabled cape with part# BB-BONELT-HDMI [ 0.252690] bone-capemgr bone_capemgr.8: Skipping disabled cape with part# BB-BONELT-HDMIN [ 0.282744] bone-capemgr bone_capemgr.8: slot #0: No cape found [ 0.319851] bone-capemgr bone_capemgr.8: slot #1: No cape found [ 0.356959] bone-capemgr bone_capemgr.8: slot #2: No cape found [ 0.387222] bone-capemgr bone_capemgr.8: slot #3: 'RS232C x4 Cape,00A0,KEK cERL CTRL,cape-bone-uartx4' [ 0.387406] bone-capemgr bone_capemgr.8: slot #4: specific override [ 0.387447] bone-capemgr bone_capemgr.8: bone: Using override eeprom data at slot 4 [ 0.387475] bone-capemgr bone_capemgr.8: slot #4: 'Bone-LT-eMMC-2G,00A0,Texas Instrument,BB-BONE-EMMC-2G' [ 0.387608] bone-capemgr bone_capemgr.8: slot #5: specific override [ 0.387644] bone-capemgr bone_capemgr.8: bone: Using override eeprom data at slot 5 [ 0.387672] bone-capemgr bone_capemgr.8: slot #5: 'Bone-Black-HDMI,00A0,Texas Instrument,BB-BONELT-HDMI' [ 0.387809] bone-capemgr bone_capemgr.8: slot #6: specific override [ 0.387845] bone-capemgr bone_capemgr.8: bone: Using override eeprom data at slot 6 [ 0.387873] bone-capemgr bone_capemgr.8: slot #6: 'Bone-Black-HDMIN,00A0,Texas Instrument,BB-BONELT-HDMIN' [ 0.388152] bone-capemgr bone_capemgr.8: Skipping loading of disabled cape with part# BB-BONELT-HDMI [ 0.388222] bone-capemgr bone_capemgr.8: Skipping loading of disabled cape with part# BB-BONELT-HDMIN [ 0.388534] bone-capemgr bone_capemgr.8: initialized OK. : [ 4.800832] bone-capemgr bone_capemgr.8: slot #3: dtbo 'cape-bone-uartx4-00A0.dtbo' loaded; converting to live tree [ 4.801128] bone-capemgr bone_capemgr.8: slot #3: #5 overlays [ 4.804422] 48022000.serial: ttyO1 at MMIO 0x48022000 (irq = 89) is a OMAP UART1 [ 4.806330] 48024000.serial: ttyO2 at MMIO 0x48024000 (irq = 90) is a OMAP UART2 [ 4.809856] 481a8000.serial: ttyO4 at MMIO 0x481a8000 (irq = 61) is a OMAP UART4 [ 4.811270] 481aa000.serial: ttyO5 at MMIO 0x481aa000 (irq = 62) is a OMAP UART5 [ 4.811678] bone-capemgr bone_capemgr.8: slot #3: Applied #5 overlays. [ 4.811731] bone-capemgr bone_capemgr.8: slot #4: Requesting firmware 'cape-bone-2g-emmc1.dtbo' for board-name 'Bone-LT-eMMC-2G', version '00A0' [ 4.811751] bone-capemgr bone_capemgr.8: slot #4: dtbo 'cape-bone-2g-emmc1.dtbo' loaded; converting to live tree [ 4.812171] bone-capemgr bone_capemgr.8: slot #4: #2 overlays }}} UART1,2,4,5がそれぞれttyO1,ttyO2,ttyO4,ttyO5になっていることが確認できた。[[br]] 実際に通信して確かめてみる。[[br]] RS232Cクロスケーブルをポート1と2につなぎ、シリアル通信プログラム minicom で実験。タミーナルを2つ立ち上げて、それぞれでminicomを実行する。 {{{ root@beaglebone:~# minicom -D /dev/ttyO1 -b 115200 }}} {{{ root@beaglebone:~# minicom -D /dev/ttyO2 -b 115200 }}} minicomが起動したら、片方のターミナル画面から適当な文字を入力すると、もう片方のターミナルに入力した文字が表示されれば成功。表示されないようなら、配線をチェックするか、違うRS232Cポートにケーブルをつないでいないかをチェックする。 == 参照HP == [http://papermint-designs.com/community/node/338 NULLCape. How to Roll your own BeagleBone Capes (Part II) | Community Papermint Designs][[br]] [https://groups.google.com/forum/#!topic/beagleboard/pf1MNKptqS0 Where are the serial ttyO1,2,3,4? - Google グループ][[br]] [http://circuitco.com/support/index.php?title=Cape_Expansion_Headers Cape Expansion Headers - Circuitco Wiki Support][[br]] [http://www.logicsupply.com/blog/2013/07/18/disabling-the-beaglebone-black-hdmi-cape/ Disabling the BeagleBone Black HDMI Cape Logic Supply Blog][[br]] [http://azkeller.com/blog/?p=62 Adventures in BeagleBone Cape EEPROMs | K.Keller's Blog][[br]]