2015年12月25日金曜日

VirtualBoxのアップデート後になぜかGuest AdditionsのCDがマウントできない

VirtualBoxのGuest AdditionsはVirtualBoxアップデートのたびに更新しないといけないですが、いつからか、メニューからマウスでCDを挿入してもマウント失敗するようになってしまいました。

https://forums.ubuntulinux.jp/viewtopic.php?id=13601

にあるように、sudo mount /dev/sr0 /mnt で手動マウントすればうちでは大丈夫でした。

2015年8月21日金曜日

小ネタ: vivadoのアンインストール

vivadoのバージョンを巻き戻そうと思ってアンインストールしようと思ったのですが、マニュアルを見ると「プログラムグループからアンインストールを選んで…」とか書いてあります。

Linuxの生xwindowでそんなの無いよ!という環境ではコマンドラインでアンインストーラ起動だそうです。

[installPath]/.xinstall/Vivado_2015.1/ xsetup –Uninstall

2015年8月10日月曜日

VirtualBoxで仮想シリアルポート(com0com)を使う

最終的にはzynqでシリアルポートを使うソフトを作りたいんですが、開発はVirtualBox内のLinuxが楽ちんなのでそっちでやっています。

というわけで、VirtualBoxのシリアルポートを外に取り出してあれこれする方法。

パイプ→ethernetというルートでもダメではないんですが、windowsにはせっかくcom0comという素晴らしい仮想シリアルドライバがあるのでこれを使います。


com0comを使うと仮想シリアルポートのペアをwindows内に好きなだけ作ることができて、ペア間はクロスケーブルで繋がっているかのように見えます。
注意点は、フレーミングエラーやビットレート設定違いのときの挙動なんかはエミュレートされてないので正常動作ルートのみが開発可能、という点です。


まず64bitのwindows8だとcom0comの最新(現時点で3.0.0.0)は署名なしなので拒否られてしまいます。無理に最新版でなくても全く問題ないと思うので、ひとつ前の2.2.2.0にはレジスタード版が用意されているのでそっちを使いましょう。


com0comが無事入ったら、正統派のCUIなど無視してGUIを開いてぽちぽちとポートのペアを作りましょう。ここでは2ペア作りました。

名前はCOM**じゃないと面倒が生じることが多いのでGUI上でリネームしてあります。


そしたらVirtualBox側でこのペアの片側を使うように指定するわけですが、com0comのポートはちと表記に注意点があります。 (参考 http://homepage2.nifty.com/nonnon/Link/Null-Modem-Win8.html)


パス名として \\.\COM17  みたいに書いてあげましょう。

あとはゲスト側で/dev/ttyS0 , ttyS1にアクセスすると、ホスト側のペア(com18とか20)とシリアル通信ができます。

3つ以上使えたらいいのに…

2015年7月29日水曜日

ZYNQのMIO GPIOをLinuxから使う

ZYNQのMIOピンは、わりと制限事項があって割り振り自由度もそう高くないので、だんだんPL部が高機能になってくると最終的にはMIOのどうでもいいピンがデバッグ用に残ったりします。

ZYBOだとMIO7にLEDと、MIO50,51にスイッチが着いてます。

で、このMIO7のLEDをGPIOとして光らそうと思ってえらく苦労したのでメモを残します。



まず、日本人ならほとんどの zynq ユーザーが参考にしてそうな marsee さんの以下の記事
http://marsee101.blog19.fc2.com/blog-entry-2203.html

によると、ベースアドレス0xE000A000以降に必要なレジスタが割り振ってあって、方向指定、アウトイネーブルを1にしたあと出力レジスタのビットを1にすれば良さそうです。
んが、この通りにやっても反応がありませんでした。読み出し方向も全く反応が無く、全レジスタ0が読めるだけです。

Linuxからだと上位1Gの空間にアクセスするのに制限があるのか? とか勘違い迷宮にはまり込んで、LEDドライバを流用したカーネル空間からあれこれトライするも、やっぱりダメです。



ベアメタルでMIOのGPIOを使うサンプルはxilinxにもいろいろあるので、ためしにFSBLのカスタマイズ部分  ( fsbl_hooks.c の FsblHookBeforeHandoff の中 ) に、marseeさんと同じ書き方で
volatile unsigned int* mio_base;
mio_base = 0xe000a000;
*(mio_base + 0x81) = 0x80;
*(mio_base + 0x82) = 0x80;
*(mio_base + 0x10) = 0x80;
と書いてみると、みごとにMIO7のLEDが光ります。


つまりPLのコンフィギュレーションやレジスタの使い方は合っていて、Linuxが起動しちゃうと動作しないわけですから、上記のレジスタ以外の上位概念のせいで動作しなくなっているようです。

テクニカルマニュアル
http://japan.xilinx.com/support/documentation/user_guides/j_ug585-Zynq-7000-TRM.pdf
のgpioセクションをきれいな心で読み返してみると、上位概念は
  • モジュール単位のリセット
  • モジュール単位のクロック
  • 出力ピンのトライステート指定
の3つがあるようです。

今困ってる現象では読み出しもまったく機能せずレジスタが0に見えているので、Linuxがリセットかクロックのどちらかを操作してGPIOモジュールを止めたままにしてるんではないかと思います。



強制的に slcr を操作してモジュールを動かすこともできるかもしれませんが、Linux流のやりかたはLinuxにちゃんと用意されてる gpio-zynq ドライバで初期化する、という方法だと思います。


xilinxドライバ参考資料
http://www.wiki.xilinx.com/Linux+GPIO+Driver
これに加えてxilinx ZYNQ用のGPIOドライバ( gpio-zynq.c )をmenuConfigで有効にしておきます。

dtsにはzynq用ものなら最初からgpioについて書かれてるのでそのままでOKです。


起動すると、特にdmesgにgpioドライバのメッセージはありませんが、なんとなく起動してるっぽくて /sys/class/gpioを見ると gpiochip906 というフォルダが増えました。

が、使い方がよくわからないまま、xilinxの参考資料のとおりに
  >echo 240 > /sys/class/gpio/export
とかやっても特に制御用のgpio204フォルダが出現するわけでもなく、正しく動いてるのかどうかわかりません。

まあ、ドライバは起動してるんだから行けるかな、と思ってここで冒頭のmarseeさんの記事にあったコードを (MIO10ピンを意味する0x400はMIO7相当の0x80に変更して) 実行しても、やっぱり無反応のまま…というところでまた途方にくれていました。



が! その後しばらくぐぐっていたら、xilinxフォーラムに
http://forums.xilinx.com/t5/Embedded-Linux/Zynq-Petalinux-hangs-on-GPIO-access/td-p/645008
という記事があり、一番下の方のデバッグ出力を見ると
GPIOs 906-1023, platform/e000a000.gpio, zynq_gpio:
という箇所があるのを見つけました。906って、さっき出現したgpiochip906と同じです。
つーことは、zynqのmio/emio用gpioモジュールは、ドライバ内ではピン番号906~にマップされてる、てことみたいですね。


それなら! というわけで、MIO7相当の
  >echo 913 > /sys/class/gpio/export
とやってみると、見事にgpio913というフォルダが出現し、その中のdirectionやvalueに1を書き込むとMIO7のLEDが点灯しました。


また、一度このexport操作をすると、後はmarseeさんのコードの通りにレジスタを操作する方法でもLEDのON/OFFが可能でした。

つまり、906以降のどこかのピンに対して最初にexportをしたときにgpioモジュールのクロック供給が開始されてる、てことみたいです。

これでやっと、MIOピンを無駄にせずLinuxからIOとして使えるようになりました。

2015年7月12日日曜日

X1 Carbon SSD交換

新職場で高級ノートのThinkpad X1 carbon (3rd Gen. 2015) を買ってもらったのは良かったのですが、固定資産にならない縛りのためにSSDは増量できず128Gの最低容量でした。

これが、zynqやらVS2013やらやりだすともう足りないのなんの。
速いUSBメモリのextremeにubuntuマシンのHDDイメージを入れたりしてなんとか耐えていましたが、ディスク開き要領3Gとかで常時使うことになってしまって精神衛生上良くないです。ウェアレベリングがあるので壊れはしないと思いますが…

調べてみると、128GモデルはSSDがPCIEx接続じゃないので遅いとか書いてありました。体感ではちょー速いのでさっぱりわかりませんが。


とりあえず開けてみる。スロット部分だけ取れる蓋とか無いですが、簡単に底面がぜんぶ外れるので超簡単。
M2スロットがいっぱいあって、電話用のスロットが空いてるけど当然ここにSSDを挿しても機能しないらしいです。

SSDはSAMSUNGのPM851とかいうシリーズで、型番 MZNTE128HMGR でした。
SATA規格で繋がってるとのことで、500MB/secが最高らしいですが、ベンチマーク結果は
やっぱり速いです。容量さえあれば文句ないのに。



というわけで、交換しちゃいましょう。

X1 carbonの3rd Gen.は、上位モデルだとSM951というさらに速いのを積んでるらしいですが、出たばかりで512Gモデルは簡単には手にはいらなそうです。

しょうがないので、少し前のモデルだけどXP941というシリーズの512Gモジュールを買ってきました。5万円くらい。
両面実装ですが、X1 carbon側のスロットもちゃんと上下とも空間が空いてるので問題なく挿せます。


交換してベンチマーク。

はや! シーケンシャルアクセスは倍超え!
4KQ32リードが遅くなってるように見えますがここはやるたびにかなり前後するので正直よくわかりません。

ちなみに体感では、特に違いはわかりませんでした。とにかく広いのでうれしい。

ZYNQで追加のUARTポートを使う(3) 16550互換IP

uartliteはドライバに手をいれることで特に問題なく動きました。

けど、なんかとても不安ですよね。こんな状態で配布されてるって、どんだけzynqでこれを使ってる人が少ないのだろうかと。


実績を重んじる立場からすると、多少IPフットプリントが大きくてもドライバに実績がある16550互換IPを使ったほうがいい、と思うケースもあると思います。

こちらはすんなり動く・・・かと思ったのですが、少し罠があったので紹介しておきます。


まずPL側は、IPを配置して線を繋ぎます。AXIバスの他に、TX/RXに相当するsout/sinと、割り込み線だけは繋いでください。他は全て無結線でも大丈夫です。

次にDTSは適当にぐぐってきたのを参考に書きます。割り込みはuartliteの時と同様に61-32=29、アドレスは43C00000にしました。
axi_uart0: serial@43C00000 {
   current-speed = <115200>;
   clock-frequency = <100000000>;
   compatible = "ns16550a";
   interrupt-parent = <&ps7_scugic_0>;
   interrupts = < 0 29 4>;
   reg = < 0x43C00000 0x10000 >;
   reg-offset = <0x1000>;
   reg-shift = <2>;
   xlnx,family = "zynq";
   xlnx,has-external-rclk = <0x0>;
   xlnx,has-external-xin = <0x0>;
   xlnx,is-a-16550 = <0x1>;
   xlnx,s-axi-aclk-freq-hz = <0x5F5E100>;
   xlnx,use-modem-ports = <0x0>;
   xlnx,use-user-ports = <0x0>;
   xlnx,instance = "axi_uart16550_0";
};
特にドライバに手を加える必要は無いですが、compatibleの参考とかで見たいときはファイル名8250.c を探してください。


あとはLinuxカーネルのビルド時に2箇所、有効にしなきゃいけないチェックがあります。
一つは当然
8250/16550 and compatible serial support
さらに、DTSファイルにシリアルポートの初期化を記述する前提となる機能
Serial port on Open Firmware platform bus
も有効にしないとIPを認識してドライバが起動してくれません。


これで16550互換シリアルが/dev/ttyS0 とかで動作するはずです。

ZYNQで追加のUARTポートを使う(2) Linux側

だいぶ日付が開いてるけど前回の続き

PL側にIPが配置できて割り込みを61番につないだところからスタートです。


まずはDTSファイルにポート情報の記述。PL側で自動割付したレジスタアドレスと割り込み番号を反映させます。
uartlite_1@42C00000 {
   compatible = "xlnx,xps-uartlite-1.00.a";
   reg = <0x42C00000 0x10000>;
   device_type = "serial";
   interrupt-parent = <&ps7_scugic_0>;
   interrupts = <0 29 4>;
   clock = <100000000>;
};
この例だとアドレスは0x42C00000で、割り込み番号は61から32を引いて29と記述してます。


次にLinuxドライバですが、xilinx / digilent配布のものにソースは入っています。標準ツリーにも入っているようです。ただし、menuconfigでこれが選択肢に出るにはARCHとCROSS_COMPILEをそれっぽく指定してmenuconfigする必要があります。
make ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- menuconfig 
これで出たメニューで、driver → character → serialの中に、Xilinx uartlite serial port supportという項目があるのでチェックを付けて再ビルドします。

なお、ドライバのソースuartlite.c内に書かれているデバイス名候補と、DTSに記述したcompatible項目"xlnx,xps-uartlite-1.00.a"が対応していないとデバイスが認識されないのですが、最新のソースを見てもここは上記の名前ともう一つくらいしか記述がありません。

ネットをぐぐるとDTS内にuartlite-1.02を記述してる人がいたり、そもそもvivadoに入ってるIPのバージョンはuartlite2.00になってるのですが、そういう名称は自分でuartlite.cに追加しない限り認識されないので、新しいほうがいいかもとか悩まずに上記の古い名前を記述してください。どうせIP自体は1.00のころから完全互換です。


これでブートすると、/dev/ttyUL0というデバイスが出点して、echoでAとか送ると文字が送信されます。

が! 割り込みが機能してなくて、3文字以上を送ると固まるし、受信も全く反応無しです。



いろいろ調べたところ、ドライバソース uartlite.c 内のirqハンドラ生成のところをレベルではなく立ち上がりエッジ指定にしなきゃいけないようです。
ret = request_irq(port->irq, ulite_isr, IRQF_TRIGGER_RISING, "uartlite", port);

これでカーネルを最ビルドして、やっとuartliteが動作しました。

2015年6月25日木曜日

ZYNQで追加のUARTポートを使う まずPL側

組み込み機器を作っていると、買い物コンポーネントをつないだりするために無駄にシリアルを多数用意しなきゃいけないことがよくあります。

最近のマイコンはそれを考慮して最初から4系統のUARTを持ってたりするのも多いですけど、5とか6系統あたりからだんだん選択肢が怪しくなります。

ZYNQの速度からすると非常にもったいないんですが、FPGAで欲しいだけの232Cポートを用意するのはけっこうよくある使い方です。

まず、ZYNQは最初からプロセッサ側に2ポートのUARTを持ってるので、vivadoでMIOのピン割り当てを有効にしてLinuxのdtsファイルにちょっと書くだけで(参考)1ポート増設はすぐできます。最初からデバッグコンソールに使ってるのと並んで、これは(digilent配布の)Linuxでは /dev/ttyPS0と /dev/ttyPS1として見えます。


3ポート以上要るときはPL部にIPをぺたぺた配置していかないといけません。

xilinx提供のIPには

  • 16550互換のゴツイもの。ドライバはLinux純正のでOK
  • ハードフロー関係を省いた軽量なuartlite。IPの実績は長いけどLinuxドライバが迷走中

の2つがありそうです。使い方はだいたい同じですがそれぞれ罠がありました。



まず本命のuartliteについて、PL側から説明していきます。
uartliteは軽くて小さいけど16バイトFIFOと割り込み対応はしていて性能はなかなのものです。

IP側は、まずZYNQのPL部設定で汎用ファブリック割り込みを有効にしておきます。まあこれはどの割り込みテストでも一緒。


後はxilinxの参考ページほぼそのままで、下図の右下部分がuartliteです。

デバッグ用に割り込みラインをLEDにも出してるのと、無駄に16550も配置してRXを両方に入れてたりしますが16550の方は無視してください。

参考ページと違うところは割り込みの番号です。

ZYNQに割り込みを突っ込むのにはORで好きな本数束ねた後に、上の絵の中央下端にあるconcatさんを経由してからPS部のIRQ_F2Pに突っ込むのですが、このconcatさんの仕様がある時点から変わっています。

昔は割り込み番号を大きいほう(91)から使っていたのが、最近のバージョンでは小さいほう(61番)から使うようになっています。(↓concatのダイアログに文章で書いてあります)

なのでOS側のためにdtsファイルに書く割り込み番号も、61側から順に書かないといけません。

なお、ハードフローを使わないならuart16550を使う手順もPL側は全く同じです。違いはuartliteでTX/RXと名づけられていた信号はsout/sinという名前になってる、てとこぐらい。あとfreeze機能は不要なので一応GNDにつないでおきました。

後はAXIバスのアドレスを自動でいいので割り振ってあげてください。
PL側の準備はここまで。

2015年6月9日火曜日

mmapでドライバ的なコードを書くのもアリなのでは?

UIOをあきらめたので素直に通常のドライバを勉強しよう、と思いつつも、単なるIOポーリングくらいだとあちこちで紹介されているmmapを使った手抜きコードでもいいような気がしてきます。

http://www.sweetcafe.jp/?p=171

http://www.wiki.xilinx.com/Linux+User+Mode+Pseudo+Driver

windowsの感覚から考えるととんでもない機能ですが、しかしそもそもユーザー空間とカーネル空間というのはMMU (とCPUの特権レベル)で作り出している概念なので、MMUを使って正式に両者を繋げるようなアクセスはいんちき技というわけでもないようです。


もちろん、ドライバの枠組みを通らずにユーザーコードからメモリマップドIOを操作する(=ハードウェアにアクセスする)のは、ソフトの移植性やハードウェアの隠蔽レベルを下げてしまう可能性はあります。

が、そこはソフトを書く人次第ですから、mmapを使うコードをきちんとカプセル化して"ドライバ"であると意識してプログラミングすれば保守性は問題ありません。

というか、ユーザーコードとハードウェア制御が混ざってカプセル化が崩れるという心配は全く同じことがUIOを使った場合にも言えるので、UIOがアリなんだったらもはやmmapで作ったドライバを邪道扱いする理由は無い気がしてきました。




・・・と、言い訳を並べたところで性能計測

DigilentのチュートリアルでPL側に作ったLEDレジスタ(0x43C30000)をmmapで100万回リード、ライトして時間を計測しました。

  • mmap経由で8ビットライト x100万回 = 0.23sec  ⇒ 1アクセス 230nsec
  • mmap経由で8ビットリード x100万回 = 0.21sec  ⇒ 1アクセス 210nsec

と、なかなかの速度です。1バイトアクセスならPCIexよりはるかに早い!


このままPIOでバカみたいにデータ転送しても数MB/sec出るわけなので通信系ドライバ程度ならこれで十分な場合もありそう。


書き込み100万回のコードを貼り付けておきます(ひでみさんのコード丸パクリです)
#include <unistd.h>
#include <sys/mman.h>
#include <stdio.h>
#include <fcntl.h>
#define SIZE 0x1000
#define BASE_ADRS 0x43C30000
#define REG_DATA 0x00
#define REG_TRI  0x01

void main(){
  int fd;
  unsigned int *buf;

  fd = open("/dev/mem", O_RDWR | O_SYNC);
  if (fd == -1) {
    printf("open failed");
    return;
  }

  buf = mmap(NULL, SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, BASE_ADRS);
  if (buf == MAP_FAILED) {
    printf("mmap failed");
    return;
  }

  int cnt=0;
  int dat;
  while(cnt++ < 1000000){
    buf[REG_DATA] = 0x00;
    //sleep(1);
    buf[REG_DATA] = 0xFF;
    //sleep(1);
  }

  munmap(buf, SIZE);
  close(fd);
}
念のためopenのときにO_SYNCフラグを付けておきましたがこれの有無で特に動作、実行時間に変化は見られませんでした。

これを普通にコンパイルして、実行時に
time ./test2
で実行すると時間が計れます。

2015年6月8日月曜日

Digilentの最新リポジトリでもUIOの状況は・・・同じ

いっこ前の記事でxilinxのリポジトリ内容が古い・・・とフォーラムに書かれてたと言いましたが、フォーラムの書き込みは2013年のものです。

そしてZYBOユーザーの人はチュートリアルどおりに作業すると、dtsファイルのサンプルが入ってるのがmaster-nextなのであえて古いものを使っていることになります。

dtsファイル以外にはDigilent最新リポジトリでZYBOが困ることは特になさそうなので、最新をとってきて、dtsファイルだけmaster-nextから抜き出したものを使うのを試しました。


どきどきしながらdtsファイルにUIOのデバイス設定を書いてリブート・・・


やっぱり/dev以下にはuioデバイスは出現しませんでした。ちぇっ。

zynqのドライバ入門 UIOを使ってみたかった・・・が

先輩方のUIO解説記事 (例えば、https://formalism.github.io/blog/posts/2014/05/zynqpllinux-dts/) にしたがって、カーネルをmake menuconfigで確認すると、ZYBOチュートリアルで拾ってきたものでもちゃんとUIOには[*]チェックが入っています。

楽勝~と思って、dtsにそれっぽいデバイスをいろいろ書いて、dtbをSDカードにつっこんでリブートすると、/devの下にuio0とかが・・・無い!

いくらやっても、カーネルをリコンパイルしてもどーやっても出現しません。



しばらく苦戦しているうちに、ふと先輩方の多くが、Digilentのチュートリアルをさらっと流した後にdigilentリポジトリではなく、http://masahir0y.blogspot.jp/2014/01/u-boot-linux-kernel-zynq.html のように公式リポジトリや、その他のディストロを使っていることに気づきました。

そういう目でぐぐっていると
http://forums.xilinx.com/t5/Embedded-Linux/help-with-simple-Zynq-PL-device-access-via-Linux-UIO-based-user/td-p/270836
に、

「xilinxのカーネルは古いので、UIO機能自体は入っているけどdtsを解析してuioデバイスを作る機能が入っていない。だからUIOを使うには自分でデバイスを作るカーネルモードのコードを書かなきゃいけない」

と書かれていました。

うーん、困りました。
そもそもUIOの紹介ドキュメントに「UIOは何一つ新たなものを実現しません。ただ単にわかりやすく、特権コードを書かなくていいだけです」と言ってるくらいなので、どうせカーネルモードのコードを書のなら無理してUIOを使う必要が無さそう。

かと言って、UIOのためだけに使用するカーネルのソースを別のにするというのも何か違っている気がします。(もちろん公式が新しいわけだし、変更点を理解している人なら全然問題ないんでしょうけど)

というわけで、digilentまたはxilinxリポジトリのカーネルを使う限りはUIOではなく普通のドライバ記法を勉強することになりそうです。

zynqのドライバ入門 myledサンプルから一歩進みたい

Digilentのmyledサンプルまではフォローできました。これでFPGA(PL)にAXIで繋いだレジスタへのwriteができ、同じものをreadしてCPU側で表示することができました。

この先やりたいことは組み込み用途ならだいたいみんな一緒で

  1. myledサンプルだと、一度read/writeするたびにcloseしないといけないので遅い。連続rwしたい。
  2. 割り込みハンドリングしたい
  3. 大容量データを転送したい

といった順序で戦っていくことになります。



まず1番目についてですが、現状の/proc/myledデバイスを open->read->close または open->write->close するコンボでどれだけオーバーヘッドがあるか、ユーザーコード側で100万回ループさせて確認してみました。

readの方はコンソールに文字を出すと/dev/nullに捨ててもかなりのオーバヘッドになるので、コード内で読み捨てしています。

  • open->write->close ×100万回 = 156秒  ⇒ 1回あたり 0.15msec
  • open->read->close ×100万回 = 76秒    ⇒ 1回あたり 0.07msec

人間の速度からすれば高速ですが、10msecごとにIOをポーリング監視したい、といったような組み込み用途ではさすがに見過ごせない遅さです。


3番目の大容量転送は、DMAやらブロックデバイスやらが登場しそうな気がするのでいったん忘れることにして、とにかく1番と2番をなんとか学習したいと思います。


あちこちの先輩方の記事を見ると、このあたりに関してはUIOを使うと簡単そうなのでちょっと試してみたのですが・・・

2015年6月5日金曜日

ZYBOでLinuxブート時にUSB phyがmissingで初期化されない問題

とりあえずDigilentのチュートリアルベースでいろいろいじれるようになりました。

いろいろ試すのに母艦とのファイル受け渡しをやっていて、LANが使えない環境だとUSBメモリを使って受け渡ししたくなるのですが、Linuxブート後のZYBOにUSBメモリを挿しても認識されません。

おりょ?と思ってdmesgで確認すると
ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
ehci-pci: EHCI PCI platform driver
zynq-dr e0002000.ps7-usb: Unable to init USB phy, missing?
確かに初期化時に失敗しています。


DTSが不適切だったかなぁ?と思って確認しましたが、特にDigilentのZYBO用から何も変更していないのでおかしくなりようがありません。


同じように困ってる人がいないかな~と思ってぐぐっていると

http://www.sweetcafe.jp/?p=322

起動時に何かデバイスを挿していないとこのようにphyが見つからず失敗するとのこと。


OTGのホスト判別機能が関係しているのは間違いないですが、ソフト的な対処法がわからないので、ハードウェア的にホストであると教えてやることで当面やりすごすことにします。



OTGに対してホストであると教えるには、OTGのID線をGNDに落としておけばいいので

  • 何かデバイスを挿しておく
  • 市販のOTG⇔USBA変換コネクタをマイクロUSBポートの方に挿しっぱなしにしておく

のどちらかで可能です。たまたま変換コネクタが手元にあったのでこれを使うことにします。

2015年6月3日水曜日

(メモ) zynqのUSBをデバイスポートとして使う例

zynqのUSBをホストとして使う分にはlinuxの情報が山ほどあるしそもそもプログラミングすら不要な場合が多いですが、デバイスとして使うのはとっかかりが無いと難しそう。

もちろんサンプルは用意されてるのですがhands on tutorialほどには低レベルな読者を想定していないので苦労しそう・・・

と思っていたら、ありがたいことに日本語で例を挙げてくださってる方がいました

https://formalism.github.io/blog/posts/2014/04/zynqusb/

https://formalism.github.io/blog/posts/2014/04/zynq-usb/

procファイルシステムってなに?

ZYBOのチュートリアルを一通り終えた。
/proc/myledデバイスを登録してリードライトが可能になったので、原理的にはハードウェアとの情報のやり取りはなんでも可能ぽぃ。

けど、このサンプルの通りだとアクセスするたびにfcloseしてopenし直さないといけないのでオーバーヘッドがとてもでかいです。

試してみたら

  1. fopen
  2. fputcでLEDの状態を変更
  3. fclose

のセットをを100万回やって2分36秒でした。1回あたり0.23msかかっていることになります。

※後でもう少しちゃんと計りなおしました


ど論外というほど遅くはありませんが、大半がfopen/closeのオーバーヘッドだと思うのでオープンしっぱなしでアクセスしてキャラクタデバイスの限界速度を知っておきたくなります。


というところで、キャラクタデバイスの中でもこのサンプルはprocfsの枠組みを使っているそうなので、procfsについてまずお勉強からです。

http://www.turbolinux.com/solution_service/library/features/c_magazine/vol_03.html


勉強しているうちに、ZYBOのサンプルはprocfsの中でも、さらにseq_fileインターフェイスを使ってバッファリングしていることがわかりました。

http://wiki.bit-hive.com/tomizoo/pg/proc%20fs%20%A4%F2%BB%C8%A4%C3%A4%BF%A5%AB%A1%BC%A5%CD%A5%EB%BE%F0%CA%F3%A4%CE%C9%BD%BC%A8%20%A4%BD%A4%CE2


ZYBOのチュートリアルだとopenの時にseq_printfしてドライバとしてはreadのための処理を終えちゃっていて、後は1バイトずつ読出しがかかるたびにseq_readが受け渡しをやっているようです。

この方式だと、openして、大量のデータをどがーーーっと読み出してcloseするようなある意味ブロックデバイスのようなデータ転送がキャラクタデバイスでも簡単にできそうです。



まあ、それはそれで後で転送速度とか調べるとして、逆にIO監視のようなリアルタイムちびちび再読出しを(毎回のopen/closeオーバーヘッド無しに)するにはどうするか…。seq_fileを使わない方が簡単そうですね。


追記:
seq_fileを使わない方は、create_procの書式が最近変更されていて古い記事がそのまま使えなかったので新書式のほうのサンプルからスタート
http://pointer-overloading.blogspot.in/2013/09/linux-creating-entry-in-proc-file.html

2015年6月1日月曜日

zybo起動用ramdiskの編集

ひととおりチュートリアルをフォローして、SDからのlinuxのブートまでこぎつけました。

linuxカーネルはdigilentから拾ってきたものそのままですが、ビルド前にmake menuconfigするとそれなりのGUIが出るので無知でも多少のカスタマイズはできそうです。

となると、しろうとシステム的にはramdiskイメージさえ編集できれば自作ソフトを起動したりSDの別パーティションをマウントしたりとやりたいことの大半はできるわけです。


といっても、マウントして操作するだけです。

digilentから拾ってきたサンプルのramdiskが ramdisk8M.image.gz だとすると


  1. まずgzip -d ramdisk8M.image.gz で解凍
  2. 適当な名前でマウント  sudo mount ramdisk8M.image /media/ramTest/
  3. /media/ramTestに移動して好きなように編集しまくる
  4. cdで ramTest以下から抜けて、umount
  5. gzipで再圧縮
  6. 後はチュートリアル通りubootヘッダを付加してSDに入れ直し


よりストイックに、ゼロから作成したい場合は

http://www.ibm.com/developerworks/jp/linux/library/l-initrd/

なんかが参考になりそうです。

Linuxブートまでの参考ページ

ZYBOにLinux導入お勉強の、参考ドキュメントはぶっちぎりで digilentのhands-on tutorial が良いのですが、使っているバージョンが2014.1であることや、些細な誤記程度はあるので正誤表的に解説してるページを追加で参考にすると良いです。

自分で書こうと思ってメモしながらやっていたのですが、Begin a nerd engineerの内川さんの記事に全てが書かれていたので、こちらをリンクしておきます。

http://nerdengineer.com/jp/blog/files/09c7e46c28ab96e4ecce1800b9b11575-3.html

とても助かりました。

2015年5月31日日曜日

zynqのブートお勉強 u-bootってなに?

zynqのブートは多段ローダーを使いさらにその上でLinuxのブートもあるので、ただチュートリアルをやってるだけだとどのレベルで何をやってるか勘違いしやすいです。

とりあえずFSBLやu-bootがなぜ必要で何をやってるのかお勉強ちゅう

参考ページ

http://nahitafu.cocolog-nifty.com/nahitafu/2014/08/zynqfsbl-5f71.html FSBL奮闘記

http://masahir0y.blogspot.jp/2014/01/zynq-2.html zynqのブート

http://blog.kmckk.com/archives/4414137.html u-bootの初心者向け説明

http://www.embeddedworld.jp/2014/12/u-boot%E3%81%AE%E3%83%96%E3%83%BC%E3%83%88%E3%82%B7%E3%83%BC%E3%82%B1%E3%83%B3%E3%82%B9/ u-bootの説明


2015年5月29日金曜日

XSDKでBOOT.imgのパック

FSBLのビルドまではすんなり行きますが、最後にBoot.imgをパックして作るツールのところで、
指定するファイルのパスが2014.1と2015.1はわりと違います。

  1. 最初のが、直前にeclipseでビルドしたFSBL。
  2. 二番目が、vivadoで動作確認してexportしたはずのPLのbitファイル
  3. 三番目はlinux環境でビルドしてきたu-bootなので間違えようがない

よくわかっていませんが、うちの環境では下のように指定したら一応ブートしました

いちおうこれでできたBoot.imgをSDに置いてブートしたら自作のロジックが動きました。

Linuxのイメージはまだ作ってないので、PS側はFSBLからu-bootに制御が移った後linuxが見つからない、という愚痴を垂れてu-bootプロンプトらしき個所で止まります。

ちなみにFSBLの設定?かなにかで、起動時のログはuart0→USBシリアルに吐かれるようになっているので、PROG UARTポートにteratermを繋いでおいてリセットすれば起動ログが見えます。なんて楽ちん。

ZYBOのlinuxチュートリアル ハードウェアのエクスポートとSDK起動

Zynqの始め方はいろいろありますが、digilentのZYBO用資料(Embbeded linux hands on tutorial)がかなり丁寧なのでこれを追いかけることにします。

だいたい先頭からやっていくだけですが、いくつかはまるポイントがあるので順不同でメモしておきます。


FPGA(PL)側のサンプルをビルドして動いた後、それをエクスポートしてXSDK(という名のeclipse)で読み込んでBOOT.imgを作ろう、というところで、現在の2015.1はExportメニューが2014.1より簡略化されています。

まあ、そこで困る人はいないと思いますが、その後XSDKを起動してハードウェアプロファイルを選ぶところで、ZYBOという選択肢は無いので、どのファイルをハードウェアプロファイルとして食べさせれば良いのか困ってしまいます。

実は上のvivadoのメニューでExportのいっこ下にあるLaunch SDKでXSDKを起動すると、VivadoでExportしたばかりのハードウェア情報をXSDKがインポートしながら起動します。

そうすると、Application Projectを作ろうとした時もvivadoでさっきまでいじっていたハードウェアが見えていてPSにcortexa9_0も選べます。


2015年5月28日木曜日

VirtualBox内のubuntuに見せる共有フォルダの権限とシンボリックリンク

windows側から見せてる共有フォルダにプロジェクトを置いて、仮想linuxからは本当にmakeするだけ、とかやりたい。

makeの過程でどうしてもシンボリックリンクを作ったりするものがあるので、ただ読み書きできるだけでなくそれも許可しておく。



読み書き権限はlinux内でグループ追加するだけ
シンボリックリンク許可はホスト側でVirtualBoxに設定をしてやるらしいです

https://gist.github.com/m-nori/4507653


VirtualBoxの仮想HDDサイズ縮小

ネットで検索すると見つかる情報をメモ


Linuxでどのフォルダが容量を食っているか調べるのはduコマンド
http://itpro.nikkeibp.co.jp/article/COLUMN/20060227/230748/


仮想HDDを縮小するのに、0埋めしてホスト側でツールを使う手順
http://freefielder.jp/blog/2014/05/virtualbox-hdd-size.html


0埋めする方法がかっこいいですね。

Zynqの開発環境 windows? linux?

Zynqの開発環境を作ってるのですが、とにかくサイズが大きい!
Vivadoで5~10G、さらにXSDKで5Gくらい食います。

しかも母艦がWindowsの人は、Linux版を仮想マシンで使うかWindows版で行くか、と悩むことになります。

どこのチュートリアルを見ても、Zynq内でLinux使う予定なら素直に開発環境もLinuxにすれ、と書かれていますが、実際両方試してみてその通りでした。。。

コンパイラやmakeツールなんかはwindows版でもそれなりに揃うのですが、具体的に困るのは

  • 拾ってきたソースをビルドするときに、設定スクリプトを一度実行してからmakeしなきゃいけない
  • 拾ってきたソースでLinux環境の標準的なライブラリをincludeしまくっている
という場面です。

上記の問題がスタートアップ時に遭遇する程度ならいいんですが、LinuxをZynq内で使ってると日々こういう苦労をすることになるので、armのクロスコンパイルはLinux母艦でやるのがよさそうです。



最近の仮想マシンは共有フォルダがかなり自然に使えるので、Vivadoはwindows側、armコンパイルは仮想Linux側、パッキングなんかの作業はwindowsのXSDK、という分業もありじゃないかと思いますが、残念ながらLinux側にarmコンパイラだけ入れるという方法が見つかりません。

xilinuxの説明 http://xilinx.wikidot.com/zynq-tools では、
「SDKインストーラの中の*arm-xilinx-linux-gnueabi.bin を使えばコンパイラだけ入れられるよ」と書いてありますが、SDKインストーラはパスワードxzで固められていて、中のファイルを自由に取り出す方法がわかりませんでした。

というわけで、現状ではホスト、ゲスト両方のOSにVivado + XSDKをインストールする羽目になっています。使っているThinkpad X1 carbonのSSDがたった100Gしかないのですぐに溢れます。。。


だれかコンパイラのインストーラだけ取り出す方法を知っていたら教えてください(泣)

ぶろぐ開設

もともと別にちびヘリRC情報という日記を書いていて、ヘリには関係ないんだけど組み込み系の作業メモを残したいなーと思うことが多かったのでやっと作りました。

日々の組み込み関係で遊んだときのメモを残していこうと思います。
扱いそうなキーワードは
  • STM32
  • Zynq
  • arduino
  • Linux
  • FreeRTOS
  • 唐突に電源とかアナログの入門
といったところです。

当面はZynq入門中なのでいきなりですがそっち関係が多いと思います。