2016年1月2日土曜日

MinGWでC++11 (to_string)

ちょっとテキストファイルを別形式にコンバートする小物ツールを作る話がありました。

最終的にはギガバイト級のデータを扱いたいみたいなので、あとで速度を上げやすいようにC++で (なんと自分で選ぶのは初) やってみようかと思い、まずは速度度外視でアルゴリズムを作る段階。

生Cと違ってそれなりのstringクラスはあるようだけど、splitが無かったりしてあまり高機能では無いです。
とはいえ、c++11仕様をONにするとそれなりにいろんな機能が揃ってるようなので、-std=c++11オプションをつけてlinuxでちまちまと開発。


・・・と、そこまではよかったんですが、
年始でちょっと暇ができたところで、windows環境でのビルドも試そうと思って同じものをmingwでビルドしてみたら、無情にも

error: 'to_string' was not declared in this scope

と無常にもto_stringごときでエラーが出ました。


そんなわけないしー、ほかのc++11機能はとおってるしー、としばらく悩んだ末にぐぐってみると、MinGWのバグらしい…
This is a known bug under MinGW. Relevant Bugzilla. In the comments section you can get a patch to make it work with MinGW.
This issue has been fixed in MinGW-w64 distros higher than GCC 4.8.0 provided by the MinGW-w64 project. Despite the name, the project provides toolchains for 32-bit along with 64-bit.
(http://stackoverflow.com/questions/12975341/to-string-is-not-a-member-of-std-says-so-g)


パッチは出ているようですが、MinGW-w64を使えば問題ないみたいなのでそっちに乗り換え。
nuwanディストロ (http://nuwen.net/mingw.html) を拾ってきてただパス通すだけでOKでした。

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 とかで動作するはずです。