2017/09/20

JavaScriptの整数範囲はJSONに影響するのか?

以前、JSON-RPCをやるのにuint64_t対応したライブラリが見つからない、という話を書いた。

結局、内部でしか使わないからいいや、ということで、jsonrpc-cをforkして、uint64_tにだけ対応させることにした。


それはそれでよいのだけど、世の中にはあるんじゃなかろうかと探していた。
同じ疑問を持つ人がいた。
c++ - Does libjson support 64 bit int types? - Stack Overflow

libjsonは知らんのだが、回答からすると、JavaScriptは内部的に53bitまでの制限があるよ、ということらしい。
ECMAScript仕様のページにリンクが貼られていて、確かにごにょごにょ書かれている。


こちらは、ECMAのJSON仕様(pdf)だ。
ただ、JSONのtext format仕様なので、値の範囲がどうのこうのということは書かれていない。


だから、やはり安全にいくなら、uint64_tは文字列にする方がよいのだろう。
32bitずつにして、上下で表してもよいかもしれんが、とにかく表せないかもしれない書式を使うのは危ないかもしれん。
まあ、そんなことをいえばint64_tだって53bit以上あるのだから同じことか。


それだったら、いっそのこと全部の数字を文字列で表せばいいやん、みたいな気持ちになってしまうので、深追いは止めよう。
大人の対応というのは、最終的に自分への負担が減る対応にするべきなのだ。。。

2017/09/18

[vscode]gdbを使ってみよう(2017/09/18)

コンパイラとしてgcc系のものを使うことが多いので、デバッグもgdb系になる。
が、何十年もやっていながら、未だにgdbに慣れていない。。。

だが、世の中にはGUIで隠してくれるデバッガもある。
dddやinsight、eclipseもプラグインで対応できる。
nRF51をデバッグしていた頃はeclipseを使っていたのだが、起動が重たいので、動かすかどうかをためらうこともあった。

最近、Visual Studio Code(以下、vscode)を使うことが多くなったので、そっちでも同じようなことができそうな気配がする。
まずは、vscodeでgdbを使ったデバッグをしてみよう。


vscodeは更新が多く、また機能をextensionsで実現することも多いため、最新版ではここに書いていることが使えなくなっているかもしれない。

こちらは、2017/08/18に更新されているので、これを眺めながらやっていく。
C++ Programming | Visual Studio Code Docs


ビルドはコマンドラインでやってもよいのだが、せっかくなのでvscodeからやってみよう。
昔やった、lmdbのサンプルコードがあったので、それで試していく。
コード自体はどうでもよいのだが、Hello Worldみたいなサンプルではわかりづらいので、多少込みいったものを選んだだけだ。


サンプルは、こうやってビルドできた。

$ gcc -o tst ex1.c -llmdb -pthread

そのフォルダでvscodeを起動。

$ code .

ファイルで開くとダメそうな気がするので、ディレクトリ指定で開くとよいかもしれん。
その状態で Ctrl+Shift+B を押すと、タスクがないよ、というメッセージが出てくる。
「Configure Build Task」の方をクリックすると、4択になるので「Others」を選択。
すると、.vscode/tasks.jsonというディレクトリとファイルを作ってくれる。

tasks.jsonは、こんな感じで書く。

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "taskName": "gcc",
            "type": "shell",
            "command": "gcc -Wall -ggdb -o tst ${relativeFile} -llmdb -pthread",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": {
                "owner": "c",
                "pattern":[
                    {
                        "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
                        "file": 1,
                        "line": 2,
                        "column": 3,
                        "severity": 4,
                        "message": 5
                    }
                ]
            }
        }
    ]
}

リンク先よりもversionが上がっているので、変わりやすいのかもしれん。


"group"を書いて、"kind"を"build"にしないと、Ctrl+Shift+Bでビルドしてくれなかった。
"problemMatcher"を書いておくと、それに引っかかった出力がタブ「PROBLEMS」に出てくれる。
${file}だとフルパスになるためか、PROBLEMSをクリックしてもファイルがないと言われてしまった。
${relativeFile}だとvscodeを開いたディレクトリからの相対パスになるようで、そっちだとOKだった。


makeしたい場合は、こんな感じで書いた。

{
    // See https://go.microsoft.com/fwlink/?LinkId=733558
    // for the documentation about the tasks.json format
    "version": "2.0.0",
    "tasks": [
        {
            "taskName": "make",
            "type": "shell",
            "command": "make",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": {
                "owner": "c",
                "pattern":[
                    {
                        "regexp": "^(.*):(\\d+):(\\d+):\\s+(warning|error):\\s+(.*)$",
                        "file": 1,
                        "line": 2,
                        "column": 3,
                        "severity": 4,
                        "message": 5
                    }
                ]
            }
        }
    ]
}

ただ、これは統合開発環境じゃないから仕方ないのだが、problemMatcherは出力をなぞるだけのため、Makefile内でディレクトリ移動してMakefileを呼び出す、みたいなことをやっていると、ファイルを見つけられないようだ。

make用のExtensionsがあるのかもしれんが、まあ今回はよかろう。


次はgdb。

https://vscode-doc-jp.github.io/docs/languages/cpp.html#%E3%83%87%E3%83%90%E3%83%83%E3%82%B0
https://code.visualstudio.com/docs/languages/cpp#_debugging-your-code

どっちを見ても、launch.jsonというファイルを作れ、と書いてある。
仕方ないので、.vscodeディレクトリで右クリックし、「New File」でlaunch.jsonを作った。
そうするとlaunch.jsonファイルがタブで開き、右下辺りに「Add Configuration...」というボタンが出てきた。

ボタンを押すと、versionなどのテンプレートが出てきたので、Enterを押して確定。
まだボタンが出ているので押してみると、追加する中身のテンプレートが選べるようだった。
せっかくなので、C++のLaunchするやつを選択。
これはありがたい。


と、ここまでやってリンク先を見たら、Debug Viewにしてやればファイル作成などは勝手にやってくれたみたいだ。。。
悔しいので、.vscode/launch.jsonを消してやり直す。

まず、左側のデバッグっぽいアイコンをクリックし、Debug Viewにする。
設定してくれそうなアイコンが出てくるので、クリック。
そうすると、さっきのような選択が出てくるので、C++のgdbできそうなものを選択。
まあ、できるファイルは同じっぽいな。


"program"は書き換えないといかんだろう。
"${workspaceRoot}/tst"にする。
ファイル保存して、Viewにあるデバッグ開始しそうなアイコンをクリック!

・・・開始エラー?
よくわからんのでもう一度押すと、今度は動いて、設定していたブレークポイントで止まったようだ。
たぶん、launch.jsonの"stopAtEntry"を設定しておくと、その関数で止まるようになってるんじゃなかろうか。


変数名にマウスを当てると中身が見えるし、構造体も出てくれる。
整数型は10進数で、ポインタは16進数で表示するようだ。
16進数で見たい場合は、WATCHとして追加するしかなさそうだ。
例えば、env->me_flagsという値を16進数で見たかったら、「env->me_flags,h」のように指定するそうだ。
https://github.com/Microsoft/vscode-cpptools/issues/379

2016年12月のことだから、今は別の手段があるかもしれん。。。が、それっぽいのは見つからなかった。
まあ、こういうのは、だいたい解決されていくものだし、方法がないわけではないからよかろう。


こんな感じで、gdbを使うだけであればlaunch.jsonを作るだけでよさそうだ。

2017/09/17

[btc]confオプションはフルパスで書くべし

testnetでなかなかマイニングされないので、regtestに切り替えようとしている。
まあ、testnetは有志によるものっぽいから、何が起きても文句は言えない。。。


まず、testnetとregtestを同時に動かしておけるかどうか。
これは、ダメそうだ。
bitcoindがHTTP serverになるようで、2つめを起動したらエラーになった。

Error: Unable to start HTTP server. See debug log for details.

引数で何か設定すればよいのかもしれんが、まあそこまで切実ではないので、よかろう(実はできるのだが、後述)。


次は、confファイル。
bitcoindはデフォルトで~/.bitcoin/bitcoin.confを見に行くが、regtestのために書き換えるのが面倒だから、regtest用のconfファイルを読み込ませたい。

regtest=1
server=1
txindex=1
rpcuser=xxx
rpcpassword=xxxxx
rpcport=18443

こんな感じか。
rpcportを設定したのは、まあ、確認みたいなものだ。

$ bitcoind -conf=./regtest.conf

そして別のコンソールから確認。

$ bitcoin-cli -conf=./regtest.conf getblockcount
74242

ん??
regtestなのにブロックがあるし、やるたびに増えていってるからどこかからダウンロードしているようだぞ。
networkinfoで見ると、やはりピアが見えているし、ポート番号も8333だ。
ということは、mainnetを見に行ってるらしい。


こうやるのがよさそうだ。

$ bitcoind -conf=./regtest.conf -regtest

納得がいかないのだが、仕方ない。

regtest.confから「regtest=1」を削ってもよいかも。
ただ、bitcoin-cliの方は-confで設定したregtestを見ているようで、-regtestオプションを付けなくてもよいようだ。
まあ、bitcoindが付けているのだから、両方付けた方が統一されていてよいかもしれん。


では、最後にJSON-RPC。

$ curl --user xxx:xxxx --data-binary '{"jsonrpc": "1.0", "id":"curltest", "method": "getblockcount", "params": [] }' -H 'content-type: text/plain;' http://127.0.0.1:18443/

ダメだ、接続できない。
wiresharkでbitcoin-cliしたときのポートを見ると、18332になってる。
全然confファイルの言うことを聞いてくれんやつだ。。。

そして、ポート番号を18332にしてもダメ。
認証に失敗しているようだから、rpcuserなんかも見てないということか??
しかし、getnetworkinfoで見ると、なんか18444を監視している。
いっちょんいうことばきいてくれんっちゃけんねぇ。。。


このregtest.confを、カレントディレクトリではなく~/.bitcoinの中に置き、-conf=regtest.confとディレクトリ無しにすると、すんなり動く。
-regtestもいらないし、JSON-RPCも書いてある通りの設定になる。
よくわからんが、その方がいろいろやるよりも安全な気がする。


自動実行するときは、systemdに登録しているのだが、そのときはたぶんUserで指定した人の~/.bitcoin/bitcoin.confを使っているのだろう。
ここを見ると、/etc/bitcoin/bitcoin.confを例にしているので、そういうのはありなんだ。。。
https://github.com/bitcoin/bitcoin/blob/master/doc/init.md

systemdのservice設定を見ると、conf指定だが、フルパスで書いているな。
https://github.com/bitcoin/bitcoin/blob/master/contrib/init/bitcoind.service

まさか・・・。

$ bitcoind -conf=`pwd`/regtest.conf

はい、そういうことでした。
confはフルパスで書くべし、でした。

最初に試した、testnetとregtestを同時に動かす、もconfファイルを相対パスで指定していたのでうまく動いていないだけだった。
datadirを別にすれば、regtestを複数立てることもできるんじゃなかろうか。意味はなさそうだがね。

2017/09/16

[bow]lmdbのmdb_env_open()でエラーになる

msg queueを使うプログラムを作っていたのでUbuntu16.04で作業していたのだが、socketに変更したので今のbash on Ubuntu on Windowsでも動かせるようになったんじゃなかろうか、ということでやってみた。

・・・そこに行き着く前に、lmdbのmdb_env_open()でエラーが返ってきた。。。


エラーの内容は、exec format error。
ENOEXECというやつだ。

ずーっとたどると、mmap()でエラーを返しているようだった。
gdbを使わず、printfデバッグで探していたので、たどるのが大変だった・・・。
GUI環境じゃないところで、まだgdbを使えないのだよ、私は。


この辺りかな?
mmap's problem · Issue #658 · Microsoft/BashOnWindows

いろいろ書いてあってよくわからんが、まあ、たぶんbowのバグなんだろう。
2017年秋バージョンに期待だ。

[btc]testnet3

bitcoindでは、ほとんどtestnetを使っている。
bitcoin.confにも「testnet=3」と書いている。

が、btcdなんかは1と書く(3だとエラー)。
つまり、testnetは実質、testnet3しかないというになるだろう。

そもそも、testnet3ってなんだ??


Testnet - Bitcoin Wiki

このページの最終更新日は2017年2月8日なので、新しいといってよいだろう。

testnetには3つあります。

testnet2は、testnetと異なるgenesis blockを持つ最初のtestnet resetだ。
testnet3は、現在のtest networkだ。

2行目の訳が怪しいので、原文を読んでおくれ。
とにかく、初代testnet、testnet2、testnet3があり、今はtestnet3ということだ。

引数だって「-testnet」だし、bitcoin.confが「=1」でも「=3」でも特に動作は変わらないようだ。
bitcoindでも、bool扱いしているように見えるから、0でなければtestnetになるんじゃなかろうかね。

2017/09/14

[tech]IPFS

世の中にはいろいろと技術があり、「これどうやってるんだろう??」というものも多い。
IPFSも、私にとっては「ど、どうやってるんだ??」という技術の一つだ。

なんというか、ブロックチェーンと非常に似たものを感じる。


ブロックチェーンでの開発を行っていると、何かに依存した状況を極力作りたくない。
「ああ、この情報をサーバに置きさえすれば解決するのに・・・」と思ったとしても、それをやってしまうと依存が生じてしまう。
まあ、多少はよいか、という考え方もあるのかもしれないが、やっぱりここまできたらねー、という意地みたいなものも出てくる。


そこで、IPFSだ。
全然技術的に理解はできていないのだが、ファイルをアップロードすると、適当にファイルを分割されて、適当に冗長性を持たせつつ、適当に分散させて、ノードを提供している人たちに持たせている。
たぶん、ブロックチェーンのフルノードみたいに、全員が同じものを持つ、というものではないように思う。
また、単に分割してばらまくわけでもなさそうだ。

それを取得するには、アップロードしたときに渡されるハッシュ値を使う。
ファイル名に相当するのかな。
それを使うと、そのハッシュ値に相当するものがファイルとして取得できるようだ。


サイトにある「Try it」を試しただけで、それ以上は入り込んでいない。
私がやったときは、子猫の画像が取得できた。


まあ、Bitcoinのブロックチェーンだって、こんだけ人々がアクセスしてもハッシュ値でトランザクションが一意に表せているので、IPFSの参加者くらいであれば十分にまかなえているのかもしれないし、ハッシュ値のサイズだって違うかもしれない。

だから、ハッシュ値でファイル名の代わりにする、という考え方はまだわかるのだが、残りの重要な部分はさっぱりわからん。
RAIDみたいな感じを持ってしまうけど、たぶんどこかのIPFSノードが動いていないくらいだったら問題ないんじゃなかろうか。


これは、なんというか、ぞくぞくする怖さを感じましたな。
こういう技術が生まれてくることに、まだまだ視野が狭かったなー、と感じざるを得ない。
いや、自分で生み出せたかも、とかじゃなくて(無理無理...)、世の中で未発見のものは、発見されたとしても私には理解ができないものなんじゃなかろうか、などと考えていたことに対してだ。

一般技術者としては、その発明/発見に敬意を表しつつ、理解し、より使いやすい形にしたり、安全にしたり、応用したりするのがまっとうなやり方かな、と思う。

2017/09/11

[c/c++][linux]stdoutへのリダイレクトが期待通りにできない

共通で使っている処理があり、そこは出力を標準出力に行っている。
ただ、一部だけ、どうしてもファイルに掃き出したいと考えた。
元の方は書き換えたくなかったので、呼び出し元で標準出力をファイルにつなげてやればよいだろう。

この処理は何回も呼び出し、それぞれ別のファイルに出力したい。
だから単純なリダイレクトではないのだけど、まあclose()してやるだけだろう。。。


うまくいかなかった。

リダイレクトを分割したいが、うまくいかない

ファイルは3つできるのだが、中身は3.txtにしか入っていない。
そして、3.txtには全部の出力が入っているのだ。
fdをclose()させていないが、あんまり関係が無かった。

標準出力は出力タイミングまでバッファにためるタイプだったはずなので、SYNCっぽいものをあれこれ追加したのだが、どれもダメだ。


じゃあ、標準エラー出力だったらバッファにためないからいいんじゃなかろうか、ということでやってみると、OKだった。

stderrならうまくいく


ということは、システムコール側ではなく、もっと上位層で制御されているということか。
ならば、ファイルディスクリプタの1をfsync()するのではなく、stdoutの方をfflush()したらいいんじゃなかろうか?

fflush(stdout)するとOK

OKだった。
なるほどねぇ。


ただ、一部だけリダイレクトさせるのも格好が悪いので、結局実装としては別の関数にしてFILE*を取るようにしたのであった。

2017/09/09

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (19) : 完

動かん(18)で、XSDKでRunした場合はZyboのLinuxではなく、素の環境で動いているんじゃないか、という疑惑が発覚した(私の中で)。

素の環境というのは、リセットベクタから起動した後、OSを介さずにC Runtimeだけ動かし、すぐにmain()から動き始める、という意味だ。

バイナリの種類が違いそうだというのは、fileコマンドの結果によるものだ。
PetaLinux用の/bin/bashと比較しよう。


$ file bash
bash: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=bf9ec80803a2f03da139c81eddb5bc276cb5250b, stripped


$ file hello.elf
hello.elf: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, not stripped


dynamically linkedかstatically linkedだけでは判断できないのだが、「for GNU/Linux」とまで出力されては、違いがあることを認識せざるを得まい。


Windows版のXSDK v2017.2には、どっちのコンパイラもあるようだ。

image

aarch32は、archがARM32bit版の意味かな?
他にもフォルダがあり、aarch64やmicroblazeもある。
こんだけコンパイラがいっぱい入っていれば、ダウンロードサイズも大きくなるわな。。。

単なるarmフォルダもあり、こっちはarm-xilinx-eabiやarm-xilinx-linux-gnueabiもある。

SDK\2017.2\gnu\arm\nt\bin>arm-xilinx-linux-gnueabi-gcc --version
arm-xilinx-linux-gnueabi-gcc (Sourcery CodeBench Lite 2015.05-17) 4.9.2


SDK\2017.2\gnu\aarch32\nt\gcc-arm-linux-gnueabi\bin>arm-linux-gnueabihf-gcc --version
arm-linux-gnueabihf-gcc (Linaro GCC Snapshot 6.2-2016.11) 6.2.1 20161114

ほー。
久しぶりにSourceryという名前を見た。


選択は、プロパティ画面で、「C/C++ Build > Tool Chain Editor」からできそうだった。

image

何も考えずに作ったプロジェクトは、上の図のように選択されていた。
プロジェクトは新規作成したので、どこかで選択できるようになっているはず。

これか。

image

OS Platformがデフォルトで「standalone」になっていたのだ。
これが「linux」ならよいのか。


「linux」にすると、何やら更新が行われ、少し設定項目が変わったようだ。

image

Windowsでやるときも設定できるのだろうか?
そのままウィザードを進めると、テンプレートから空アプリかhelloworldかが選べるので、今回はhelloworldを選択。
自動でビルドしてくれるので、できているELFファイルをSDカードにコピーして、PetaLinux起動。
Zyboで立ち上げて、実行。

・・・動くやん。。。


20回に達する前に解決してよかった、と前向きに考えよう。
長い連載で理解したのはこういうことだ。

  • XSDKでアプリのプロジェクトを作るとき、デフォルトでは「standalone」になっていて、これはOS無しで動くバイナリ
  • OS設定を「Linux」にすると、Windows版のXSDKであってもARM Linuxで動くELFファイルを作ってくれる
  • PetaLinuxのCustom moduleではxparameters.hを読んでくれないので、なんとかせんといかんようだ

なお、どのコンパイラが選択されているかは、XSDKのPreferencesにある「Xilinx SDK > Toolchain Preferences」から確認できそうだ。

image

ZynqはCortex-A9だったと思うので、Linaroがデフォルトのようだ。

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (18)

18回目になるのに、まだ解決しないとは・・・。
いや、そもそも最初の目的はなんだったっけ?

第1回を見ると、Zyboのチュートリアル通りにやってみたものの、EclipseベースのSDKから実行すると動くのだが、実行ファイルをPetaLinux上にコピーして実行してもIllegal Instructionが発生した、ということのようだ。
じゃあPetaLinuxの環境でビルドせんといかんのじゃなかろうか、と。
まずは簡単なものから、と考えて見ていったら、Interface誌にJEポートをGPIO制御するドライバサンプルがあって・・・、というのが、現状だ。


しかし、XSDKのベースとしている環境を変更する、という方向もありかもしれん。
せっかくXSDKがあるのだから、コマンドラインでビルドするPetaLinuxはLinux環境やドライバまでで、アプリはXSDKでやっていきたいではないか。


久々にXSDKを立ち上げ、helloworldアプリをビルドした。
そして、XSDKからRunさせると、ちゃんと"Hello Wrold"がコンソールに出力される。
ここでいうコンソールは、ZyboのUSBをPCに接続して開いたTeraTermのUARTコンソールだ。

そのhello.elfを、ビルドしたPetaLinuxが入っているSDカードにコピーして実行すると、やっぱりIlletal Instructionになる。
Zyboチュートリアルのときは、ハードウェアが関係して、不正なアクセスか何かが発生してダメなのかと思っていたけど、そうではないということか?


まずは、fileコマンドで確認しよう。
PC Linux上で確認する。

$ file hello.elf
hello.elf: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, not stripped

staticリンクだから、ライブラリがないということではないだろう。
まあ、そうだったら別のエラーになるはずだ。


Illegal Instruction | Zedboard

む、「Linux Application」と「Standalone Application」の違いがあるのか。
よく考えれば、XSDKから実行するときは、ZyboにLinuxが立ち上がってなくても動作しているし、XSDKからLinux環境ごと転送して起動させているような様子もない。すぐ実行されるし。

ということは、このELFファイルはLinux環境向けではない・・・?
普通のLinux環境向けバイナリはどうなるんだっけ。。。

$ file /bin/grep
/bin/grep: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=a28bf08898e693819102c974c8e54fdcf6f8a7a6, stripped

ああ、そうなのか。。。
XSDKってなんとなくLinux用のバイナリを作ると考えていたのだけど、よく考えたらFreeRTOSもサポートしているので、素のバイナリも生成することができないといかんのか。


コンパイラ変更とかでよいのかしら?
解決は次回にして、今回はここまでにしよう。

2017/09/08

[btc]TXIDとSegwitのTXIDとWTXID

TXID、というものがある。
Transaction IDの略だ。

IDというと、どこかで管理したりしていそうだが、Bitcoinはどこかに依存することがないというか、全体に依存しているというかで、データのためのデータはそんなにないと思う。

ただ、トランザクションを一意に表す数字がないと不便なのも確か。
だから、トランザクション自体のデータからハッシュ計算してIDを求めている。


さて、Segwitが出る以前。
TXIDはシンプルで、トランザクションデータ全体をSHA256し、それをさらにSHA256した値(32byte)だった。

トランザクションの構成は、こうだ。

  • version
  • txin
  • txout
  • locktime

bitcoindでトランザクションを作ったことがある人はわかるだろうが、順番としては、

  • 署名が空のトランザクションを作る
  • 署名する

という手順を踏む。
署名したトランザクションはブロックチェーンに公開することができるので、署名するのは最後なのだ。
だから、TXIDが計算できるのは署名後ということになる。


さて、時代はSegwit。
Segregated Witnessという名前の通り、署名が分離されたトランザクションになる。
トランザクションから分離したということは・・・TXIDからも分離されたのだ(そういう理屈なのかどうかは、知らん)。

しかし、トランザクションデータには署名が入っている。
細かく言えば、txメッセージで送信するトランザクションデータには署名が載っている。
ではSegwitなトランザクションのTXIDはなんなのかというと、計算方法が以前と異なるのである。
計算式はシンプルなTXID時代からするとかなり面倒になったのだが、署名部分は計算から除外するようになった。

だから、非SegwitトランザクションのTXID計算方法と、SegwitトランザクションのTXID計算方法は異なるのだ。


だいたい話は終わりなのだが、余談としてWTXIDのことも書いておこう。

ずばり、WTXIDは、Segwitトランザクションを以前と同じTXID計算方法で求めた値のことだ。
ただ、WTXIDの使いどころが分からないので、計算をしたことがなく、検証まではできていない。
https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#transaction-id

2017/09/07

[c/c++]JSON-RPCでuint64_tに対応するのは難しいか

最近、サーバ型というかdaemon型というか、バックグラウンドで動くアプリを作っている。
それに対して外部から指示を与えたいことがあるのだが、今までLinuxのメッセージキューを使っていた。
それで困っていなかったのだが、他の類似するツールを見るとJSON-RPCでやりとりしていることが分かった。

長いものに・・・巻かれるしかないのか・・・。

同じ形式でAPIを受け付けるように作っておけば、外側の部分は自分で作らずに済むし、そうしておくことによって他の人から使ってもらえる可能性も上がる(たぶん)。

あきらめて、JSON-RPCのパラメータを受け付けるように改造することにした。


こういうときは、githubなどからライブラリを探して、それを使うのがよいだろう。
Google検索して見つかった一番上が、こちら。

httpの方が汎用性が高いのかもしれないが、TCPのsocketをつくってwrite/read()すれば動くので、作るのが楽そうだ。


半分ほど実装していて思い出したが、今回はuint64_tを使っているのだった。
しかし、この子はintかdoubleしか持っていない。
doubleでは丸められる可能性があって困るのだ。。

そういえば、と別の場所で使っているjanssonも見直してみたが、long long型の対応になっているのでint64_tはいけるものの、uint64_tは無理だろう。

よく考えれば、Cは標準型でそこまでしか対応していないし、JavaみたいにBigDecimalみたいな標準もないため、そもそも対応すること自体が難しいだろう。
janssonのbignum版を作っている人もあったが、整数型はgmpかopensslを使うことになるようだ。
うーん、それはちょっと今回の方針にあわない。。。


今回はintかuint64_tまでしか使わないので、自分でuint64_t対応を追加すればよいのだろうが、気力が湧かない(それでいいのか)。
ひとまず、逃げの手段として、uint64_tは文字列に変換して、読み出すときはまたuint64_tとして戻すことにした。
array型で、順番がこちらで決められるからできる技だ。
ただ、serverもclientも自前じゃないとダメなんだけどね。。。


gccなら__int128があるようで、それならuint64_tのサイズでも収まるから少し気は楽になるが、うーん、やっぱり、なんかねー。
この辺りは、pythonみたいに自由な幅にできる言語が有利ですな。

2017/09/05

[btc]regtestでsegwitするにはブロック数がいる

最近、というわけでもないが、testnetが今ひとつ順調ではないように見える。

数日前は、トランザクションが1つ(というか、coinbaseだけ)のブロックが多く、トランザクションが全然さばけていないようだった。
https://testnet.blockexplorer.com/blocks-date/2017-08-31

今日は普通だと思っていたのだけど、なんかsegwitのトランザクションだけ除外されていないか?
そういう真似ができるのかどうか知らんが、数時間前に発行したsegwitのトランザクションがマイニングされないのに、faucetから送ってもらったトランザクションはすぐにマイニングされていたのだ。


よくわからんが、不安定で作業にならないので、regtestを使うことにした。
初めてのregtestだ。


Bitcoinを使ったアプリケーションのテスト環境 - Develop with pleasure!

bitcoin.confを書き換える程度で動かせた。
regtest時のbitcoin-qtは水色だった。

書いてあるように、bitcoin-cliなどでgenerateコマンドを使うと、その数だけブロックを生成してくれる。
これで、マイニングされたことになるので、ビクビクしなくてよいのだ。


しかし・・・segwitのトランザクションを作ろうとaddwitnessaddressしたのだが、segwitは対応していないとか出てくる。。。
regtestなのに!

検索すると、ちゃんと調べてくれた人が見つかった。
How to activate segwit on regtest

あー、101ブロックしか生成していなかったけど、432ブロック以上ないとsegwitがActiveにならないんだ。
しかし、432ブロックというのはなんだろうか?

https://github.com/bitcoin/bitcoin/blob/28f788e47e58f2b462351d6989348a4e1a241b2b/test/functional/bip68-sequence.py#L371
BIP68関連らしい。

https://github.com/bitcoin/bitcoin/blob/28f788e47e58f2b462351d6989348a4e1a241b2b/test/functional/segwit.py#L198
こちらも432だが、144 * 3ということになっている。

144 = 24(時間) * 60(分) / 10(ブロック毎分)

ということかな?
mainnetの時間で3日分というのが432の根拠のようだ。

なんで3日なのかというのは、わからんかったが、まあいいや。

2017/09/04

[win][修復]Windows10が立ち上がらなくなったので復旧 - 2

まさかの第2弾。
というよりも、OSが立ち上がらないということはしばしばあると思うので、その記録だ。

hiro99ma blog: [win][修復]Windows10が立ち上がらなくなったので復旧


予備で用意しているPCがあり、そのWindows10が起動しなくなった。
用意しているというか、マザーボードやCPUが古くなったので一式買い替えたのだが、その前に使っていたPCだ。
Windowsも新しいPCに持っていこうと思ったのだが、マザーボードが変わるとインストールできないという話を聞いたので、そちらは別途購入したのだ。

最後にWindows Updateしたのが1年くらい前だったので、たぶんその間は起動していないのだと思う。
無事に起動したので、過去のデータはもう不要だろう、とWindowsのリセットで全データ消去を選択。
自動的に再起動してクリーンアップが進んだのだが、途中かどこかでブルースクリーンが発生し、再起動を繰り返すようになってしまったのだ。

クリーンアップしたらきれいな状態で立ち上がるだろう、と思っていたので、修復ディスクは作っていたものの、復旧ディスクは作っていない。
復旧ディスクって、USBメモリ1本使うので、もったいない、と思ったのが正直なところだ。


ブルースクリーンになるのはログイン画面が出る前なのだが、F4を押して起動させるとあのメニューは出てくる。
そこでまたPCのリセットを行ったが、エラーが起きましたというだけで何もできない。
修復ディスクで起動させても、同じようなものだった。

復旧ディスクであれば何でもよいかと思い、ThinkPadで作っていた復旧ディスクで起動したのだが、起動させている間にネットで検索すると、どうも共有できるものではないらしい。
ThinkPadはWin10 Home、予備PCはWin10 Proだったのだが、予備PCにWin10 Homeとかいうパーティションが作られてしまった。。。
もちろん、復旧もできなかった。

このWin10はWin7からのネットワークアップグレードでできているので、Win7のディスクはあるものの、Win10用は何もないのだ。


もうあきらめるしかないかと思ったのだが、もう1つ手段があった。
新しいPC用に買ったWindows10のインストールディスクだ。
これが、使えた。
ディスクから起動すると復旧させるボタンが出てくるのだが、それは押さずに普通のインストールを進める。
プロダクトIDを入力するところをスキップさせると、起動時にネットワーク認証を行うらしい(画面にそう出ていた)。
そうやって進めると、無事に起動できる状態になった。

よかったよかった。
復旧ディスクを急いで作ったのは、言うまでもない。


復旧ディスクって、もうすぐ2017年秋バージョンのリリースが行われるそうなのだが、新しくなるごとに更新した方がよいのだろうか?
そこら辺がよくわからんね。

2017/09/03

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (17)

前回の動かん(16)では、xparameters.hにアドレスの定義が載っていることを確認した。

では、ソースに直接書く方法から、includeして参照する方法に変更しよう。
と書き換えたものの、xparameters.hをincludeしてくれない。。。


xparameters.hは、この2箇所にあるのだが、使うのは前者だ。

components/plnx_workspace/fsbl_bsp/ps7_cortexa9_0/include/xparameters.h
components/plnx_workspace/fsbl_bsp/ps7_cortexa9_0/libsrc/common_v1_00_a/src/xparameters.h


パスを継ぎ足していったのだが、componentsから書いても見つからない。
どこからかの相対パスで指定したいのだが、どこから書いてよいものかもわからん。

あきらめてモジュールのソースファイルと同じ場所にコピーしたのだが、それでもダメだ。
カレントディレクトリすら参照してくれないというのか!


と思ってfindすると、実際にビルドするディレクトリはproject-spec/meta-user/recipes-modules/led8drv/filesではなく、build/tmp/work/plnx_arm-xilinx-linux-gnueabi/led8drv/1.0-r0という場所にファイルをコピーして行っているようだ。
そして、filesにあるファイルをすべてコピーしているわけではなく、xparameters.hなどはコピーされていないため、参照できていない、ということらしい。

じゃあ、何を書き換えたらよいかというと、bbファイルを変更するとコピーしてくれるようだった。

SRC_URI = "file://Makefile \
            file://zybo_gpio.c \
            file://xparameters.h \
            file://xparameters_ps.h \

        file://COPYING \
           "

これで、取りあえずはファイルをコピーしてくれてビルドもできるようにはなった。
だが、ファイルを手動でコピーする手間がかかるし、なにより格好が悪い。


PetaLinux Tools User Guide(UG977 v2014.2)にはpetalinux-configで更新できるようなことが書いてあるのだが、最近ではこのドキュメントは更新していないようだし、やってもダメだった。
きっと、ちゃんとしたやり方があるのだろうとは思うが、わからんのだ。
SDK内であれば何かありそうなのだけど、PetaLinuxのところだけでやりたいのだよなぁ。

2017/09/02

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (16)

久しぶりすぎて、内容を覚えていない・・・。

前回は、GPIOのアドレス定義が自動生成されたxparameters.hに載っていることがわかった、というところまでだった。
何をしていたかというと、Linuxのデバイスドライバを作る際、どのアドレスを操作すればよいのかを調べていたのだ。


今見ているのは、これ。
original: http://www.cqpub.co.jp/interface/download/2016/4/IF1604Z.zip

Interface誌のサンプルをちょっと変更した程度のものだ。
GPIOのアドレスは、gpio_table[]を使っている。

動かん(14)のときにどれを使っているのか計算しているが、mknodしたのが24なのでgpio_table[3]ということだ。
そのアドレスは、0x41200000 + 0x10000 + 0x0。

./components/plnx_workspace/fsbl_bsp/ps7_cortexa9_0/include/xparameters.hを見ると、こういう行があった。

/* Canonical definitions for peripheral BTNS_4BITS */
#define XPAR_GPIO_0_BASEADDR 0x41200000
#define XPAR_GPIO_0_HIGHADDR 0x4120FFFF
#define XPAR_GPIO_0_DEVICE_ID XPAR_BTNS_4BITS_DEVICE_ID
#define XPAR_GPIO_0_INTERRUPT_PRESENT 0

まず、MAP_BASE_ADDRの根拠はわかった。
zybo_gpio.cでは固定値なので、このアドレスも求める方法があるのだろうが、まあ、よかろう。


次はオフセットだ。
制御しているのはZYBOのJEコネクタで、0x41210000から1KBをioremap()し、32bitを書込むようにしている。

ああ、こういう定義が近くにあった。

/* Definitions for peripheral LEDS_4BITS */
#define XPAR_LEDS_4BITS_BASEADDR 0x41210000
#define XPAR_LEDS_4BITS_HIGHADDR 0x4121FFFF
#define XPAR_LEDS_4BITS_DEVICE_ID 1
#define XPAR_LEDS_4BITS_INTERRUPT_PRESENT 0
#define XPAR_LEDS_4BITS_IS_DUAL 0

Block Designを見ると、GPIO類はこうなっていた。

image

この名前が、そのままマクロ定義になるのか。


mknodするminor番号だが、zybo_gpio.cではビットを表していたのか。

0- 7 : ボタン
8-15 : DIPスイッチ
16-23 : 未割り当て
24-31 : LED

だから、16~23だとエラーなのか。
ビットシフトを3つやってるのも、8bit単位で何番目かを割り出すという意味なのだろう。
読み書きの方向についてはminorのb4を使っているが、0~15はINPUTだから使っただけか。
LEDでもスイッチでもいけるように、GPIO_BUFFという構造体を用意して、そこに情報を突っ込み、あとはシステムコールで呼び出されたらそれを使うだけ、ということにしたかったのだろう。


ioremap()は、物理メモリをアクセスする準備みたいなもののようだ。
IoMemoryAccess - Kernel Newbies Japan
MMUもあるし、こういうやり方になるのか。
戻り値をそのまま使ってよいわけではなく、readb/w/l()、writeb/w/l()を介してアクセスするそうだ。
zybo_gpio.cでは iowrite32()を使っているので、ビット幅で指定するタイプもあるのか。

9.4. Using I/O Memory
こちらはオライリーのLinux Deveice Drivers第3版の元ページ?のようだが、readb()などのタイプはolderと書いてある。
まあ、ビット幅の方がわかりやすいわね。


ioremap()だが、終わったらiounmap()しなくてよいのだろうか?
なんとなく、close()時にやった方が良い気がする。

Linuxデバイスドライバのお作法がわかっていないので、基本的なところは抑えた方がよさそうだ。

[c++]Boostのdijkstra_shortest_paths() - end

Boostのグラフで経路を求めたので、最後に、自分であれこれやったソースをGistに置いておこう。

boostのグラフを使って経路探索するサンプル


経路は、boost.jpのグラフにあるものを使った。

$ g++ -o tst dijk_dist.cpp
$ ./tst
distance: 11
START --> Asia --> Beer --> Devel --> Foobar --> GOAL


Boostのサンプルにあった、graphvizで出力するやりかたも真似した。

image

双方向にしたのでゴチャゴチャしているが、方向によって重みが違う場合にはこうやることになるだろう(今回は同じ重みだが)。

[c++]Boostのdijkstra_shortest_paths() - 4

前回は、dijkstra_shortest_paths()に重みを指定しつつ、経路を得るための引数を指定するところまでだった。
なんであんな中途半端で終わらせたかというと、仕事に行く時間だっただけだ。。。

動作結果は、OKだった。
検証したソースを載せたいところだが、そっちは仕事で書いているコードでやってしまったのだ。すまん。


第3引数には他の種類もある。
こちらでは、visitor()というものを使っている。
Boost.Graphに入門 - Faith and Brave - C++で遊ぼう
やっていることは同じような内容なのだが、最短経路以外にも試されている。


BoostのGraphは自由度が高いので、あれこれできてしまい、検索して見たサイトで全部やり方が違っていて「うーん、難しい・・・」と感じてしまう。

ただ、便利だし、Cから使うときもそこだけライブラリにしておけばうまいことやれるんじゃなかろうかと思う。
Makefileで、CとC++を混在させるやり方がよくわからんのだ。。。
.oを.cやら.cppに見立てる方式ではダメだから、最近はソースファイル名を列挙する方式にしているのだけど、extern "C"だけでうまく回避できるんだっけ?


いかんいかん、話が逸れてしまった。
ともかく、BoostのGraphは、大ざっぱに言えば、

  • adjacency_list<>でグラフを構成する型を作る
  • そのインスタンスを作って、vertexやedgeを突っ込んでいく
  • アルゴリズムを実行
  • 結果を得る

という流れのようだ。

そして、vertexやedgeは単純なものであれば元からある型を使えばよいし、プロパティとして複数の情報を持たせたければ構造体などを指定すればよい。
プロパティを自前で用意する場合は、重みをweight_map()で指定する。
距離の結果を得たい場合はdistance_map()を、経路の結果を得たい場合はpredecessor_map()を指定する。

私が使う範囲では、このくらいわかっておけばよさそうだ。

2017/09/01

[c++]Boostのdijkstra_shortest_paths() - 3

第3回。前回はこちら


前回は、グラフの有向や無向の設定だけを見た。
それ以外にグラフの設定で使いそうなのが、プロパティだろう。
経路探索する場合は、vertexとvertexのつながりだけでなく、経路の取捨選択に用いる情報を付加することが多いからだ。
よくあるのは、距離とか、そこを通るのにかかる費用とか。

距離のような単純な情報であればboostが用意していて、edgeのプロパティとして

boost::property<boost::edge_weight_t, int>

などと書いてあげればよい(これはint型の重み)。


ただ、重みの情報は1つだけど、そのルートを通るようになった場合に参照したくなる情報もある。
さっきの例でいえば、重みとしては距離を使うけれども、経路が分かった後には通行料を知りたい、などという場合だ。
そういうときは、自分でプロパティを設定できるようである。


https://boostjp.github.io/tips/graph.html#bundle-property
ここでは、structを作ってプロパティにしている。
何でもいいのかな?
まあ、C++のtemplateはマクロみたいなものだったと思うので、ちょっと種類が異なるグラフ型を作ると、それに関連する関数も新たに作ることになってしまうのだと思うが。

試して分かったが、このプロパティにする型だが、関数内に書いてはダメだった。
グローバルスコープじゃないと展開できないのだろう(私はC++にあまり詳しくないので、推測だ)。


あとは真似をしておけばdijkstraで経路探索したり、距離を表示させたりすることはできた。
しかし、サンプルではせっかくedgeにもプロパティを付けてTokyoやNagoyaを設定しているのに、表示するときには固定文字列を使っている。
かといって、map[v1].nameなどと指定するだけでは芸が無い気もする。

それに、これは2点間だからよいが、複数のvertexがあって経路探索した場合は、どの経路を通ったかをもらって、そこからプロパティを取得していきたいではないか。


https://boostjp.github.io/tips/graph.html#dijkstra-shortest-paths
経路探索して、その経路を出力するサンプルがこちらだ。
プロパティはedgeだけで、int型になっている。
そして経路出力しているところを見ると、parentという変数を使っている。
使われ方は・・・ああ、プロパティサンプルのdistanceと同じ立ち位置なのか。

ただ、プロパティのサンプルではboost::weight_map()を使っているが、ここではboost::predecessor_map()を使っている。
dijkstra_shortest_paths - boostjp
weight_map()はINで、predecessor_map()はOUTだ。
INなのに、なぜ・・・。

あ、dijkstra_shortest_paths()が長いので気がつかなかったが、引数は3つしかないんだ。
そして、第3引数はxxx_map()がドットでつながっている。


Boost Graph Library: Dijkstra's Shortest Paths - 1.65.0

引数が3つのタイプは、これだ。

// named parameter version
template <
         typename Graph,
         typename P,
         typename T,
         typename R>
void dijkstra_shortest_paths(
         Graph& g,
         typename graph_traits<Graph>::vertex_descriptor s,
         const bgl_named_params<P, T, R>& params
);

最後のparamsが、xxx_map()が連鎖しているところになる。
引数が多いタイプも合って、そっちはnon-named parameter versionと呼ばれている。
あまり読んでないが、ここに書いてあるxxx_map()をどんどんつないでいって、指定したいものだけ指定すれば応じた結果が得られるということだろう。


プロパティのサンプルは、こう。

weight_map().distance_map()

経路を求めるサンプルは、こう。

predecessor_map().distance_map()

プロパティのサンプルは重みを別のところから取ってくるからweight_map()を使っているのだろうか。
しかし、それならプロパティにHighwayを指定しなくてもなんとかなるんじゃ無かろうか、と思ったが、それはコンパイルエラーになった。
ではweight_map()だけ外したらどうなるかと思ったら、それはdistance_map()がわからんと言われた。
distance_map()は「UTIL/OUT」になっているから、オプション扱いで、何かの後ろに付けるということか。


weightは任意のプロパティから指定したい、経路の情報は欲しい、ということであれば、こんな感じにするとよいのか。

    std::vector::vertex_descriptor> pred(num_vertices(map));
    std::vector distance(boost::num_vertices(map));
    boost::dijkstra_shortest_paths(map, v1,
            boost::weight_map(boost::get(&Highway::distance, map)).
            predecessor_map(&pred[0]).
            distance_map(&distance[0]));


検証は、次回だ。

[c++]Boostのdijkstra_shortest_paths() - 2

意外なことに、2回目です。
前回はこちら


グラフ - boostjp
このサイトを見て、探索はできるようになったのだが、あまりにも理解できなさすぎて、応用がまったくできない。
理論はもうあきらめるとして(いいのか。。。)、主な使い方くらいは覚えよう。


ツリーではなく、グラフだ。
だから、ノードやブランチではなく、vertexやedgeと呼ぶようだ。
まあ、ツリーでもedgeを使ったりするようなので、そこまで依存した言葉遣いではないのだろう。


このグラフ全体をclass adjacency_listが持つようだ。
派生して使うのではなく、templateになっていて、テンプレートパラメータを指定することでグラフ全体の設定になるようだ。

説明はサイトを読んだ方が早いだろう。
主に変更しそうなものは、グラフの有向(一方向、双方向)/無向と、カスタムプロパティかな。
双方向有向が無向と違うのは、重みが方向によって替えられたり、辺によって一方向にすることができる、というところか。
細かいけど、片方向はdirectedS、無向はundirectedSだけど、双方向はbidirectionalSと末尾が違うので注意だ。


こんな感じで、じわじわ読み進めていこう。

主な使い方、と最初に書いたものの、それですらいつ終わるかわからんが、やらねば終わらぬのだ。

2017/08/30

[git]branch名にスラッシュは使えるが、使うなら最初から使うこと

他の人のgitリポジトリを見ていたのだが、ブランチにスラッシュを使っていた。
作業者ごとに掘っていたり、課題ごとに掘っていたりと、なんか見やすい気がする。

やだ、カッコイイ、やってみたい(ミーハー)!


$ git checkout -b test1
$ git checkout -b test1/help
fatal: cannot lock ref 'refs/heads/test1/help': 'refs/heads/test1' exists; cannot create 'refs/heads/test1/help'

話が違うじゃないか・・・。

ネット検索すると、branch名と同じ名前のディレクトリをmkdirするときにエラーが出たので失敗している、ということらしい。
Using the slash character in Git branch name - Stack Overflow

mkdir -pしてないからディレクトリが掘れないのか?と思ったが、そうではない。

$ ls -F .git/refs/heads/
master  test1

ああ、branchで作るのって、ディレクトリじゃなくてファイルなんだ。
てっきり、ディレクトリを作って、その中に管理ファイルを置くものだとばかり思っていたのだ。
mkdirして失敗するのは、既にディレクトリと同じ名前のファイルが存在しているからだ、ということになる。

branchつくって作業をしていたけど、ついでにこっちの作業も並列で進めたくなって、でも元のbranchから派生させるようなものでもないから今のbranchから作りたくて、どこかの時点でマージさせたい、ということがあって、そこでスラッシュを作って派生しているのがわかるようにしようと思っていたのだ。
アンダーバーで区切ればよいのだけど、単語の切れ目で使っているので、それはそれで分かりづらい。


ともかく、gitのbranch名にスラッシュは使えるのだが、使うなら最初からスラッシュを付けて作っておかないと後からはできないよ、という話でした。

2017/08/29

[c++]Boostのdijkstra_shortest_paths()

Cで、dijkstra法による経路探索を行いたかった。
最短の経路探索法なら何でもよいのだが、思いつくのがdijkstra先生の方法しかなかったのだ。

一応、大昔に受けた授業でやった記憶だけは残っている。
動的計画法だのなんだのかんだの。
だから、アルゴリズムの本を読めば記憶が甦ってくるんじゃなかろうかと期待したのだが、うん、ダメだね。


そして最初に書いたように、経路探索を行いたいだけで、別に経路探索するアルゴリズムを自分で実装したいわけではない。
ライブラリでもサンプルソースでも、動けばよかろうなのだ。

よかろうなのだが、なかなか気に入ったソースが見つからない。
よく見るのは、M x Nの2次元配列を作るタイプだ。
しかし、今回は動的に増えていくので、そういう書き方だとやりづらいし、メモリをいっぱい使うことになるので嫌だ。

1ヶ所見つけたのだが、そこはサイトがGPL1.2で、これはこれでよろしくない。
もう少しゆるめのライセンスがよいのだ。


そこで妥協したのが、C++にすることだった。
今作っているCのライブラリさえ使えればよいので、C++でもよいのだ。

C++といえば、やはりBoostよね。


Boost Graph Library: Dijkstra's Shortest Paths - 1.65.0

うーん。。。すごく見づらいぞ。
蛇のアイコンもあるし、pythonと関係あるのか?

もっとわかりやすいサイトがあるはず、と探すと、ありました。
グラフ - boostjp
ありがたいことに日本語だ。


始点Sから終点Zまでの経路探索をするサンプルになっている。
ノード・・・じゃなくてvertexと表現している。頂点か。
そして、頂点と頂点を結ぶ辺をedgeという。
edgeには重みがあり、それはweightだ。

というのはサンプルソースの最初の方を読んでなんとなく分かったが、型とか使い方になるとサンプルソースを読んでも今ひとつ分からない。
いきなりdijkstraのところからやるのではなく、Boostのgraphというものについての考え方や方針を把握した方がよさそうだ。
これも同じページの最初の方に書かれている。


が、しかしこれは・・・複雑だ。
日本語で説明してあって、さらに例まで載っているからわかるものの、そうじゃなかったら使い切れない気がする。

2017/08/24

[btc]confirmation

Bitcoinだけではないと思うが、ブロックチェーンに関することをやっていると「confirmation」というものに出くわすと思う。

自分がBitcoinで取引するためにトランザクションを作ってブロックチェーンに公開する場合、だいたいこういう流れになる。

  1. 自分が送金したい相手に対してのトランザクションデータを作る
  2. トランザクションデータをブロックチェーンに公開するため、どこかのノードに送信する
  3. (トランザクションデータが正しくて、ブロックチェーンのノードに受け入れられたとする)
  4. そのノードが、他のつながっているノードに対してトランザクションデータを転送する
  5. 一定期間が経つと、マイナーがブロックを作り始める
  6. あるマイナーが作ろうとするブロックに、自分が送信したトランザクションデータが取り込まれる
  7. そのマイナーが他のマイナーとの競争に競り勝ち、作ったブロックがブロックチェーンに公開される

大ざっぱに、だ。
まだマイニングしたことがないので、詳細な流れは把握していない。


さて、confirmationというのがこの流れのどこに出てくるかというと、「ブロックに取り込まれたときが1confirmations」だ。
ブロックに取り込まれるまでは、mempoolという貯木場みたいなところにトランザクションが浮かんでいるだけだ。

では、2confirmationsはいつかというと、1confirmationsになったブロックに、次のブロックが連結したときだ。
以降、ブロックが載っていくごとにconfirmationは増えていく。


一般的に、confirmationが6以上であれば大丈夫、といわれている。

大丈夫?何が??

最初に書いておかねばならんが、私はこの辺の数学的な検証については非常に疎い。
つまり、うん、わからんのだ。。。
だいたいどこにでもそう書いてあるから、そうなんだろう、くらいの根拠しかない。
まあ、6というと、6σとかあるから、なんかそれっぽいな、程度しか言えることがない。


ただ、Bitcoinのブロックチェーンには「展性」という脆弱性がある。
トランザクション展性、などと呼ぶらしい。
詳しくないので割愛するが、実際に開発している間に受けると、かなりびっくりする。
自分がトランザクションを作って、トランザクションをブロックチェーンに公開して、それが自分の立てたノードに受け入れられたところまで確認しているのだが、コーヒー飲んでおしゃべりして、そろそろconfirmationが増えたかと思って確認しようとしたら、TXIDが存在しない、ということになるのだ。


ああいうのを受けてしまうと、いろいろ考えますわな。

2017/08/23

[c/c++]設定ファイルを読みたい

プログラムを作っていて、設定ファイルを使いたいことがある。
引数に設定してもよいのだが、個数が多かったり、同じ設定を何度も使うことになったりすると、どうせなら設定ファイルにしてしまいたいのだ。


Linuxには、これといった設定ファイルの書式がなさそうではあるが、だいたいはこんな感じだと思う。

  • 項目=設定値
  • コメント行は#
  • =の前後にスペースがあったり、空行があってもOK


「項目=設定値」だけであれば、こんな感じのことをやっていけば読込むことができる。

char name[32 + 1];
fscanf(fp, "name=%32s\n", name);

(\0は%32sの中に入るんだっけ・・・)

しかし、こんなのをゴリゴリとコーディングしていくのも面倒だ。
それに、これだとスペースや改行を処理することができないので、割り切ってしまえばよいものの、なんか、ねぇ。

また、そういうのを自作したいわけでもない。


ネットで「linux 設定ファイル 編集」なんて検索しても、期待するものが見つからない。。。
ようやく見つけたのが、こちら。

benhoyt/inih: Simple .INI file parser in C, good for embedded systems

iniファイルのパーサーだそうな。
セクションを[]でわけるし、コメントは「;」だけど、コメントはINI_INLINE_COMMENT_PREFIXESで変更できるらしい。
READMEに載っているサンプルで読込んでいるtest.iniは[protocol]と[user]というセクションがあるけれども、がなくても使えるのではなかろうか?


まずは、ライブラリを作る。

$ git clone https://github.com/benhoyt/inih.git
$ cd inih/extra
$ make -f Makefile.static
$ cd ../examples
$ gcc -o tst ini_example.c -L../extra -linih
$ ./tst
Config loaded from 'test.ini': version=6, name=Bob Smith, email=bob@smith.com

うん、シンプルでよいじゃないか!


では、test.iniのコメントを#にして、カテゴリーを削除したファイルではどうなるか・・・。
うーん、エラーにならず、変な値が読み取れてしまった。

サンプルソースを見ると、handler()の中でsectionを比較するようになっていた。
MATCH()マクロからsection比較している部分をなくすと、読み込めるようになった。

よしよし。


最後に、#をコメントにしたMakefileを載せておこう。

https://gist.github.com/hirokuma/a2c4bab70d43db8ddf17b1a673da1b3e

Makefileでgccの文字列マクロを設定するときって、こうやるのね。。。
#もエスケープせんといかんのは、盲点だった。

2017/08/21

[c/c++]中途半端にハンガリアン記法風の名前を使っている

私がC/C++を覚えていた頃は、変数名などの名前付け方法に「ハンガリアン記法」というものがあった。

なくなるものではないので、今もあるとは思うが、面倒なのであまり使われていないと思う。
私も、ちゃんと使ったことはない気がするのだが、型を変数名に反映させるなんてやめてくれー、と思っていた。


しかし、だ。
自分でコーディングするときに、型を変数名に反映させている場合があることに気付いた。

boolとポインタだ。
boolの場合は「bFlag」とか「b_flag」とかだし、ポインタは「pData」とか「p_data」とかだ。

もしかすると、これもハンガリアン記法になるんじゃなかろうか。
いや、そもそもハンガリアン記法ってなんなのだろうか?


ハンガリアン記法 - Wikipedia

ハンガリー出身の人が考案者だからハンガリアンなのか。。。
チャールズ・シモニーさんらしいから、チャールジアンとかシモニアンとかでもよかったんじゃなかろうか。
でも、逆ポーランド記法みたいなこともあるし、それはそれでよいのかもしれん。


そして、論文に書いてあった「type」を、データ型として当てはめてしまったので型を反映させるような読まれ方になってしまったが、考案者としては「変数の意味や使用目的」と意図していたそうな。

まあ・・・「type」をそう読み取ってしまったのは、仕方ないよな。。。
それに、私もWikipediaを読んだだけで、原文を当たったわけではない。
だから、本当にそうなのかはわからんが、それっぽいよな。


こちらが、たぶん原文。
Hungarian Notation
なんだ、Microsoftの人だったのか。

表に例があるし、コードもあるのだが、データ型を名前にしている感じはしないな。


Wikipediaには「アプリケーションハンガリアン」と「システムハンガリアン」の2種類があると書かれているが、これは論文に書いてあったものではなく、Microsoftがハンガリアン記法を決めたときに作ったものなのかな。


Wikipediaに書いてあるシステムハンガリアン風の書き方で私が使っているのは、これらだ。

  • 論理型(頭にbをつける)
  • ポインタ型(頭にpをつける)
  • ファイルスコープの変数(頭にmをつける)
  • グローバルスコープの変数(頭にgをつける)
  • typedefした型(お尻に_tをつける)

最近はC++を使ってないので、classを作ったらどうするかはよくわからん。
大文字で始める、くらいのルールにしそうな気がする。

ファイルスコープのポインタ型、みたいな合わせ技もあるのだが、それは「mpData」みたいな書き方にしている。

引数は大文字で始まり、スタック変数は大文字を使わない、というルールにしているつもりなのだが、あんまり守ってない。。。
Dataとdataとか、pDataとp_dataとか。
なるべく守ろうとするのだが、1つの関数を書いていて大きくなりすぎてしまったからstatic関数に分ける、なんてことをやってしまうと、変数として小文字を使っているので、関数の仮引数を大文字にしてしまうと面倒になるので放置、ということがしばしば。


ああ、そういうのが変なるールを作ったことによるコストなのだよな。。。

プロジェクトだと、ある程度コーディング規約を決めないとバラバラになりすぎるのだけど、ぎちぎちにしてしまうとコーディング自体が楽しくなくなるので、難しいところだ。

2017/08/18

[linux][c/c++]現在時刻の取得

Linuxで時間の取得を行いたい場合がある。
今の時間だ。
time(NULL)でepoch timeを取得していたのだが、それでよいのか自信がなくなってきた。


マイコンの場合、RTCに設定した時刻が取ってこれるだけで、それ以上でもそれ以下でもない。
それに、RTCから自分で値を引っ張り出さないといけないので、epochも何も気にしようがない。

しかし、time()はきっとライブラリ側でOSが管理しているしくみに置き換えられているはず。
Linuxで時間といえばgettimeofday()だよなあ、と検索したのだが、どうもgettimeofday()は廃止予定らしい。
gethostbyname()もそんな感じだったな。。

推奨されているのは、clock_gettime()
まずは動かしてみよう。

https://gist.github.com/hirokuma/17bdf87bf3c8c6f29008e74635f9984e

2017/08/18 10:10くらいにBash on Ubuntu on Windowsで実行させると、こうなった。

$ ./tst
tv_sec=1503018649, tv_nsec=105938100

ネットでepochを現在時刻に変換するサイトを見つけてやってみると、JSTとして変換すると現在時刻になった。
dateコマンドでは、こうなる(あれこれしているうちに5分くらい経ってしまったが)。

$ date
Fri Aug 18 10:15:53 DST 2017


これは、内部ではUTCで管理していて、出力時にJSTの下駄を履かせているという考え方でよいのだろうか?
(DSTになっているのも気になるが。。。)
VirtualBoxで動かしているXubuntu16.04でも同じになったので、Bash on Ubuntuがそうしているわけではなさそうだ。


そして、epoch timeは各地の時刻ではなく、UTCで出すというのが共通の認識ということでよいのだろうか。
数字しかないので、UTCがデフォルト、のようなルールがないと困るのだけど、明示的に書いてある資料が見つからない。


オライリーの「C言語クイックリファレンス」には、

  • time()は現在のカレンダー時刻を返す
  • これは、紀元と呼ばれる
  • Unixの紀元はUTCの1970年1月1日 00:00:00

とある。
そして、「紀元」は"epoch"だから、epoch timeはUTCということでいいんじゃないかな。
うんうん、そうしておこう。

tig

ファイル履歴管理にgitを使っているのだが、未だにコマンド慣れしていない。
慣れない操作で失敗するのも嫌なのでGUIのツールを使っていたのだけど、最近はクラウド上につくったVMを扱わんといかんことも多くなり、なるべくgitをコマンドラインで使うようにしている。


でも、ある程度はGUIっぽく表示してくれた方が見やすいじゃないか。
そう思って探していると、tigというコマンドが見つかった。

gitを逆に並べたtigだが、コマンドラインで動かすツールながらも、GUIっぽく出してくれる。
なんというか、FDみたいなコマンドになるのかもしれん。
・・・FDってWindowsのみだったかも。


tigの操作は、ちょっとviっぽい。
カーソルの移動がそうだからか。


使うのは、ステージに挙げたりcommitしたりするところが主だ。
git addするとき、ファイルのパスをいちいちコマンドで書くのが面倒なのだよ。

tigを立ち上げて、sを押して更新したファイルの一覧を出し、uを押してcommitしたいものをステージに上げる。
上げ終わったら、大文字のCを押してcommitするエディタを起動する。
うちではnanoが立ち上がった。

historyなんかも重たくなく見られるので、使いこなせると便利そうだ。


ただ、最近はtigする気力も無いので、VirtualBoxでGUIが動く状況であればVisual Studio Codeを使っている。
差分なんか見やすいしね。

2017/08/17

[勉]MIPI

Xilinxからメールが来た。

MIPI D-PHY 搭載のザイリンクス UltraScale+ デバイス

MIPI?
初めて聞く単語なので、これは調べねばなるまい。


Mobile Industry Processor Interfaceの略らしい。

デバイス古今東西(17) ―― 撮像デバイスの変遷と次世代標準インターフェースMIPI規格|Tech Village (テックビレッジ) / CQ出版株式会社

「モバイル機器向け」なのだそうだ。
記事が2010年なので、7年前にはすでにあった規格ということになるな(2003年らしい)。

シリアル通信というと、UART, I2C, SPI, USBなどなど、たくさんある。
そこに連なるようなものなのか、


こちらが、mipi allianceのページ。
https://www.mipi.org/

仕様書をちょっとくらい見てみようかと思ったけど・・・数が多くて止めた。
Specifications Overview

カテゴリーだけで、これだけある。

  • Audio
  • Camera and Imaging
  • Chip-to-Chip/IPC
  • Control and Data
  • Debug and Trace
  • Display and Touch
  • Physical Layers
  • Software Integration

まあ、NFC Forumの規格もたくさんあったし、そういうものかもしれん。


これで終わってしまうのはさすがに悔しいので、Xilinxのメールで紹介された規格くらい調べておこう。

「MIPI D-PHYを搭載」

mipi allianceの説明ページは、こちら
PHYなので、物理層なのだろう。
スマートフォンのカメラやディスプレイ向きのようだ。

技術的な内容は出てこなかった。


MIPI ‐ 通信用語の基礎知識

同期式とのこと。
ソース同期と書いてあるので、クロック線は持たず、データ自体がクロックと同じ意味を持つということか。
マンチェスターみたいな感じかな?
マンチェスターだと1bitを2データで表すが、差動だと1データ分の時間で2データを表現できるので、倍の速度になるのかも。
上限が1Gbpsとなっているので、なにか技術的に上限が発生するのだろうが・・・そこまではわからんな。


これで終わろうと思ったが、最後に見たページではもう少し情報が載っていた。
前田真一の最新実装技術あれこれ塾:第47回 内部ディスプレイ接続規格 (4/4) - MONOist(モノイスト)

高速モードは1.5Gbpsみたいだ。
そして、予想と違ってクロック線があり、ビデオ信号だとレーンを複数用意するようだ。
下手に予想するもんじゃないな。

2017/08/11

hexdumpで16進数を出力したい

バイナリファイルをソースコードに埋め込みたいことがある。
画像データを配列として使いたい場合などだ。

ファイルから読み込んで%02xなどで出力させるだけなのだが、いちいちコマンドを作るのも面倒だ。
hexdumpというコマンドがあるのでやってみたが、オプションを使えばなんとかいけそうなものの、よくわからん。
だいたい、なんで2バイトごとに出すのがデフォルトなんだ?


と、コマンドに文句を言ってもしょうがないので、オプションを調べよう。

hiro99ma blog: hexdumpのフォーマット

0xを付けた出力をしたい場合は、これでよい。
これは8バイトごとに改行しているので、8/1になっている。

$ hexdump -e '8/1 "0x%02x, " "\n"'  abcdef.bin


pythonで、ひたすらずらずら並べた文字列を作りたいこともある。

$ echo "$(hexdump -e '1/1 "%02x"' abcdef.bin)"

echoはなくてもよいのだけど、改行を付加しないので、コマンドラインで実行すると見づらかったのだ。


で、hexdumpを16進数の1桁ダンプ以外で使うことが無さそうなので、aliasに登録しようとした。

alias hexdump='hexdump -e '\''1/1 "%02x"'\'

いやあ、こんなに難しいとは。。
シングルクオーテーションで全体を囲む中にシングルクオーテーションを入れたい場合は、

  • 一度シングルクオーテーションを閉じる
  • \'を付ける
  • シングルクオーテーションを始める

ということをせんといかんそうだ。

青文字がシングルクオーテーションで囲んだ範囲、赤文字がエスケープしたシングルクオーテーションとなる。

alias hexdump='hexdump -e '\''1/1 "%02x"'\'


aliasをシングルクオーテーションで囲むのは、スペースも含めて入れてほしいという場合だけのはず。
まあ、これで登録しても、aliasコマンドで見ると

alias hexdump='hexdump -e '\''1/1 "%02x"'\'''

なんだけどね。

2017/08/07

[c/c++]lmdbでの検索

たまにはFPGAを離れて、DBのことをやってみるのもよいだろう。
そうだな、lmdbなんてどうだろうか?


最後にlmdbのことをやったときは、付属サンプルのmstest.cを見ていくだけだった。
今回は、KEYから検索したり、VALUEから検索するときのことを考えよう。



今のところ、私のlmdbに対するイメージはこうだ。

image


mdb_env_create()で1つのENVを作り、mdb_env_open()する。
ENVからmdb_txn_begin()でTXNを開始し、同じトランザクション内で処理したいものをmdb_dbi_open()でDBIを開く。
あとは、TXNとDBIのセットでmdb_put()したりmdb_get()したり。
終わってトランザクションを確定させたいなら、mdb_txn_commit()してmdb_dbi_close()。
変更したものを破棄するなり、読込むだけで保存するものが無ければ、mdb_txn_abort()だけ。
mdb_put/get()だけでなく、cursor系のAPIもある。


さて、検索するには、どのAPIを使うのがよいのか。。。

いまのところ、私の認識はこうだ。

  • KEYが指定できる場合は、mdb_get()
  • それ以外は、cursor系APIでDBIの中を全部探す

SQLではないので、自分でやるしかないだろう。
mdb_cmp()で比較するようなことができるのかと思ったが、関係なさそうだ。


自分でやるしかないので、全部KEY-VALUEに突っ込むだけではなく、DBIをうまいこと分散させるのもよいだろう。

2017/08/05

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (15)

前回は、ZYBOのPmod JEをたたくドライバに載っているアドレスからリファレンスマニュアルを調べようとしたけど失敗した、というところまでだった。


ならば、正攻法で調べるしかあるまい。
Pmod JEからたどっていくのだ。

image

7本使っているが、1本見ればよかろう。

image

これはIC19Bなのだが、IC19AがZynqだから、これもZynqのピンなのだろう。
V12は、IO_L4P_TO_34という名称なのか。


これで検索して出てくればよかったのだが、それっぽいものが出てこない。
テクニカルマニュアルj_ug585-Zynq-7000-TRM.pdfの「2.8 PL I/Oピン」に載っているT[3:0]がそれか?

image

T0だから、メモリバイトグループT0に属するメモリバイトグループということか。


同じ表の中に、こういうのもあった。

image

IO_L3N_だから、こっちの可能性もある。

詳細は「パッケージおよびピン配置ガイド(pdf)」を参照とのこと。
別ドキュメントかー。


Zyboに搭載されているのは、ZYNQ XC7Z010-1CLG400C。

image

SIOとPS I/Oに大別されている。
PS I/OはPS側から制御するI/Oだろうから、SIOはPL側から制御するのかと思ったが、SIOは「SelectIOリソース」という意味らしいので、PSかPLかを選択できるのかもしれん。

ネットで検索すると、「7シリーズ FPGA SelectIOリソース ユーザーガイド」というPDFが出てきた。
7シリーズはZynqのPL部だから、PL部なのだろう。
Zynqの概略図でも、PL部に"Multi Standards I/Os"というものがあるし。
https://japan.xilinx.com/content/dam/xilinx/imgs/block-diagrams/zynq-mp-core-dual.png


IO_L4P_T0_34という名前だが、こういう意味になると思われる。

  • IO : ユーザーI/Oピン
  • L : 差動ペア
  • 4 : バンク固有のペア
  • P : 差動ペアの正側
  • T0 : メモリバイトグループT0に属する
  • 34 : バンク番号

さっぱりわかりません。。。


まず、バンクの説明図があった。
PLバンクの図らしい。

image

「すべてのHP I/Oバンクは完全にボンディングされていて、すべてのPSバンクは完全にボンディングされている」らしい。
HPと書いてあるけど、表ではHPが0本、HRが100本だったから、HR I/Oバンクだと思う。

  • HR : Hight Rangeバンクのことで、3.3V対応という意味のようだ
  • HP : Hight Performanceバンクのことで、1.8V対応という意味のようだ

Vivadoでも1.8Vを3.3Vに変更していたが、こういう意味があったのか。


ピン配置はASCIIファイルになっているらしい。
XC7Z010のCLG400はこれ
うん、V12はIO_L4P_T0_34で、メモリバイトグループ0、バンク34だね。
そして、I/Oタイプは「HR」とのこと。
さっきの図でBank 34 HRとなっていたから、そのままなのかな。


あとは、ピン配置の図と、ハンダ付けとかそういう説明があったが、今回はよかろう。
ピンの数は、20x20 = 400本のようだ。


わからなかった用語を検索しておく。

差動って、USBとかで使われている正負が逆転したやつだろうか?
それとも、差動増幅というやつだろうか。
なんとなく、前者っぽい。
https://ja.wikipedia.org/wiki/%E5%B7%AE%E5%8B%95%E4%BF%A1%E5%8F%B7#.E9.AB.98.E5.91.A8.E6.B3.A2IC.E3.81.AB.E3.81.8A.E3.81.91.E3.82.8B.E5.B9.B3.E8.A1.A1.E6.8E.A5.E7.B6.9A


というわけで、アドレスについては書いてなかった。

次はデバイスツリーを見る。
これにはアドレスが書いてあったはずなので、そこからたどれるかもしれん。
というより、アドレスを直接ドライバに書くのではなく、最終的にはデバイスツリーから取ってくるようにせんといかんのか。


0x41200000だが、ZynqではなくARMの方(plnx_arm-system.dts)に出てきた。
そっちか!

		gpio@41200000 {
			#gpio-cells = <0x2>;
			compatible = "xlnx,xps-gpio-1.00.a";
			gpio-controller;
			reg = <0x41200000 0x10000>;
			xlnx,all-inputs = <0x1>;
			xlnx,all-inputs-2 = <0x0>;
			xlnx,all-outputs = <0x0>;
			xlnx,all-outputs-2 = <0x0>;
			xlnx,dout-default = <0x0>;
			xlnx,dout-default-2 = <0x0>;
			xlnx,gpio-width = <0x4>;
			xlnx,gpio2-width = <0x20>;
			xlnx,interrupt-present = <0x0>;
			xlnx,is-dual = <0x0>;
			xlnx,tri-default = <0xffffffff>;
			xlnx,tri-default-2 = <0xffffffff>;
		};

ARMの方ではあるが、xlnxとなっているところが多いから、たぶんXilinxがカスタマイズしたのかな。


Zynqの概略PNGを見ると、PS部とPL部の接点は多くなかった。
そういえば、ZynqにAXI GPIOを追加したな。

image

今回のInterface誌に載っていた手順を振り返ると、こうだった。

  • Vivadoで新規プロジェクトを作る
  • AXI GPIOを追加する(Zyboのテンプレートを使ったので、ボード上のLEDにつながっていた)
  • GPIOのブロックを変更して、4bitを7bitにする
  • XDCファイルを変更して、ボード上のLEDからV12などに変更する

元々はボード上のLEDを制御するGPIOだったのだ。
だから、V12が0x41200000に割り振られているのではなく、AXI GPIOでアクセスする先頭が0x41200000で、AXI GPIOのつなぎ先をV12に変更した、というだけのことか。


いつものマイコンだと、ピンと機能が結びついていて、どの機能を有効にするかを設定する、というやり方だった。
FPGAでは、ある程度はピンの使い道を変更できるということだな。
「今回はUARTを2本使いたいけど、そうするとSPIが使えなくなるから、UARTの代わりに空いているI2CにしてFTDIのチップ載せるか」みたいなことはせず「今回はI2C使わないからUART2本とSPIに割り当てよう」ということができるのだ。


というわけで、Pmod JE --- AXI GPIO、というつながりで考えればよさそうだ。


では、Pmod JEのV12がAXI GPIOにつながっているとしよう。
次は、AXI GPIOがARMのGPIOにつながっていることを確認したい。

AXIバスだから、このルートだろう。

image

AXIバスはARMのAMBAバスにつながっているようだ。
AMBA Interconnect、というらしい。

image

インターコネクトは、Zynqテクニカルマニュアルの5章だ。
PSから書込みたいので、M_AXI_GPxになるのかな?

image

「Zynq-7000 All Programmable SoC Data Sheet」の最後の方にメモリマップがあった。
http://www.xilinx.com/support/documentation/data_sheets/ds190-Zynq-7000-Overview.pdf

image

0x4000_0000がPL AXI slave port #0なので、PSがマスター=M_AXI_GP0という認識と一致した。


「5.6.1章 AXI信号」に表があって、「読み出しアドレス」「書込みアドレス」などあるのだが、アドレスっぽい値が書かれていない。
変換できるのかもしれんが、ちょっと私には無理だな。。。

0x4000_0000 + 0x0120_0000、という計算だと思う。
この0x0120_0000というオフセットの計算方法が知りたいのだ。
デバイスツリーでは、0x4120_0000, 0x4121_0000, 0x4122_0000の3つがあるので、何かあると思うのだが・・・。


ZYNQのPS/PL通信をやってみた(4) GPIOテストコードを書く: なひたふJTAG日記

最初のステップでXPSで生成したAXI_GPIOを操作したいけどアドレスがどこにあるか・・・とかそういうことを調べる必要はありません。それらはxparameters.hをインクルードすることで解決されます。

なんですってー!

PetaLinuxのディレクトリ内をfindした。

$ find ./ -name xparameters.h
./tools/hsm/data/embeddedsw/ThirdParty/sw_services/openamp_v1_1/src/open-amp/obsolete/system/generic/machine/zynqmp_r5/xil_standalone_lib/xparameters.h
./tools/hsm/data/embeddedsw/XilinxProcessorIPLib/drivers/common_v1_00_a/src/xparameters.h

ファイルはあったのだが、4年も経過したからか、該当するマクロ名はなかった。
XPSじゃないしね。


しかし、ネットで検索していると、xparameters.hを使っている人が多い。
そして、XPAR_LED_xxxみたいなものもあるので、これは自動生成する類のものと思われる。
GPIOをソフトウェアから制御する | 特殊電子回路


Vivadoでプロジェクトを立ち上げ、Launch SDKして、Newで"Application Project"を選び、Hello Worldを選んだ。
そうすると、なにやらbspというプロジェクトもできている。
その中を見ていくと大量のincludeファイルがあり、xparameters.hもあった。

image

あー、こうやってアドレスがわかるのね。。。


あまり納得できたわけではないのだが、今回はこれでもいい気がしてきたので、これで話を進めよう。

2017/08/04

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (14)

Zybo用にビルドしたPetaLinux v2017.2で、Digilent社のチュートリアルを動かしたいというシリーズ。

・・・なのだが、手始めにInterface誌2016年4月号に載っていたLEDサンプルを動かしている。
そういえば5月号はどんな内容なのだろう、と読んでみたら、私がLinux上で0~9に光らせるようにした処理をFPGA上でやる内容だった。

そこに行く前に、まず今のドライバがどういう作りになっているのかを確認し、Digilentのチュートリアルを動かして、とにかくこのシリーズを終わらせてしまおう。
とはいえ、まだまだかかりそうだな。。。


ドライバのソースファイルはこちら(Gist)。
original: http://www.cqpub.co.jp/interface/download/2016/4/IF1604Z.zip

ZIPとなってるが、元ファイルがZIP提供だったのでそういうタイトルを付けているだけで、リンク先はGistだから安心して欲しい。

ドライバの基本的な部分は、たぶんどこも同じだろうから省略しよう。
FPGAっぽいところ、今回で言えばGPIOアクセスに関係するところだけ見ていく。


そうなると、見るのはまずopen()から。
何かやっていそうなのは、ioremap()とkmalloc()くらいか。

bitは、minorの下位5bit分。
名前からして、デバイスファイルのMAJOR, MINORのminorだろう。
それが、bit = [16, 23] = [0x10, 0x17]の範囲はエラーなんだと。
確かに、mknodしたときは24にしていた。

minorのb4をmodeに割り当てていて、0だったらREAD、1だったらWRITEにしている。
24=0x18だから、WRITEだ。

cookieに使うgpio_table[bit >> 3]は、0x18(0) --> 0x0c(1) --> 0x06(2) --> 0x03(3)、となる。
gpio_table[3]は、

MAP_BASE_ADDR + LED_PIO_BASE + LED_PIO_DATA_OFFSET
  = 0x41200000 + 0x10000 + 0x0

だ。

アドレスが出てきたので、Zynqのリファレンスマニュアルを見ていこう。

image

左側のPLは「CPUおよびACP」、右側のPLは「その他のバスマスター」。

ここからたどっていけばわかるだろうと思ったのだが・・・さっぱりわからん!
GPIOのピンとアドレスがマッピングされているだけではないのか?

Zynqだからなのか、Cortex-Aだからか、いきなりリファレンスマニュアルを読むのは早すぎたようだ。。。

2017/08/02

[xfce]thunarでのパスコピー

Linuxの環境として、Xubuntu 16.04を使っている。
AndroidのビルドがUbuntuで説明されていたのでUbuntuを使いだし、でもUnityになって使い慣れず探していたら、見つかったのがXubuntuだった、という流れだ。
Unityは、メニューが画面上部固定なので、いちいちマウスカーソルを動かすのが面倒でね・・・。
廃止になるらしいから、次は試してみるかも。


Xubuntuは、ウィンドウシステムとしてXfceというのを使っている。
読めないけど、ネズミの絵が出てきたり、テキストエディタがMousepadだったりするので、似た発音なのかもしれない。
XfceのAboutを見ると「collection of programs」となっているので、ウィンドウシステム(xfwm4)を含んだ一式らしい。

さて、よく使うことになるファイルマネージャーだが、デフォルトではthunarというものになっている。

image

これの、パスをコピーする方法が分かっていなかったのだ。
ファイルを右クリックしてプロパティを表示させ、そこに載っているパスをコピーしていたのだけど、さすがにめんどくさいし、方法があるはずだ、ということで検索した。


[SOLVED] Thunar: what is hot key to display path (e.g. for copy)
Ctrl+Lで移動用ダイアログを表示させると現在のパスが出ているから、それでいんじゃないの、ということのようだ。
まあ、これはこれでよいか。


しかし、ファイル名を含んだパスだと、このあとでファイル名だけコピーせんといかんから面倒だな。。。
と、何気なくファイルコピーの要領で、ファイルを選択してCtrl+CしてMousepadにCtrl+Vすると、フルパスが入っているではないか!
空のディレクトリだと使えない技なのだが、それだったら1つ上に上がって選択すればよいか。

あとは、メニュー「View > Location Selector」で"Toolbar Style"にしてもよいかも。
これだと、パンくずリストではなく、昔のExplorerのようにテキストでコピーできる。
昔はレジストリの編集をしてまでもテキストボックスにしていたのだが、最近は「パンくずリストもありやん」と思うようになった。
まあ、あやつはクリックすると切り替わってくれるからな。


最近はXilinxのPetaLinuxを扱うこともあって、Linuxもよく使っているから、もうちょっと使い慣れないともったいない。
歳を取ると、使い慣れる時間がもったいない気もするのだが、まあ気長にやるさ。

2017/07/30

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (13)

前回(12)で/devにファイルを作ってくれるようになったが、rmmodの方を何もしていないことに気付いた。

本を真似して追加。

device_destroy(char_class, char_dev);
class_destroy(char_dev);


が、rmmodすると、エラーというか、派手に失敗した。

# rmmod zybo_gpio
Unable to handle kernel paging request at virtual address 0f400020
pgd = de690000
[0f400020] *pgd=00000000
Internal error: Oops - BUG: 5 [#1] PREEMPT SMP ARM
Modules linked in: zybo_gpio(O-) uio_pdrv_genirq
CPU: 1 PID: 1062 Comm: rmmod Tainted: G           O    4.9.0-xilinx-v2017.2 #1
Hardware name: Xilinx Zynq Platform
task: de4a4140 task.stack: de78c000
PC is at class_unregister+0x8/0x4c
LR is at char_exit_module+0x20/0x54 [zybo_gpio]
pc : []    lr : []    psr: 000e0013
sp : de78df38  ip : dd61cb6c  fp : 00000000
r10: 00000000  r9 : de78c000  r8 : c0106e24
r7 : 00000081  r6 : be83db60  r5 : 000000f4  r4 : 0f400018
r3 : 0f400018  r2 : 0000003b  r1 : c7c1fb00  r0 : 0f400018
Flags: nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
Control: 18c5387d  Table: 1e69004a  DAC: 00000051
Process rmmod (pid: 1062, stack limit = 0xde78c210)
Stack: (0xde78df38 to 0xde78e000)
df20:                                                       bf008b40 000000f4
df40: be83db60 bf008570 bf008980 00000880 be83db60 c0177650 dd735900 6f62797a
df60: 6970675f b6f3006f 00000001 de4a4140 00000000 c0a33838 de4a4140 00000000
df80: c0a33838 0000005b de4a4140 c0131bdc de78c000 00106e24 0002165c 6f62797a
dfa0: 6970675f c0106c60 0002165c 6f62797a be83db60 00000880 000ba9b0 be83de18
dfc0: 0002165c 6f62797a 6970675f 00000081 be83df0e 00000002 000b87b8 00000000
dfe0: be83db58 be83db48 000214b4 b6e17a60 600e0010 be83db60 f4f71bdc 6efff6d7
[] (class_unregister) from [] (char_exit_module+0x20/0x54 [zybo_gpio])
[] (char_exit_module [zybo_gpio]) from [] (SyS_delete_module+0x164/0x1d4)
[] (SyS_delete_module) from [] (ret_fast_syscall+0x0/0x3c)
Code: e8bd4010 eaf8ae6e e92d4070 e1a04000 (e5903008)
---[ end trace 7dde3b5d13b2d080 ]---
Segmentation fault

classの登録・削除をコメントアウトするとrmmodしても問題ないので、追加した部分に問題があることになる。


PCがclass_unregisterになっているから、class_destroy()だろうか?
いや、device_destroy()したあと、先にclass_unregister()してやらないといけないみたいだ。。。が、それでも同じだ。


insmodしたときに、out-of-treeとか出てるので、それだろうか。。。
わからんが、気になるので調べよう。

treeは、デバイスツリーかと思っていたのだが、kernelのソースツリーなのか。
https://www.kernel.org/doc/Documentation/kbuild/modules.txt

確かにこのドライバはkernelのソースツリーには入っていない。
では、別に問題ないのかな?


じゃあ、さっぱりわからんな。
Linuxのドライバのサンプルを探すところからやらねば。


2017/07/31 0:02追記

あ、class_destroy()の引数を間違えているではないか。。。

誤:class_destroy(char_dev);

正:class_destroy(char_class);

そうよね、classの削除なんだから、classを引数に取るよね。。。

gistを修正した。
まあ、いつもに比べると傷は浅いな(失敗慣れしすぎ)。

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (12)

前回(11)のminorを32から24に書き換えるというのが変だということに気付いた。
32で動いていたのだから、そこは書き換えたらいかんだろう。

よくわからんが、class登録するときだけ24にして、他は32のままに変更した。
そうすると、/devにも作成されたし、echoすると成功した。

GISTに置いておこう。
https://gist.github.com/hirokuma/1bda2e783813412c4df16b8027f5480c


まだ、32だの24だのが何なのか理解していないので、次回からはそこを調べていこう。
Linux/Zynqのつながりを見ていくことになるはずだ。


あとは、おまけだ。


image.ubの効率的な作り方を知っておきたい。

全体をビルドするときは petalinux-build だけでやっているが、けっこう時間がかかる。
今回だと、koファイルだけビルドして、image.ubの元になる場所にコピーして、image.ubを作り直す、というだけでよいはずだ。
事前のチェックとか、そういうのはすっ飛ばせないだろうか。


まず、--helpを見る。
使えそうなのは、この辺りか。

Deploy kernel forcefully:
   $ petalinux-build -c kernel -x deploy -f

Build kernel and update the bootable images:
   $ petalinux-build -c kernel
   $ petalinux-build -x package

Build rootfs only:
   $ petalinux-build -c rootfs

Build myapp of rootfs only:
   $ petalinux-build -c rootfs/myapp

以前ダメだったスラッシュでの方法も書かれている。
が、これはmyappなので、moduleだと使えないんじゃなかろうか?
試しにgpio-demoでやってみたが、やっぱりエラーだ。


PetaLinuxのユーザーズガイドを見る。
v2017.2はUG1144(pdf)だが、内容はv2017.1と同じらしい。
コマンドラインリファレンスUG1157(pdf)もある。
ネットから探しているけど、DocNavを使うのがよいだろうね。

気になっていたこのコマンド。

$ petalinux-build -x package

これは、今のdeployエリアに入っているものからFIT imageを作るものらしい。
だから、koファイルを作って、deployエリアにコピーさえすれば、最後に -x packageでimage.ubができるはず。
rootfs/myappではなく、myappを直接指定すればよいのかな?

$ petalinux-build -c myapp
$ petalinux-build -x package

やってみた。

$ petalinux-build -c led8drv
[INFO] building led8drv
[INFO] sourcing bitbake
INFO: bitbake led8drv
Loading cache: 100% |############################################| Time: 0:00:00
Loaded 3236 entries from dependency cache.
Parsing recipes: 100% |##########################################| Time: 0:00:02
Parsing of 2447 .bb files complete (2415 cached, 32 parsed). 3237 targets, 224 skipped, 0 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies
Initialising tasks: 100% |#######################################| Time: 0:00:06
Checking sstate mirror object availability: 100% |###############| Time: 0:00:13
NOTE: Executing SetScene Tasks
NOTE: Executing RunQueue Tasks
NOTE: Tasks Summary: Attempted 2430 tasks of which 2389 didn't need to be rerun and all succeeded.
INFO: Copying Images from deploy to images
[INFO] successfully built led8drv

lsでimage/linuxのタイムスタンプを見ると、rootfs.cpioやvmlinuxは更新されているが、image.ubは同じだ。

$ petalinux-build -x package
[INFO] building project
[INFO] sourcing bitbake
INFO: generating FIT Image
INFO: bitbake petalinux-user-image -R /home/xxx/build/conf/fit-image.conf
Loading cache: 100% |############################################| Time: 0:00:00
Loaded 3236 entries from dependency cache.
Parsing recipes: 100% |##########################################| Time: 0:00:02
Parsing of 2447 .bb files complete (2415 cached, 32 parsed). 3237 targets, 224 skipped, 0 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies
Initialising tasks: 100% |#######################################| Time: 0:00:05
Checking sstate mirror object availability: 100% |###############| Time: 0:00:11
NOTE: Executing SetScene Tasks
NOTE: Executing RunQueue Tasks
NOTE: Tasks Summary: Attempted 2431 tasks of which 2402 didn't need to be rerun and all succeeded.
INFO: Copying Images from deploy to images
[INFO] successfully built project

こっちは、image.ubのタイムスタンプが更新された。


しかし、それぞれ時間かかるのよねぇ。

$ time petalinux-build -c led8drv
real	1m23.720s
user	1m10.616s
sys	0m11.788s

$ time petalinux-build -x package
real	1m20.351s
user	1m7.700s
sys	0m10.048s

いっそのこと、petalinux-buildでやった方が早いんじゃないだろうか?

$ time petalinux-build
real	2m34.151s
user	2m10.356s
sys	0m19.984s

微妙やね。。。
コマンドを2回打ち込まなくてよい分、この方が楽かもしれん。

2017/07/29

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (11)

動かんシリーズの1~10で、PetaLinux v2017.2を載せたZyboのJEコネクタに接続した7セグLEDを制御できるようになった。

PetaLinuxがよいのか、というのは難しいところだ。
できれば、Ubuntuみたいにセキュリティアップデートを動的に行いやすいディストリビューションの方がよいのかもしれない。
メーカーが、売った人を追跡できるような規模であれば、営業さんにアップデートしてもらうという作戦もあるのかもしれんが、そうもいかんだろうしねぇ。
みんなどうしてるんだろう?


さて、まずはデバイスファイルから解決しよう。

以前、NXPのOM5578をRaspberry Piで動かそうとしたときに、ドライバのエラーが出て/devにファイルが作られないということがあった。
だから、自分でmknodしたり、あらかじめrootfsに仕込んだりせず、ドライバが自分でデイバスファイルを作ることができるのだと思う。


あー、udevというものがあったな・・・。
PetaLinuxでもudevを使っているのだろうか?

Starting udev
udevd[725]: starting version 3.2

あるのね。

私が持っている『Linuxデバイスドライバプログラミング』では、ドライバのクラス登録と、/sys/class配下にドライバ情報を作る作業を行うらしい。


もしかしたら、テンプレートで作ったソースファイルだとやってくれているかもしれない、と思ってディレクトリを見ていると、<project_name>/project-spec/meta-user/recipes-apps/gpio-demoというフォルダがあることに気付いた。
こんなアプリ追加してないんですけど。。。

ネットで検索すると、echoで書込むことによってLEDが光るらしい。
えんべでっどログ: ZYNQのMIO GPIOをLinuxから使う

# echo 913 > /sys/class/gpio/export
# echo out > gpio913/direction
# echo 1 > gpio913/value

お、MIO7のLED(LD4)が点灯した。
0を書込むと消灯する。

デバイスファイルを使わずにアクセスすることもできる、ということか。
そういえば、Raspberry Piも同じようなものがあったな。


このドライバは、./build/tmp/work-shared/plnx_arm/kernel-source/drivers/gpio/gpio-zynq.cのようだ。

本によると、class_create()やclass_device_create()を使うようなのだが・・・このソースには使われていなかった。
もう9年くらい前の本だから、時代が変わったのだろうか?
あるいは、kernelの組込みドライバだから、別のしくみがあるのだろうか。
なんとなく、後者である気がするのだが、深入りはやめておこう。


ただ、デバイスツリーも気になっているのだ。
あれは、デバイスの情報を取ってくることができないので、代わりに別バイナリにしたとか、そんな話だったと思う。
Raspberry Piで見たとき、デバイスツリーの情報からmknodしている箇所があったような気がするのだが、他のと記憶が混ざっている気もする。
この本では、まだデバイスツリーが登場する前なので、関連があるともないともわからない。
うーむ。


まあ、本の通りやってみよう。

やってみたのだが、class_device_create()が未定義と言われる。
includeが足りないのかと思ったら、廃止になったのか・・・。
driver - Linux function class_device_create changed to? - Stack Overflow

device_create()になったらしいが、なかなかつらいな。
サイトにはサンプルも更新されているようなので、そちらを見た方が良いのかも。
SBクリエイティブ:Linuxデバイスドライバプログラミング


とりあえずdevice_create()にするとビルドできた。
insmodすると、/devにファイルができてる。
おお!

・・・しかし、リダイレクトで書込むとエラーになった。

-sh: /dev/zybo_gpio32: No such device or address

lsで見ると、majorは244でいいんだけど、前回mknodしたときのminorは24だったのだ。

# ls -l /dev/zybo_gpio32
crw-------    1 root     root      244,  32 Jul 29 08:58 /dev/zybo_gpio32

まあ、これは元のソースが32になっていたから、仕方ないのかな?

24に変更して、ビルドし直す。
insmodして、echoして・・・ダメだ、同じエラーだ。

# ls -l /dev/zybo_gpio24
crw-------    1 root     root      244,  24 Jul 29 09:09 /dev/zybo_gpio24

/sys/class/zybo_gpio/zybo_gpio24はできているんだけどねぇ。

# cat /sys/class/zybo_gpio/zybo_gpio24/uevent
MAJOR=244
MINOR=24
DEVNAME=zybo_gpio24

続きは、また明日だ。

[zybo]PetaLinux v2017.2でHDLを書かずにLED制御の準備をする (2017/7月)

今月のこれまでの成果として、Zybo + PetaLinux v2017.2で、HDLを書かずにLED制御の準備をするまでの手順を書き残そう。
「LED制御の準備」というのは、ドライバを作る手前まで、という状態に持っていくことを指している。
まだチュートリアルが動かせないシリーズがあるので、DeviceTreeなども解決してから続きを書こう。


ツールは、こう。

  • Vivado v2017.2 (Windows10)
  • XSDK v2017.2 (Windows10)
  • PetaLinux v2017.2 (Xubuntu 16.04 on VirtualBox)


HDFファイル作成

まず、Vivadoでの作業を行う。

  1. Vivadoを起動
  2. Projectを作成する
    1. Boardは"Zybo"を選択
  3. "Create Block Design"をクリック
    1. "+"アイコンをクリックして、Zynqを追加
    2. 上の方にリンク"Run Block Automation"が出てくるので、クリックして、チェックされているのを確認して、OK
    3. "+"アイコンをクリックして、AXI GPIOを追加
    4. 上の方にリンク"Run Connection Automation"が出てくるので、クリック
      1. 一番上のツリーにチェックする
      2. axi_gpio_0>GPIOの中から"leds_4bits"を選択して、OK
    5. LinuxからEthernetを使いたい場合は、ZYNQをダブルクリック
      1. 左のPeripheral I/O Pinsをクリック
      2. Searchに"Ethernet"と打つ
      3. Ethernet0>MDIOにチェックが入っているので、右にスクロールさせて、MDIOをクリックしてOK
    6. Save
  4. 左側のツリーでSourcesタブを選択し、Design Sourcesの下にある項目(たぶんdesign_1(design_1.bd))を右クリック
    1. Create HDL Wrapper...を選択
    2. ダイアログが出てくるので、auto-updateの方になっているのを確認して、OK
    3. Critical Messagesダイアログが出てくるが、気にせずOK
  5. "Generate Bitstream"をクリック
    1. 終わるまで待つ
    2. 終わったらダイアログが出てくるので、Cancelを選択してOK
  6. メニューから、"File > Export > Export Hardware..."を選択
    1. Include bitstreamにチェックして、OK
  7. メニューから、"File > Launch SDK"を選択
    1. 立ち上がったら、自動的に関連するファイルを作ってくれるので、終了させる
  8. Vivadoも終了させる



PetaLinux image作成

  1. PetaLinuxの設定ファイルを読み込む
    $ source settings.sh
  2. プロジェクトを作るフォルダに移動(お好きな場所へ)
  3. 空のプロジェクトを作る。今回は"gpioled"という名前にする。
    $ petalinux-create -t project -n gpioled --template zynq
  4. できたディレクトリ(今回はgpioled)に移動する
    $ cd gpioled
  5. さきほど作ったVivadoプロジェクトの中から拡張子がsdkのフォルダ内にある"design_1_wrapper_hw_platform_0"というような名前のフォルダをまるごとgpioledの中にコピーする
  6. 読込んで設定
    $ petalinux-config --get-hw-description=./design_1_wrapper_hw_platform_0
  7. 特に変更せず終わらせると、そこそこ時間かかる処理が始まる。
  8. 忘れていたが、LEDのドライバを準備する。今回はleddrvという名前にする。
    $ petalinux-create -t modules -n leddrv --enable
  9. "gpioled/project-spec/meta-user/recipes-modules/leddrv"辺りにファイルができているので、うまいこと編集するとよいのだが、まずはテンプレートのままにしておく。
  10. ビルドする。こちらは時間がかかる。
    $ petalinux-build
  11. BOOT.BINを作る
    $ petalinux-package --boot --fsbl images/linux/zynq_fsbl.elf --fpga images/linux/design_1_wrapper.bit --u-boot --force


これで、BOOT.BINとimage.ubができたので、SDカードにコピーしてZyboを起動。
ログインして、ドライバを確認。

# ls /lib/modules/4.9.0-xilinx-v2017.2/extra/
leddrv.ko

read/writeを用意していないが、insmodくらいならできるだろう。

# insmod /lib/modules/4.9.0-xilinx-v2017.2/extra/leddrv.ko
leddrv: loading out-of-tree module taints kernel.
<1>Hello module world.
<1>Module parameters were (0xdeadbeef) and "default"

open/closeもできそうだが、デバイスファイルがないのでできない気がする。


ひとまず、これで、デバイスファイルとドライバを作ればLED制御できそうな状態になったと思う。
以降の調査は、これからやっていこう。

2017/07/27

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (10)

前回までで、ようやくここまで来た。

  • Vivado v2017.2でGPIOを7本有効にする
  • XSDK v2017.2で何かする(この工程はいるのか?)
  • hdfファイル一式をPetaLinux v2017.2に持っていって、user moduleを追加してビルドし、mknod, insmodして動かす


user moduleがビルドできずに悩んでいたのは、petalinuxで追加したmoduleのテンプレートにあったREADMEを読んだからだということに気付いた。

To compile and install your module to the target file system copy on the host,
simply run the
     "petlainux-build -c kernel" to build kernel first, and then run
     "petalinux-build -c rootfs/led8drv" to build the module
command.

-cで、rootfsとled8drvをそれぞれやりなさい、ということかもしれんが、わからんよ。。。


あとは、ドライバをいじるところをやれば、多少は理解できるんじゃなかろうか。


Linuxのドライバは、

  • open
  • close
  • read
  • write
  • ioctl

でできているはずだ。
ioctl()って逃げよねぇ、と思いつつも、他に手段が思いつかないので、便利に使っている。


Interface誌のダウンロードから持ってきたファイルを見ておこう。
closeではなくreleaseという名前になっているし、ioctlはないが、基本的にはこういう構成になるだろう。
プレフィクスが"char_"なのは、キャラクタ型ドライバだからか。
確か、ブロック型とキャラクタ型があって、ASCII社の本で簡単な区別方法を読んだ気がするが、探し出せなかった。
ブロック転送しないものはすべてキャラクタ型だ、とか、そんなだったような。


私だとioctl()でやってしまいそうだけど、ここはchar_write()で書込処理を行っている。
利点は、Linuxコマンドと組み合わせやすい、というところか。
ioctl()だと、ソース書かないと動かせない気がする。

今は、書き込んだデータがASCIIコードでそのまま吐き出されているのだが、条件は簡単で、

    • 1byte目が'0'
    • 2byte目が'x'
    • データ数は3より大きい

だった場合、3byte目をiowrite32()で書込んでいるだけのようだ。


では、簡単に書き換えて、ビルドし直してみよう。
やはり、echoした数字をそのまま表示させたい。

なんとなくカルノ図を描いたりする気がしたのだが、Linuxから見ると数字を変換してポートに書込むだけなので、変換テーブルしかいらなかった。

image

アノードが共通なやつを使っているから、0で点灯するのだ。
大ざっぱだが、こういう感じの修正になった。

    unsigned int val;
    const unsigned int VAL[] = {
        0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10
    };

    if (('0' <= k_buf[2]) && (k_buf[2] <= '9')) {
        printk("WRITE %02x\n", (unsigned char)VAL[k_buf[2] - '0']);
        iowrite32( VAL[k_buf[2] - '0'], cookie);
    }


ドライバの差し替えは、これでよいのかな?

$ petalinux-build -c led8drv
$ petalinux-build -x package

やるのは、ドライバのコンパイル・リンクと、rootfsへのコピーおよびUboot形式への変更だけなんだけど、あれこれやってるから時間がかかるな。。。

# mknod -m 666 /dev/zybo_led c 244 24
# insmod /lib/modules/4.9.0-xilinx-v2017.2/extra/zybo_gpio.ko
# echo 0x1 > /dev/zybo_led

うん、期待通りに点灯した。


mknodを毎回やるのはめんどうなので、何とかしたいところだ。
Raspberry Piでは、Device Treeに書いておけばudevか何かが自動的にmknodしていたように思うが、PetaLinuxはどうやるんだろう?

そういうのは、次回だ。

2017/07/25

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (9)

前回(8)の続き。

ドライバのビルドはできたのだけど、insmodしても/dev/zybo_ledみたいなものが出てこない・・・。


昼ご飯を食べ終わって、急に思いついた。

あー、mknodしてない!

は、恥ずかしすぎる・・・。


# mknod -m 666 /dev/zybo_led c 244 24
# insmod /lib/modules/4.9.0-xilinx-v2017.2/extra/zybo_gpio.ko

Interface誌ではmknodするのが245になっていたが、insmodしたときが244だったので、そっちにあわせた。

echoすると、LEDが変化した。

# echo 0x1 > /dev/zybo_led
----- This is the Open Function -----
Node NAME: Ext_GPIO:
MAJOR Number = 244, MINOR Number = 24
Open device successfully: Ext_GPIO:


---- This is the WRITE function -----

k_buf is 0x1
  pos = 4
----- This is the Close Function -----
Closing device: Ext_GPIO:

image

書込んだ値にあわせて7セグも数字のように点灯するのかと思ったが、どうもASCIIコード('1'だと0x31)を出力させているらしい。

Aがb7、Bがb6、・・・ということらしい。
1だとビットは3つしかないのに、なんで4本光ってるんだ?
HI点灯とLO点灯の違いだろうか。


まあいい、このレベルまでは持ってくることができたから、次からはドライバのソースを見ていこう。

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (8)

前回(7)の続き。
LED用のドライバを動かすためにmoduleを追加して、ようやくビルドできたところまで。
全部動いてからまとめて書くとあっさりしているのだろうけど、日記だから許しておくれ。


ビルドのテストとしてmymoduleという名前で追加したのだけど、もう不要になったから、先に削除しておこう。
モジュールのフォルダを削除しただけではコンパイルエラーになり、project-spec/meta-user/recipes-core/petalinux-image.bbappendに追加されていた名前を削除してもコンパイルエラーになった。
依存関係が残っているというエラーっぽいのだが。。。
project-spec/meta-plnx-generated/recipes-core/images/petalinux-user-image.bbにも書かれていたので、そこからも行削除するとビルドできるようになった。


PetaLinuxのリファレンスに書いてあるとおりにビルドしていたのだが、どれをやってうまくいったのかわからん。
エラーにはならなかったのだが、探す場所と探す名前を間違えていてね。。。
Interface誌のページからダウンロードしたCファイルをそのまま使うと、こうなった。

/lib/modules/4.9.0-xilinx-v2017.2/extra/zybo_gpio.ko

lsmodしても出てこないから、自動では読込まないのだろう。

# insmod /lib/modules/4.9.0-xilinx-v2017.2/extra/zybo_gpio.ko
zybo_gpio: loading out-of-tree module taints kernel.
Device registered successfully, Major No. = 244

out-of-treeと出てるけど、よいのかな?
successになっているけど、/dev/zybo_ledなんてデバイスファイルは見つからない。。。
別の名前で増えたわけでもない。


うーん、残念だが、また次回だ。

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (7)

前回(6)の続き。

ドライバを作って追加しようとしたが、ビルドに失敗したのだった。
こういうときは、PetaLinuxのリファレンスマニュアルを読もう。

ちゃんと、「Adding Custom Modules」「Building User Modules」という項目がある。
あ・・・そういうことか。。。



$ petalinux-build -c rootfs/led8drv

  ↓


$ petalinux-build -c led8drv


なんで私はrootfs/なんてのを付けようと思ったのだろうね。。。
あまりにガックリしたので、今日はここまで。

2017/07/24

[btc]ブロックのversion bits

Bitcoinで、UASFだのなんだのと騒がしかった(これを書いているのは2017/07/24)。
あまり関係ないので放置していたが、まったくわからないのも悔しいので、少しだけ調べることにした。


ビットコインのBIP91シグナル、ロックインへ 分岐か収束か | ビットコインの最新情報 BTCN|ビットコインニュース

やはりよくわからんが、bit1やbit4という数字が出てくる。
BIP91を見ると、bitが4っぽいことはわかった。

consensus.vDeployments[Consensus::DEPLOYMENT_SEGSIGNAL].bit = 4;

しかし、どのデータを見るのか?
BIP9がその大元らしいが、最初に「'version' field in Bitcoin block」と書いているので、ブロックのversionフィールドなのだろう。

Bitcoinプロトコルの"block"に構成が書かれている。
txと同じで、先頭の符号付きLittle Endianの4byteがversionになっている。


では、どのbitがどういう意味なのかという仕様がいるはずだ。

BIP9には以下のリンクが貼られていた。
bips/assignments.mediawiki at master · bitcoin/bips

見ると、bit0とbit1しかない。
bit1は、segwitだ。BIP148と思われる。


じゃあ、bit4ってのはなんなんだってことになるけど、8月1日にbit4が立ったversionのblockじゃないとノードがはじくようにしようとしていた、ということだろうか(BIP読んでない...)。
bit2と3が空いているが、実は私が知らないだけで、そういう判定のような意味で使おうとして、消え去ったのか。

最初の記事にも書いてあるが、じゃあ、bit4だけ立てて、bit1は立てなかったら、segwitを有効にする閾値を80%にすること自体は賛成するけど、segwitには賛成しないよ、ということか。


結局「なんだかよくわからんね」で終わってしまった。
またどこかで勉強しよう。


そもそも、versionをそういう目的で使うのって、曖昧すぎじゃなかろうか。
それをわかってやってるのかもしれないけど、それにしてもねぇ。。。


2017/07/24 12:38追加

BIP91がアクティベート、SegWit支持率は97.9%の高止まり | ビットコインの最新情報 BTCN|ビットコインニュース
BIP141シグナルと書いてあるので読んでいったら、そっちにもbit1と書かれていた。https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#deployment


あれ、じゃあBIP148ってなんだっけ?ということになった。
P2SHみたいに、と書いているから、これがUASFというやつなのか(読んでなさ過ぎ)。

BIP091   : bit4
BIP141-  : bit1

じゃあ、bit4もbit1も立てたノードが多数あるのか。
"SegWit支持率"と書いているから、bit1だけで97.9%あるということなのかね。
bit4が承認されなくても達成できるけど、それがなかったらここまではこなかったのか。


Segwit support - Bitcoin Wiki
これは、DeveloperとBusiness(マイナー?)の意思表明リストらしい。
ページの一番下に更新日が書いてあって、私が見ているのは2017/07/23 09:04になっている。
見たら何か分かるかと思ったが・・・これだけだとわからんな。
グラフになっていたら、


BIP91はSegwit2Xとかいう、segwitもやる、ブロックサイズも倍にする、という話が発端だったと思う。
先にsegwitに対応して、3ヶ月後くらいにブロックサイズを倍にするんだっけ。
UASF・Segwit2x・Bitcoin Unlimited:闘いの果てに | ビットコインの最新情報 BTCN|ビットコインニュース
でも、そういうのはBIP91には書かれてなさそうだから、そっちはそっちでまたあるのかね。


やっぱりよくわからんが、理解できるように追いかけなかったのは正解だった。。
こんだけ情報が早いと、ちょっとついて行けんねぇ。

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (6)

メモ。

前回、petalinux-create -t modulesでドライバのテンプレートを追加したが、ビルド時にエラーが出た。



AR# 68502: 2016.4 PetaLinux: Creating template module using underscores in naming convention causes build failures

名前にアンダーバーが入ってるとエラーになるって??
と思ったが、私は「led8drv」にしたから、入ってなかった。

ともかく、PetaLinuxというよりは、Yoctoに由来するエラーのようなので、そこら辺から探していくのがよいだろう。

2017/07/23

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (5)

動かん(4)の続き。

前回は、BOOT.BINやimage.ubを作るところまで。
今回は、ドライバを作るところだ。


Solved: How to write a petalinux device driver - Community Forums
The XDMA Framework For The DMA330 DMA Engine - drivers-sessions1-2-public.pdf

古いのかもしれないが、PDFのp.20にコマンドが書かれていた。
"petalinux-create -t modules -n <名前> --enable"で作るようだ。
このコマンドは、PetaLinuxのプロジェクト内で実行しないとエラーになる。

名前を「led8drv」にしたら、project-spec/meta-user/recipes-modules/led8drv、というところを用意してくれた。
この辺りはPDFと違うところだな。


今回はInterface誌のzybo_gpio.cをそのまま使うことにする。
Makefilとled8drv.bbに載っているファイル名を書き換えた。
あとはビルドなのだが・・・petalinux-buildすることにした。
単体でもできるのかもしれんが、petalinux-buildすればimage.ubに入ってくれるんじゃないの?

入ってくれんかった。
createで作ってくれたテンプレートの中にREADMEもあったので、読もう。


まず、rootfsのbuildがいるようだ。

$ petalinux-build -c rootfs

そうするとmenuconfig画面が出てきて、"modules"を見ると今回作ったドライバが入っていた。

image

あとは、順番に実行せんといかんのか。

$ petalinux-build -c kernel
$ petalinux-build -c rootfs/led8drv

エラーになる。

ERROR: Nothing PROVIDES 'rootfs/led8drv'

ファイルを置き換えるだけではダメなのかと思ったが、元に戻してもエラーが出る。
既にあるGPIOのドライバと重複したからかもと考えたが、それだったらこういうメッセージにはならんよなぁ。


うーん・・・。
今週はこれでおしまいだ。

[zybo]PetaLinuxでDigilentのチュートリアルが動かん (4)

動かん(3)の続き。

前回は、Vivadoのブロックに対する警告(同期リセット)を無視することにして、LEDとZyboをつないだところまでだ。
残りをやろう。
環境は、Vivado/XSDK v2017.2だ。


まず、Block Design画面で「LEDs_4Bits」のブロックをダブルクリックして、GPIO Widthを7に変更する。
今回はドットがないので7つでもよいはず。
Interface誌では8になっているので、ダメだったら考えよう。
奇数にするってのは、ちょっとドキドキしますな。


続いて、Sourceタブで「system.bdを右クリックするそうだ。
しかし、ファイルがたくさんあってわからん・・・。
検索しよう。

image

これが絞り込んだ結果らしい。
ちなみに、検索方法の設定はちょっと怪しかった(Vivado v2017.2)。
まあ、SとIだから、どっちがどっちかは大体分かるけどさ。。。

image


次はピンアサイン。
zybo_base_systemを使ったので、base.xdcというファイルになっていた。
Interface誌を見ると、こういう感じで修正するように書かれていた。

set_property PACKAGE_PIN V12 [get_ports {leds_4bits_tri_o[0]}]

V12はわかる。
これは、JEコネクタの1番ピンに紐付いているからだ。

image

では、leds_4bits_tri_o[]はどこから出てきた名前だろうか?
base.xdcに、こういう行があった。

set_property PACKAGE_PIN M14 [get_ports {leds_4bits_tri_o[0]}]

今回は、JE1,2,3,4,7,8,9なので、leds_4bits_tri_o[0~6]までに当てればよいのか?
しかし、Pmodの図はこうなっていた。

image

あ・・・私まちがえてる。。。
Pin1は右上として、Pin2はその左隣なんだ。
下をPin2だと思ってたけど、一番左にPin6と書いてあるな。
写真ではわからんと思うが、修正しておこう。

image


base.xdcを直接編集してもよいが、せっかく専用のエディタがあるので、そっちを使おう。
Run Synthesisしておくと、I/O Planning画面が使えるようだ。
しかし、Run Synthesis自体がかなり長い・・・。
PCの性能はそんなに悪くないと思うのだが、10分以上かかったんじゃなかろうか。

ともかく、I/O Planningは選択できるようになった。

image

GPIOという名前が付いた項目がいくつかあるので、led関連を探すとこうなっていた。

image

よく考えたら、LEDs_4Bitsってボード上のLEDだろうから、新たにGPIOのブロックを追加すべきだったんじゃなかろうか。
まあいいや。

JEポートの1~9番を使っているので、それぞれ割り当てる。

image


あとは、Generate Bitstreamするだけ。
これはこれで時間がかかりそうだ・・・そうでもなかった。
3分くらいかな。


Interface誌ではExportするところは書かれていないが、タイトルがそうなっているので、Exportしよう。
たぶん「Include bitstream」にチェックを入れるはず。
と思ったが、bitファイルさえできればよいのならExportしなくてよいのかも。
私のところではプロジェクト名を「led8」にしたが、led8.runs\impl_1\system_wrapper.bitができていた。
Exportしたあとに調べたのではっきり言えないが、タイムスタンプからするとGenerate Bitstreamで生成されているはず。


手順では、ExportしたあとにSDKを起動するようになっていて、SDKからBOOT.BINを生成している。
しかし、このBOOT.BINって、何者だろうか?
XSDK v2017.2だから、PetaLinux v2017.2なのだろうか。

まあいい、書いてあるとおりにやってみよう。
Launch SDKすると、プロジェクトができていた。
led8/led8.sdk/system_wrapper.hdfを読んだようなログも出ているし、間違いなかろう。
自分で作らなくてよかったんだっけ?

image


あるものは使おう。
手順ではCreate Zynq Boot ImageでBIFファイルを選ぶようになっているが、私のところにはBIFファイルが見当たらない。
「既にoutput.bifファイルがありますので」と書いてあるけど、ない場合は「Create new BIF file」でよいのだろうか。
しかし、これはこれでUDFファイルがいるようなのだ(importの場合もいるみたいだけど)。

image


どうも、zybo_base_systemにboot.bifがあるらしい。
単なるテキストファイルだ。

the_ROM_image:
{
	[bootloader].\fsbl.elf
	.\system_wrapper.bit
	.\base_demo.elf
}

同じフォルダに、ここに書いてあるELFファイルがあるので、これを使ってBOOT.BINやimage.ubを作るということか。

UDFは、ユーザー定義フィールドなのか?
以前のXSDKにはない項目のような気がする。


そもそも、Vivadoはなんとなくわかるとして、XSDKは何をするツールなのだ?


ザイリンクス ソフトウェア開発キット (XSDK)

読んでもわからん。。。
PL部は、Vivadoで、ハードウェア開発。
PS部は、XSDKで、ソフトウェア開発。
そういう見方でよいのだろうか。

だいたい、ホモジーニアスとかヘテロジーニアスとか、生物か何かの授業で聞いたような単語の意味がわからん。
ホモジーニアスが同種、ヘテロジーニアスが別種なのだろうけど、それがFPGAとどう関係するのか。
マルチプロセッサで実現したH.264ビデオ・デコーダ ――コンフィギャラブル・プロセッサのユーザ定義命令とオンチップ・バスを活用|Tech Village (テックビレッジ) / CQ出版株式会社

うーん、ARMコアが2つだからホモジーニアス?
それとも、PS部とPL部でヘテロジーニアス?

ともかく、Eclipseだし、DigilentのチュートリアルでZYBOに転送してたので、少なくともARM向けにクロスコンパイルはしてくれそうだし、Program FPGAでbitファイルを焼いてもいるのだろう。


ここからBOOT.BINを作ることができると便利そうだけど、今回は深く考えず、VirtualBox上のXubuntuでビルドしたPetaLinux v2017.2を使おう。
あれなら、hdfファイルとbitファイルがあればよかったはずだ。

led8.sdk\system_wrapper_hw_platform_0をフォルダごとXubuntuにコピーして、

$ petalinux-create -t project -n led8 --template zynq
$ cd led8
$ petalinux-config --get-hw-description=../system_wrapper_hw_platform_0
(変更せず終わらせる)
$ petalinux-build
(時間がかかる)
$ petalinux-package --boot --fsbl images/linux/zynq_fsbl.elf --fpga  images/linux/system_wrapper.bit --u-boot --force

と手順を書いたが、petalinux-build中にエラーが起きた。

| ERROR: axi_vdma_0: mm2s_introut port is not connected

Solved: AXI DMA in Vivado How should I connect mm2s_introu... - Community Forums
concatというIPを追加して、axi_vdma_0とaxi_vdma_1のmm2s_introutをそれぞれつないだ。
そしてPS7 IRQ_F2Pにつなげばよいそうだが、Zynqにそういうポートがないな。

Zynqをダブルクリックして、Interrupt Portタブを検索すると出てきたのだが、チェックができない。。。

image

AR# 58942: Vivado IP インテグレーター、Zynq-7000 - PL 割り込みを Zynq-7000 PS に接続する方法
あ、先にFabric Interruptsにチェックして、その後でIRQ_F2Pにチェックするのか。
zybo_base_systemを使わない方が楽だったな。。

そこだけ修正すると、imageの生成までできた。


さて、PetaLinuxを起動するだけであればBOOT.BINとimage.ubをSDカードにコピーするだけでよかったのだが、今回はどうするとよいのか。

などというところも、Interface誌に書いてある。
Linuxのドライバを経由して、作ったものをたたくようだ。
まあ、Linuxだからドライバを作らないとダメよね。
FreeRTOSにも対応しているみたいだから、そっちだともう少し触りやすいかもしれないけど、Zynq使っていてFreeRTOSにするというのももったいない気がする。
もったいないというか、せっかくマイコンの性能をそこまで気にせずにいけるし、リソースもそこそこ広大なのだから、ドライバを作らないかんという面倒があったとしても、そのルールに載った方が楽だと思うのだ。


まずは、ドライバなどをインストールせず、petalinux-buildしたものをそのままSDカードにコピーして立ち上げた。
うん、7セグがフル点灯している。
つまり「8」が見えている。

image

写真に詳しくないのだが、まだ明るい時間なのに、撮影したらこうなってしまった。
ともかく、カソード側は全部GNDに落ちているということか。

そして、それ以上に大切なのは、GPIOの設定が既に有効になっているということだ。
いや、どうかな・・・。
LED側は電源を突っ込んでるだけなので、GPIOでGNDにつながってさえいれば点灯する。
もしかしたら、Zになっているだけで点灯してしまう可能性がなくもないのではなかろうか(どうだろう?)。


ともあれ、Linuxのドライバがいる。
Interface誌のダウンロードコーナーにあるので、それを使う。
Digilent社もドライバを出しているそうだし、ZynqのドライバAXIのドライバもありそうだが、まあいいや。

いま、kernelの起動ログでGPIOっぽいものを出しているのは、これくらいだ。

GPIO IRQ not connected
XGpio: /amba_pl/gpio@41200000: registered, base is 902
GPIO IRQ not connected
XGpio: /amba_pl/gpio@41210000: registered, base is 895
GPIO IRQ not connected
XGpio: /amba_pl/gpio@41220000: registered, base is 891


Cソースが1つだけなので、コンパイルすればよいのかな。

$ arm-linux-gnueabihf-gcc -o zybo_gpio.ko zybo_gpio.c
zybo_gpio.c:16:25: fatal error: linux/delay.h: No such file or directory

惜しい。
ドライバのコンパイルは、動作環境のLinuxドライバ用ディレクトリを-Cで指定し、変数Mにカレントディレクトリを、obj-mにビルド後のファイル名(.o)を指定すればよいようだが、はてさて。

長くなってきたので、今回はここまで。