2016/05/31

[android]AsyncTaskとキャンセル

私が持っているAndroidの本には載っていないのだが、今は非同期で動かすというか、ワーカースレッドみたいにして動かしやすいようにAsyncTaskなるものがあるそうだ。

 

使い方はそこまで難しくなく、ネットに出てくるサンプル通りに書けば動いた。
しばらく非同期部分を動かしたかったので無限ループにすると、通らないルートが発生するためか怒られた。
適当にif文とbreakを追加すると言われなくなったのだが、そんな対応でよいのだろうか。。。

 

無限ループも、ぐるぐる回すと忙しすぎるので、Thread.sleep()で10秒ごとに回すようにした。
さて、そのときに非同期部分をキャンセルさせたかったら、どうするとよいのだろうか?

 

最初に試したのは、フラグだった。
停止フラグを用意して、ボタンを押したらフラグを立てる。
無限ループ内では停止フラグを見るようにして、立っていたらbreakで抜ける。
まあ、動くには動くのだが、sleepしている間は待っておくしかないので、ちょっとわびしい。

どうやら、Thread.sleep()は、Thread.interrupted()を呼ぶと抜けるらしい。
シグナルみたいなものか。

 

そうしていくうちに、isCancelled()があることに気付いた。
AsyncTaskを継承するとcancel()が追加され、これを呼んでやるとisCancelled()が立つので、無限ループでもこれでbreakすればよいようだ。

cancel()を呼ぶと、onCancelled()が呼び出されるようになっている。
じゃあ、さっきのThread.interrupted()をここで呼んでやるようにしておこう。

が、そこまでしなくても、cancel(true)としてやるとThread.interrupted()が呼ばれるようになっているみたいだ。
「mayInterruptIfRunning」では、わからんかったなぁ。
"thread"はAsyncTaskのことを指しているのかと思っていたよ。。


DDMS...じゃなくて、Android Device Monitorでアプリのスレッドを見ると、AsyncTaskをnewしていくとこういう風に見えた。

image

doInBackground()を抜けても数は変わらなかったが、StatusがWaitになった。
ArrayList<>に保持していたものもclear()しているから、消えると思ったんだけどね。
まだGCのタイミングじゃないと言うことか。
あるいは、1つずつ消さないといけないのか。。。
  • ArrayList#clear()だけ
    • 残ったまま
  • さらに=nullもする
    • 残ったまま
Android Device Monitorから「Cause GC」としても残っているので、消える対象になっていないのだろうという気がする。
うーん、この辺りをどうしてよいのか思いつかないところが哀しいですな。

[esp8266]NFCIDを取得してTCP送信

ESP8266にRC-S620/Sをつなぎ、ポーリングしてNFCIDを取得し、TCPのサーバに送信するというだけのアプリを作った。

hirokuma/esp8266_rcs620s at 32464d397720708f8a45274fd52e9671eb8cbe40

 

何に使うのか?といわれると、さあ?、としか答えられないアプリだ。。。
最近どちらも動かしていなかったから、両方動かしてみました、くらいか。

TCPのサーバも、Linuxでsocketを使ってlistenしてacceptするという、教科書にあるようなものだ。
送る方がHTTP GETっぽく送って、サーバがクエリーをさばくようにすると、もうちょっとそれっぽいアプリを作ることができたのかもしれんが、まあこの辺が私の限界だ。

 

まあ、NFCIDを取得するだけだったら、このしくみは電気を食いすぎだろう。
せめてBLEか。
AndroidがあるならNFCが動くだろうから、こういうの自体いらん。
RC-S390はもっと情報を公開してくれるといいんだけどねぇ。

 

無理やり使い道を考えるとしたら、家の鍵とかか。
錠がNFC R/Wになっていて、錠とサーバがつながっている。
一瞬しか役に立たない鍵情報をサーバから送ってもらい、RC-S620/Sをカードエミュレーションさせて、情報が一致しないと開けられない、とか。。。

うん、スマホでできるね。
「無理やり」とすれば、スマホがなくてもできる、というところか。
私がスマホとか持ち歩かない人間なので、そこら辺にあるもので代用できるといいんだけどね。
「私が使うことで、それは本物になるのよ」みたいな。

2016/05/30

[ble]Linkingのプロファイル仕様

IoTの囲い込みを打ち破るドコモの隠し玉 - 日経テクノロジーオンライン

 

Linkingは仕様書が簡単にダウンロードできるようなので、ちょっとだけ眺めた。
Project Linking

利用規約やアンケートはあるが、メールアドレスの登録すら不要だった。


構成は、こう。

  • PeripheralDeviceLink Service
    • Write Message Characteristic
    • Indicate Message Characteristic

BLEのサービスは1つ、Characteristicも2つ、しかも書込みとIndication用のみ。
なかなか割り切った作りだ。

 

紛らわしいのは、「サービス」という言葉だろう。
BLEとしてのサービスは1つしかないのだが、Linkingとしてのサービスは5つある(今のところ)。
Write Messageにはフォーマットがあり、そのフォーマットに「サービスID」と「メッセージID」がヘッダとして載るようになっている。
このサービスIDとメッセージIDの組み合わせで、何をするデータなのかが決まるというやり方のようだ。

 

まあ、デバイス側としてはCharacteristicをいくつも用意しなくてよいから、メモリが少なくて済みそうな気はする。
書込みサイズも20バイトまでと書かれているから、Long Writes対応もいらなさそう(ただし、メッセージ長が大きい場合もあり、それはシーケンス番号ヘッダを追加して対応するみたい)。

nRF5xしか知らないのだが、サービスやCharacteristicを追加したり減らしたりというのは、難しいわけではないのだが面倒な作業ではある。
なので、書き込まれたデータだけで判断すればよいのだったら、そこまでフレームワークを作ってしまって、あとはその下だけ変更するようなやり方ができそうだ。

デバイス側はBluetooth Developer Studioプロジェクトを配布してくれるとよかったのだけど、まあ、そこまでやるほどでもないか、というところだ。


中身がどうのこうのという評価はしないのだけど、ドキュメントが残念な感じだ。
Excelで作られたものをPDF化しているのだろうけど、いっそのことExcelで配布された方がありがたかった。

セル内での改行を見栄えベースで行っていると、印刷したときにはみ出てしまって、見えなくなることがあるのよねぇ。

それと、ページごとの用紙サイズがまちまちで、あまり大きくない画面でPDFビューアを使うと画面外にはみ出たりしてしまってね。。。
用紙の縦と横が混在しているわけでもないけど、どうやってるんだろう?

image


対応デバイスは、ここら辺でも売られているとのこと。
Braveridge公式ストア / Linking対応製品

安い、安いねぇ。。。
遊びで自作するのはいいけど、製品にするとなるとここまで安くできないといけないのですな。

2016/05/28

[esp8266]UARTのRX_FIFOをアプリで読めばよい

前回の続き。

UARTの受信レジスタ(RX_FIFO)を読むuart_recvTaskというものがあるのだが、それが今のアプリタスクが終わらないと呼び出されないので、どうしようどうしよう。。。というところまでだった。

 

最初に記事を書いてから、頭の整理のためにシーケンス図を追加した。
そうすると、難しく考えすぎていることに気付いた。

もともと、uart_recvTaskもコンテキストとしてはアプリタスクと変わらない(割込みじゃないという意味で)。
なので、アプリタスクでuart_recvTaskがやるのと同じことをやってしまえばよい、と。
受信データはRX_FIFOに勝手にたまっているから、同期で読めるのだ。
なーんだ。

image

RC-S620/Sは基本的に相手から勝手にデータを送ってくることはないので、uart_recvTaskの動きを止めてしまっても良いのだが、このまま様子を見てみよう。

やればできるやん。

[esp8266]system_os_post()は割込みではない

RC-S620/Sの処理をESP8266に組み込もうとしている。
が、いきなり詰まった。

いま作っているRC-S620/S用のライブラリは、Linuxベースで作った。
同期でUART送信し、同期でUART受信する。
他のOSになったとしても、非同期を同期に見せかけるようにすればよいだろう、と思っていたのだ。

しかし、ESP8266のnon-OS版に付いているUARTドライバは、

  • UART受信は割込みで見る
  • 受信したデータをためるのはsystem_os_post()後

という形になっている。

image

RXFIFO_TOUTはタイムアウトのフラグらしいのだが、調べていない。
一定時間FIFOに変化がなくなったら立つのかな?
UART_RX_TOUT_THRHD_Sが24だが、単位がわからんな。

 

なので、UART受信タスクの優先度をアプリタスクよりも高くしておけばいいや、と軽く考えていた。
そして、アプリ側ではwhile()でUARTタスクがためた受信データを監視しよう、と。

 

これが動かない。。。
ログを埋め込んだのだが、アプリの受信待ち処理を入れなければUARTタスクで受信したデータがログ出力され、待ち処理を入れると出力されない。

たぶん、アプリのタスクによってUART受信のタスクが待ち状態になって、こうなっている。

image

 

つまり、これを動かしたければ、受信待ちは同期で行うのではなく、同じようにsystem_os_post()で回すようにしないといかんと言うことだろう。
Linux系のselect/pollみたいに待たせることができればよいのだが。

 

うーーーん・・・。
同期向けに作ってある処理を非同期化するのはとてもつらいぞ。
それが嫌なら、UARTの受信データをためる処理を割込みに持っていけばよいのだろうが、それはそれでつらい。。。

解決方法が思い浮かばん。

[esp8266]espconn_gethostbyname()への誤解

AndroidやったりLinuxやったり落ち着きがないが、今日はESP8266だ。
しかもNon-OS版なので、あまり使っている人がいないような気がする。
みんなArduino使うからなぁ。。。

 

さて、今回はespconn_gethostbyname()についてだ。
名前の通り、ホスト名からIPアドレスを引いてくれる関数なのだが、使っていてよくわからない動作をしていたのだ。
何かというと、引数にip_addr_tのアドレスを与えるのだけど、名前を引き終わってコールバックされたときにはそのアドレスは更新されず、コールバック関数の引数で渡されるのだ。
じゃあ、引数で与える意味がないではないか、という疑問だ。

 

これはEspressifのドキュメントではなく、Kolbanさんのドキュメントを読まないとわからなかった。
Espressifのドキュメントでは、この関数の戻り値がESPCONN_INPROGRESSだと「already connected」となっているのだが、Kolbanさんのを読むと「キャッシュで持っていないのでlookupしにいきます」という意味らしい。
まあ、LinuxもPROGRESS系の戻り値はそうだよな。。。

だから、戻り値がOKのときには即座に結果を引数に返すけど、INPROGRESSの場合はコールバックの引数で返す。
コールバックの際は関数呼び出し時の引数で渡したアドレスの方は使わない、という動きをしているようだ。
サンプルでは渡すipaddr_tをグローバル変数にしてあるけど、こういう動作ならばローカル変数でよいはずだ。


Arduino版だと、この辺りは見えなくなっているようだから楽そうだ。
それに、誰かの作ったライブラリを使えるのも魅力だから、そのうち移行したいものだ。

2016/05/27

[android]2つspinnerを使ってみる (2) - 最終回

前回の続き。
スピナーを2つ使って、大項目と小項目を選択し、ボタンを押したらメソッドを呼び出す、というだけのものを作りたい。

まあ、何かというと、テストアプリだ。
大項目と小項目に分けたテスト書を作って、それに沿って実行するアプリの枠を作っておきたい。
見栄えにはこだわらないけど、ちゃんと動くことと、変更しやすいことを目的にするのだ。

 

前回までのコミットは、たぶんこちら
スピナーのレイアウト指定が違っていたので、妙に間隔が狭くなっていたのを修正したところまで。

今回は、コマンドの実行部分まで作る。


結果として、こうした

Cだったら、2次元配列にして、添字で大項目・小項目の番号を指定して呼び出すようにするかなぁ、と思って、そのまま作ってみた。
関数ポインタはないけれども、interfaceを使えば同じようなことができるということだったので、まねした。

 

うーん。。。
目的は達成したのだけど、Javaとしてというか、コーディングとしてどうなんだろうか?
こんな1箇所にまとめず、テストごとにファイルを分けた方が良いのかもしれない。
C#みたいに、1つのclassを複数ファイルに分けられるのだったらよいのだが。

まあ、ここはメニュー用と割り切って、テストの本体は別にした方がよいかもしれん。
テスト項目だから、これが100個も200個も並ぶと訳がわからなくなりそうだ。

 

また、今はドロップダウンにしているけど、押し間違えそうだからダイアログ形式の方がよいかもしれん。
文字列をstrings.xmlに持っていくなら、name()はStringじゃなくてintでリソースIDを返すようにすべきか。

 

なんか、悩みはじめると全然終わらんですな。
ともかく、今回はおしまい。

[android]2つspinnerを使ってみる (1)

技術紹介じゃなくて、よくわかんないなりにやってみた、というコーナーだ。
「こいつ、こんなことも知らないのー」という目線で見ていただけるとありがたい。

 

やりたいのは、Windowsの部品名で言えば、コンボボックスを2つつくって、1つ目に大項目を、2つめに小項目を選べるようにして、ボタンを押したら大項目と小項目の組み合わせに応じたメソッドを呼び出す、というもの。

Androidでは「コンボボックス」じゃなくて「スピナー」spinnerと呼ぶのですな。
スピンするイメージがないのだが、まあいいや。

 

スピナーを作って、リスナーを設定すると、選択されたときにonItemSelected()が呼ばれる。
引数にidがついているから、それで選択されたアイテムの番号がわかるようになっている。

なので、大項目のonItemSelected()のときに、小項目用のスピナーを設定すればよいはず。

 

動的にスピナーの項目を作るときは、ArrayAdapterにadd()していって、最後にスピナーにsetAdapter()すればよい、ということになっている。
実際にそれで設定できたのだが、妙にアイテム間が狭い。。。

image

小項目のArrayAdapterとSpinnerは、大項目のonItemSelected()ではcontextが合わないようなので(たぶん)、privateメンバにしてonCreate()のときに設定させている。
だからかなぁ。

 

こう、こまごま言葉で説明せずにソースを置きたいのだけど、今使っているブログエディタ(Open Live Writer)にはまだソースを載せるのに適したプラグインが出てないのだ。
GitHubに置こう。
https://github.com/hirokuma/AndroidTwoSpinners/blob/master/app/src/main/java/com/blogpost/hiro99ma/twospinners/MainActivity.java

みんなのまねして、android.R.layout.simple_spinner_itemを使っているけど、これが狭いということなのかな。

Y.A.M の 雑記帳: Android Spinnerの選択肢をXMLで指定する
ああ、スピナーの部分とドロップダウンのところで違うレイアウトになっているということか。
今回は、コンボボックスみたいなやつだから、ドロップダウンなのだろう。

image

よーし。

 

なんか、こうですね、XMLでやるところと実装でやるところがよくわかってないし、設定値の関係性もわかってないのですよ。
やっていれば、いつか見えてくるようになるのだろうか。。。

[java]enum値の名前が取得できる!

Cだと、デバッグログのためにこういうことをしばしば行う。

=======================
typedef enum {
  ERR1,
  ERR2,
  ....
} ErrType;

const char *getErrString(ErrType err)
{
  switch (err) {
  case ERR1: return "ERR1";
  case ERR2: return "ERR2";
  ....
}

=======================

面倒だから、そのままint値で出力することもあるのだけど、数字だと検索しにくいし読みづらいので、変換するのだ。

 

久々にAndroidアプリを作ろうとしていて、似たような状況が発生した。
enumもオブジェクトだから、こういう関数を作らずにメソッドにしてしまうか。。。

そういえば、リフレクションとかいう、メソッド名で逆引きして実行するような機能があったから、あんな感じで名前を引っ張れるのでは?

 

=======================
enum ErrType {
  ERR1,
  ERR2,
  ....
}

void xxx(ErrType err) {
  ...
  Log.d(TAG, err.toString());
  ...
}
=======================

これでいけるんだ!
はぁ、さすが21世紀やねぇ。。。

 

j2objcじゃないけど、CをJavaっぽく置き換えてくれるツールはないだろうか。。。
コンパイルが通る必要はないのだけど、ちょっとやるたびにJavaだとどう書くのかがわからないのだ。
C to Java converter
これを使うと、少しはそれっぽくしてくれたのだが、うーん、期待通りではないな。

地道に覚えていくしかないか。

2016/05/26

[esp8266]UART1TXを使う

久々に、ESP8266を使ってみよう。
今のNon-OS SDK最新版は、V1.5.3だ。
技適が心配だったのでNon-OSを使っているのだけど、Arduino版まではOKとのこと。


使うにしても題材がほしいところだが、そういえばESP8266にはまだRC-S620/Sをつないでいないことを思い出した。
RC-S730もあるのだが、WROOM-02にはRX/TXが出ているので、そことつなげばよさそうだから、I2Cよりは楽そうだ。

 

そこで、はたと困った。
ESP8266は、os_printf()でログを出すとTXから出力される。
しかし、ここはRC-S620/Sとつなぎたいので、別のところからログを出したい。

ドキュメントを見ると、IO2がUART1のTXDになることができるとのこと。
APIは、os_install_putc1()を使うらしい。
そうすると、os_printf()がUART1 TXDから出力されるようだ。

 

あれ、ではUART0 TXDを使うにはどうしたらよいのだ?
これは、文字列ならuart0_sendStr()を使うのがよさそうだ。
printf()風ではないので、sprintf()で加工してから使うとよいだろう。
RC-S620/Sに対してはバイナリの送受信だから、uart0_tx_buffer()がよいかな。


https://github.com/hirokuma/esp8266_httpget

動かしたい場合は、include/user_config_sample.hをinclude/user_config.hに変更して、中を自分の環境に合わせよう。

image

WROOM-02は、スイッチサイエンスさんから購入している。
間違えて、モジュールと基板を別々に買って自分でハンダ付けしているので、見た目がきれいじゃない。。

ESP-WROOM-02 Wi-Fiモジュール - スイッチサイエンス
ESP-WROOM-02ピッチ変換用基板《シンプル版》 (基板のみ) - スイッチサイエンス

ハンダ付けされたセットと同じになるだろうと思い込んで「動かん動かん」と悩んでいたのだが、別売りの場合はIO2が3.3Vに接続されているのだ。
基板裏のSJ2をカットして、出力されるようになった。

 

UART Download ModeにせよFlash Boot Modeにせよ、IO2はHighにしておかないといかんことになっている。
が、よくわからんが、オープンにしたままでも起動した。
ESP FLASH DOWNLOAD TOOLで焼くときも、RXDは使っていないのか、IO2にPC側のRXDをつないでいても焼くことができた。

プルアップした方がよさそうではあるのだが、よくわからんし動いているのでそのままにしておこう。

 

ENとRSTはWROOM-02基板の方でプルアップさせているからこういうイメージだ。

image

[勉]IoT

しばらくやっていなかったが、仕事が空いてしまったので勉強シリーズをやっておこう。

今回は「IoT」。


前もやったけど、よくわからんままだった。
hiro99ma blog: IoTとは何だろうか

 

IPAのドキュメントを読んで、世間の意見はどうか別としても、IPAの思っているIoTはわかったような気がする。

image

これは「つながる世界の開発指針」P.9の図だ。
まずは、単独でも動くもので、つながることが可能な機器がある(IoTコンポーネント)。

これがつながることで、単独のIoTシステムになる。
「つながる」というのは、センサーのような情報を発信するIoTコンポーネントが中継ノードなどを通してサーバにデータをアップし、サーバが情報を集めるところまで指している。
集めた情報を、さらに別のところに応用(集めたデータを解析したり、制御に反映したりしたり)する側面もある。

この単独のIoTシステム同士がつながって、さらに大きなIoTシステムを構成する。
つながるだけじゃなくて、つながって新たな価値を生むところまで含むようだ。

 

ということらしい。
前に読んだ「手引き」の方は、単独のIoTシステムとして説明していたと思う。
まあ、説明上の図がそうなっていただけだがね。

私も、まずはその認識に倣うとしよう。
仕事で関わるとしたら、IoTコンポーネントの部分になるのかな。


PDFを読んでいると、ときどき聞く「Industrie4.0」が出てきた。
これは、工場などの生産に関することなのだな。
そういう意味では、メーカーが開発するだろうから、今のところ私が関係することは無いだろう。

こういう規格で関係するのだったら、家電やスマホなどとの規格になるだろう。
HomeKitなんかもそうなるんだな。

しかし、日本の家は広いところがあまり多くないので、家電をわざわざつないでどうするんだろう、と個人的には思ってしまう。
これは私の行動範囲がかなり狭いとか、家電が少ないとか、スマホをほとんど使わないとか、そういう要因のせいかもしれん。

まあ、今回調べたIoTの観念からすると、家の中がIoTで構成され、次に各家々がIoTでつながる、というようなことになっていくのか。
隣の家のことを知りたくはないだろうし知られたくはないだろうが、火事が発生したようだ、みたいなのは知りたいかも。
変な人が住んでないかどうか、とかもか。
火事はセンサーでわかると思うけど、変な人はセンサーじゃ難しい気がする。

2016/05/25

Windows10でcygwinのコマンドがランダムにエラーを起こすので64bitにした

hiro99ma blog: Windows10でcygwinのgccがランダムにエラーを起こすが、rebaseallか

rebaseallしたが、その日は安定していたような気がしたのだけども、今日は全然ダメだった。
gccではなく、makeからforkして処理するものがダメだったようだ。

 

Windows10 Pro 64bitで起きている人が多そうだった。
私もそうだ。
rebaseで直らない人もけっこういる。
その中で「64bit版のcygwinにしたらよかった」という人がいた。

もうどうしようもなかったので、32bit版のcygwinを削除して、64bit版にした。
今のところ、それで動いている。
32bit版でビルドしたものは再ビルドが必要なのだけど、幸いWindows10にしたばかりなので資産は少ない。

 

cygwinとともに、TeraTermをインストールすると入っているcygtermも使っていた。
これは、以前は「64bit版は自分でビルドしてね」だったのだけど、今はTeraTermのインストール時にcygwinのバージョンをチェックして、自動的に32bit/64bit版を切り替えたcygtermをインストールしてくれるのだ。
コンテキストメニューからの「Cygterm Here」も使える。

うーん、ありがたい。
これだったら、32bit版は削除せずによかったのかも(心配だったので削除して、64bit版をc:\cygwinにインストールした)。
けれども、同じものが2つあるとろくな事がないのもよくある話なので、よしとしよう。

[c/c++]リングバッファふたたび

たぶん、もっと格好のよいリングバッファ実装があるはず。。。
その思いが捨てられず、探していた。

 

Learn C The Hard Way
RingBuffer_write()を見ると、memcpy()しているのだが、引数のlengthをそのまま使っている。
バッファがあふれそうな気がするのだが。。。
マクロの中でmoduloを使っているけど、書込んだ後の話だし。
<string.h>をincludeしているから、memcpy()に秘密があるわけでも無さそうだし。。。

わからん。
check()で"Not enough space"とあるから、一度に書き込めるサイズは連続したスペースの分まで、ということだろうか。

 

循環バッファ - アルゴリズムとデータ構造 | ++C++; // 未確認飛行 C
こちらはmoduloを使っているが、サイズを2のべき乗にすることで速度の高速化を図っているとのこと。
そうか、nRF51 SDKのバッファサイズが2のべき乗しか許可しないのは、このしくみが使われていたのか。。。


Googleで5ページ分ほど調べたが、気になるのはこれくらいだった。
あとは、1データずつ詰めていくタイプだ。

そこそこがんばって作ってみたのだが、あまり速度に需要はないのかもね。

GitHubのリポジトリはボタンを押せ!

昨日書いた、うちのFirefoxでGitHubのリポジトリ名(git://~)が表示されない件だが、今日やるとChromeも表示されなくなっていた。
うーむ、困った。

image

 

ボタンを押してみた。

image

あっ!

 

そういうわけで、「Clone or download」のボタンを押すと表示されるようになっていましたとさ。
めでたしめでたし。

 

いつからそうなったんだろう。。。

[c/c++]いまさらリングバッファ

Firefoxで、githubのサイトの「あれ」が表示されなくて困っている。
Chromeでは表示されているし、以前は表示されていたから、Windows10にしてインストールしたときなどに何か忘れているのか・・・。
Flash Playerかもしれないと思ってインストールしたけど、変わらん。
アドオンも無効にしたのだが、変わらん。。。

image

URL名じゃないけど、git://とかhttps://とかの、あれが出てこないのだ。
ちっ。


さて、今回はリングバッファだ。
作業が空いてしまったので何か作ろうと思ったのだが、その「何か」がリングバッファだった。
私は「リングバッファ(ring)」で覚えたけど、「循環バッファ(circular)」のような呼び名もあるようだ。

教科書にも出てきそうな内容ではあるが、私が初めて見たのはネットワークのドライバか何かだったと思う。
こういうのもあるんだ、と感心した記憶があります。

それから早数年…十数年…数十年…、ソースが公開されることも増え、フレームワークなんかにはデータ構造に関するライブラリも付いていることが多く、こういうのは実装することがなかったので、やってみました。

というよりも、見たソースがけっこう高機能なものが多く、さらっと動きが速いものが作りたかったのです。
構造体をリングにするとかではなく、単に1バイトずつのバッファがリングになっているだけというものでよいのです。

 

基本に忠実に、

  • バッファの前後がつながっている
  • 位置として、書込みポインタと読込みポインタを持つ
  • 読込みポインタは、書込みポインタを追い越さない

くらいの内容で考えました。

あとは、構造体みたいなデータは考慮外で、単にバイトデータだけを管理します。
ドライバ付近で使うイメージですかね。

また、ポインタがぐるっと回る動作を剰余(%, modulo)で実現するものが多いのですが、あれって時間かかるよなぁ、と思い、目に見える実装部分での剰余やループはなくすことにしました。


まだテスト中だが、現状を置いておこう。
https://github.com/hirokuma/ringbuf

いやぁ、かかったよ!
こんなにかかるなんて考えてなかったですわ。
頭が回ってないのだろうか。。。

 

最初は、malloc()ではなくstatic変数でべたべたに作っていた。
ここは以前の反省で、データ構造で分離できるものは構造体にして引数にした方がよい、ということで、外に出した。

この構造体だが、メンバが

  • 読込みポインタ
  • 書込みポインタ
  • バッファサイズ
  • 空きかどうか
  • バッファ

となった。
この「空きかどうか」を採用するかは、けっこう悩んだ。


初期状態は、こう。
Wは書込みポインタ、Rは読込みポインタだ。

image

データ(A, B, C, D)を詰めると、こう。
書込みポインタは「次に書込む位置」を、読込みポインタは「次に読込む位置」を表している。

image

 

では、次に1バイト書込むとどうなるか?

image

RとWが並ぶのだ。
「空きがあるかどうか」を判断するのに、RとWの位置を使うとすると、この状態はまずい。
全部空いている状態との区別が付かないのだ。

 

RAMよりもROMに余裕があるだろうから、RとWが揃わない実装にしようと思い、あれこれやっていた。
が、まあ、予想が付くかもしれないが、かなり面倒だった。。。
ちょっと処理するたびに、RとWが並ぶかどうかをチェックしないといけないのだ。

疲れて、空きがあるかどうかのフラグを別に分けることにした。
フラグが立つのは、初期化時と、読込んでRとWが一致したときだけだ。


あとは、ループ処理を実装で書かないという制約が大きかったか。

剰余の代わりは、このくらいの処理であればif文で書いてしまえば済む。
三項演算子でもよいだろう。

ただ、データの読み書きでループ処理を実装で書かないので、memcpy()を使うしか無い。
いや、そうじゃないな。
データの読み書きをmemcpy()でやりたかったからループ処理が不要になったのだ。

 

memcpy()で処理するには、データが連続するように扱うしかない。
たとえば、RとWがこういう配置だった場合。

image

読込み可能なのは青い部分、書き込み可能なのは茶色の部分だ。
RとWの位置が逆になると、もちろんこうなる。

image

つまり、パターンとしては、

  • 領域が1つしかない
  • 領域が2つに分かれている

があることになる。
剰余とループを使うと、このパターン分けが不要になるのだ。

でもまあ、パターンが2つしかないならいいか、というのがmemcpy()でやろうとした理由だ。
そこまでは考えていたのだが、この図だとポインタが[0]とか[4]にあるとか、バッファが空いていないとか、途中までしか読込まないとか、そういうのをやっていくとゴチャゴチャしてきたのだ。


WriteとReadは似たような構造をしているのだけど、気にせず分けた。
こういうのを格好良くまとめようとすると、だいたい私の場合はろくなことにならないのを経験上わかっているのだ(私という人間が)。

 

ただ、けっこうテストパターンを通したつもりだったのだが、カバレッジを見ると通っていないルートが残っていた。
通し切れていないのか、通るはずがないルートなのかはわかっていない。

 

malloc()/free()にしてるけど、そこは書き換えできるだろう。
配列にできれば、sizeも不要になって、sizeを使っているところはsizeofで置き換えられるんじゃなかろうか。

 

あとはねぇ、たぶんまだまだ格好良くできると思うから、そこですかね。
汎用性は他の人がいいのを作っているので、速度とサイズ重視で行きたいところだ。

2016/05/23

[c99]C99のinlineで悩む

構造体の中身をあまり意識させたくないので、引数に構造体のポインタをもらって要素をreturnするだけの関数を作った。
でもまあ、こういうのにわざわざ関数ジャンプしてほしくないよな、たぶん最適化してくれるだろうな、と思うのだが、ヘッダでinline指定して実装もそこに書いた。

そしたら、gccでビルドするとリンクエラーになるのですよ。
nmで見てみてもU扱いだから、他でリンクする必要ありと思っている。
いやー、classのメンバ関数だってinlineにするときはヘッダに実装まで書くのに、なんでここでリンクエラーになるの??

 

調べると、GCCのinlineはC99のinlineとは違うということだった。
static inlineは一緒で、

GCC:inline   -->  C99:extern inline
GCC:extern inline --> C99:inline

そういえば、そういうことを言っていた気がするが、いままでstatic inlineしか使っていなかったので気にしていなかったようだ。

 

こちらによると、-std=c99をつけるとC99の仕様に合うらしい。
さらには、GCCのv5からはデフォルトでC99仕様になっているらしい。
Using extern inline · ytomino/headmaster Wiki

あれ・・・じゃあ、私のが動かないのはGCCだからじゃなくて、inlineの書き方が違うからということか。

 

では、以下はGCC v5で、念のため-std=c99まで付けた場合ということで進める。

 

ヘッダに「inline」で関数実装を書くと、発生するのは、undefined referenceだ。
それを「extern inline」にすると、発生するのは、multiple definition。

externが付いていると「よそでも参照するよ」という関数がincludeしたファイルの数だけできるので、multiple definitionになる(includeしたファイルが1つしかないならエラーにならない)。
付いていないと、それは単なる宣言と見なされてしまい、undefinedになるということか?

 

なので、ヘッダに実装を書いてしまいたいのであれば「static inline」にして、ファイルごとにstatic展開してしまうしかないか。
でも、そこまでやるんだったら、インラインになるかどうかよくわからんinlineを使うよりもマクロ関数にしてしまいそうだ。

 

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0472fj/BABEGBHC.html
ここを見ると、ヘッダに「inline」で関数実装を書いているのよねぇ。
「コンパイラのコーディング慣行」の章だから、「他は知らんけどarmccはこうなんだよ」ということだろうか。


あれ・・・なんかまだ認識を間違っているみたい。

ヘッダにinlineの宣言だけを書いて、実装をソースに持っていくとコンパイルの警告が起きるようになった。
「inline function 'xxx' declared but never defined」だ。

考えたら当たり前で、単にプロトタイプ宣言をヘッダに持っていっただけだからだ。
inlineが付いているから、同じスコープ内に関数定義がないということで警告しているのだろう。

だったら、ヘッダに定義を書いていたらうまくいってよさそうなのだけど、これはダメなのだ。
ヘッダに実装を書かずextern inlineにし、ソースにinline定義を書くと、ヘッダのextern inlineについては警告するが、リンクが通る。
どう並び替えても、あまり結果が変わらない。

 


使うのはstatic inlineくらいかなぁ、という気持ちになってきた。

2016/05/21

[bbg]usb peripheralを別のドライバにする

Linuxでドライバうんぬんは、よくわかってない。

BeagleBone Greenを前回の設定でビルドすると、USB microBでPCにつないだ場合にはネットワークアダプターとして見えていた。

これはBeagleBoardでやったときもそう。
しかし、あちらは「どれをアクティブにするか」というのがmenuconfigの設定にあったので、それをCDCにすると、g_serialが読まれていた。

BeagleBone Greenで使ったカーネルでは、どれが選択されるかというのがぱっと見てわからなかった。
それに、ドライバというかモジュールとしてはビルドされているようなので、後からなんとかなるんじゃないかと思ったのだ。


まず立ち上げると、PCからはネットワークアダプターとして見えた。
lsmodすると、g_etherが読まれている。dmesgもそうだった。

このまま

$ sudo modprobe g_serial

としても、「そんなのはない」とけんもほろろだ。

 

マルチファンクションだから、うまいことやってくれるのかと思ったが、そういう意味ではないということか。

$ sudo modprobe -r g_ether
$ sudo modprobe g_serial

これで開けた。
PCの方も、「Linux USB Ether/RNDIS Gadget」から「Gadget Serial」になった。

 

まあ、同じところをEthernetとSerialと同時に見せかけるというのは無理だよな。


こういう、少しわかって先に進むと、また理解できそうだけどちょっとわからない、という疑問が出てくるところが、Linuxの深いところにはまり込む人を生み出すところなのかも。

こんだけリソースがあると楽だろうなぁ、と思いつつも、あるならあるで実装量が多くなって大変そうだ、とも思う。
まあ、どこも大変だってことだ。

[bbg]BegleBone Green用のLinuxを作ろう

BeagleBone Greenが届いたので、Linux環境を作ろう。
話があっちこっち飛んで、済まんね。

 

作ろう、と書いたものの、サイトの通りにやるだけだ。
https://eewiki.net/display/linuxonarm/BeagleBone+Black
Greenは、BeagleBone(無印)とBeagleBone Blackのどちらに近いのかわからんかったが、Blackの方に近いようだ。

  • CPU
    • BBG : AM335x 1GHz (Cortex-A8)
    • BB : OMAP3530 720MHz (Cortex-A8)
  • RAM
    • BBG : 512MB
    • BB : 256MB
  • FLASH
    • BBG : 4GB
    • BB : 256MB

こ、このくらいにしておくか・・・。
今の人はこれを見ると「どっちも遅いやん」と思うかもしれないけど、私が学生の時なんて研究室にIntel 200MHzのマシンが来て「うおー」って思った記憶があるくらいだから、けっこう感慨深いのだよ。
GHzなんてほんの最近という気がする。
歴史の年表で、地球の誕生から近代までの人口を折れ線グラフにしたものがあるけど、あのイメージだ。


まず、パソコンで動くLinux環境を用意する。
私はWindows10でVirtualBoxを使っている。
Xubuntu14.04なのだが、あまりバージョンは気にしなくてよかろう。
そこまでできれば、上から順番にやるだけだ。

[ARM Cross Compiler: GCC]
書いてあるまま。

[Bootloader: U-Boot]
書いてあるまま。

[Linux Kernel]
checkoutをどれにするか迷うが・・・私はorigin/am33x-v4.4にした。
スクリプトを動かすとmenuconfigが出てくるので、好きにする。
何もしなくても大丈夫じゃないかね。
ビルドし終わると、「Script Complete」の次にexport文が出力されるので、それをコンソールで実行させるのがよい。
私の場合では「export kernel_version=4.4.10-bone10」を実行した。

[TI BSP]
git branchをrebaseしていないなら使うな、と書いてあるから、スルーしてみよう。

[Root File System]
debianかubuntu、あるいはsmall flashから選べるようだ。
私はubuntuにした。

[Setup microSD card]
まず、lsblkで様子を見てみる。
VirtualBoxだと、メニューの「デバイス>USB」からSDカードを指したデバイスを選んでおかないと見えない。SDカードだとFATフォーマットされていそうだから、Linuxが認識していればデスクトップなどにマウントできそうなアイコンが表示されるかも。
lsblkすると、デバイスとサイズが表示されるので、SDカードのサイズらしきものを見るとよい。
心配なら、一度抜いてからlsblkし、挿してからしばらくしてlsblkし、増えたやつがそれだと思えばよいのではなかろうか。
そのデバイスを、exportする。
うちはsdbだったので、

export DISK=sdb

とした。

そして、ddで全部zeroにしたあと、install bootloader。
えっ、これもddなの?
いままではMLOもu-boot.imgも、VFATのパーティションを作ってコピーしていたのだ。
まあ、時代が変わったということかね。

そのあと、sfdiskのバージョンを調べて、それによって変える。
うちのは2.25以下だったので、下の方(--unitがある方)を実行。
mkfs.ext4のバージョンも1.42以下だったので、下の方を実行。
フォーマットが終わったら、/media/rootfsにマウント。

[Backup Bootloader]
ほう、ここでMLOとu-boot.imgをSDカードにコピーですか。
そのコピーも、本番で使うのでは無く、バックアップの意味合いのようだ。

[Dealing with old Bootloader in eMMC]
既存のeMMCにあるブートローダをクリアしたくない場合は、/media/rootfsにuEnv.txtを置くことで回避できるらしい。
でも、この後でもuEnv.txtをコピーする工程があるのよねぇ。

[Install Kernel and Root File System]
ここに出てくるexportの説明が、前の「Linux Kernel」のビルド後に出てくる話だ。

[Copy Root File System]
やるだけ。

[Set uname_r in /boot/uEnv.txt]
少し前にuEnv.txtが重なる、と書いたが、パスが違うな。

[Copy Kernel Image]
[Copy Kernel Device Tree Binaries]
[Copy Kernel Modules]
[File Systems Table (/etc/fstab)]
[Networking]
ひたすらやるだけ。
Networkingはnanoでテキストエディタが開くので、その次の「auto~」をまるまる貼り付けて、Ctrl+x、Y、Enter、などとして上書きする。viでもなんでもよいだろう。

[Networking: Using a shared SD card with Multiple BeagleBone]
何か知らんが、alwaysとeth0が見えたので、どのBeagleBoneに挿してもネットワークがeth0で見えるようにしてくれるとかか?

[Remove microSD/SD card]
syncしてumount。


さて、これでSDカードの準備はできたのだが、どうしたものか。
BeagleBoardの場合は、NANDにある方で起動していたので、USERボタンを押しながら起動させてSDカードを見ていたのだが。

image

あまり考えず、BBG上のJ1コネクタにUSBシリアル変換ケーブルを挿した。
そして電源ON!
・・・うん、SDカードから起動してくれた。
おめでとう、私!

[ipa]「手引き」を読む

せっかくIPAが手引きを作ってくれているので、眺めることにした。
「IoT開発におけるセキュリティ設計の手引き」を公開:IPA 独立行政法人 情報処理推進機構

 

感想を書いたわけでもなく、だいたいこんなことを書いている章なのね、というのをメモしただけのExcelはこちら。
https://drive.google.com/open?id=0B2_3hJpJ5Ui2bC1jWVZQMjVPMjg

図形のところは、文字化けしたりずれたりしているけど、そんなに大したことはない。
「IPA~」のところは「IPAの脆弱性対策情報データベースなど」と書いているだけだ。

 

参考文献を除くと、55ページある。
そのうち、対策検討の実施例が31ページある。
なので、さらっと読む分にはそれほど時間はかからない。

「言われてみればそうだよな」とか「そんなのわかってるよ!」というところではあるのだが、明文化してあったりチェックシートがあったりするので、整理するのに役立つだろう。

そして、あくまでも手引きなので、「こういう検討の仕方をするといいですよ」という書き方になっている。
細かいところは実例として挙げてあるが、同じものを開発することはないだろうから、自分のところの製品について検討をするしかあるまい。

 

同じくらいにIPAさんが出していた、こっちも気になる。
「つながる世界の開発指針」を公開:IPA 独立行政法人 情報処理推進機構

こっちもざっと読もうとしたが、最初にこういう表があった。

image

あー、私は開発者だから、全部読んだ方がいいんだ。
少し腰を据えて読みますかね。

BeagleBone Green来たる

もう届いた。

image

 

はじめ方

  1. まずは、パソコンで以下を開いておく。
    BeagleBoard.org - getting-started
  2. microSDを挿しておく
  3. Step2:ドライバをインストールする
  4. パソコンとつながったmicroUSBを挿す
  5. しばらくすると、ネットワークアダプターの「Linux USB Ethernet/RNDIS Gadget」として認識してくれる
  6. Step3:http://192.168.7.2をブラウザで開く
  7. うまくいけば、何か画面が開く

 

microSDを挿すのは、ここだけだといらないね。
画面が派手派手だけど、全部オンボードのFLASHか何かに入っているんだろうか。


しかしまあ、いろいろできますなぁ。
BoneScriptとかいうJavaScriptのライブラリが動くらしく、ブラウザからBBB上のLED点灯を制御できるサンプルが動いた。

 

買った時点でこれが動くのでは、私の出番は無いぞ。
差別化するためには、簡単に操作できるわけではないという分野に切り込むしかないのか。
そうなると、セキュリティ強化とかだな。

Firefoxで同期状態にあり、片方のPCでアドオンが消えたとき

Firefoxをメインで使っている。今のバージョンは46.0.1だ。
そして、Syncを有効にしている。

Syncは便利なのだが、あまり融通が利かない。
「前に戻したい」とかできないし、「サーバでは何を保存しているの?」とか確認できない。

 

そして困るのが、片方のPCでFirefoxを使っていて、間違いが起きた場合だ。
いま起きたのは、AVGをアンインストールしたらFirefoxのアドオンが全部消えてしまった、という現象だ。そこまで消してほしくなかったのだが。。。

削除された情報は、あまり時間をおかずにサーバに通知され、サーバからも消されてしまう。
だから、別のPCでFirefoxを起動するとアドオンが消えてしまうのだ。。。

 

が、これはチャンスでもある。
別のPCの方には、まだ残っているとも言えるのだ。
一番よいのは、別のPCでまだFirefoxが起動していない状態。
この状態なら、まあまあ元に戻すことができるようだ。

まず、Firefoxを起動する前にプロファイルのコピーを残しておく。
Windowsだったら、%APPDATA%で検索して、Mozilla\Firefox\Profilesの中にあるフォルダをまるまるコピーしておく。

そしてFirefoxを起動し、メニューからアドオンマネージャーを開く。
そうすると、しばらくすると同期が走って、アドオンがどんどん消えていく。
ただ「元に戻す」も出てくるので、これで元に戻してしまうことも可能だ。
だいたいはそれで元に戻るようだ。
私はLastPassを使っているのだけど、それは戻らなかったのでインストールし直した。

なんとなく心配だったので、元に戻した後、Firefoxを終了させて、コピーしたプロファイルのフォルダをコピーし直した(心配だから、リネームじゃ無くてコピーね)。
そうしておくと、サーバにはプラグインが削除されていないことになっているから、同期しても消されないだろう。
さっきのLastPassは、ここまでやっても戻らなかったのだが、インストールし直すとログイン情報は残っていたから、ちょっとしくみが違うのかも。

 

上記はFirefoxをまだ起動していなかった場合だが、起動していた場合はどうしたものか。
たぶん「あっ」と思ったときには同期されていると思う。

まずはFirefoxを終了させずにアドオンマネージャーを開き「元に戻す」をするとよいだろう。
それくらいしかやれることがないのかな?

アドオンだったらそれでよいけど、パスワードだったらどうしようもないかも。
ブックマークは、bookmarkbackupsに残っているかもしれない。

 

パスワードは、Firefox Syncだけじゃなくて、別の方法でも残すようにしておいた方が無難だな。
クラウドストレージなんかを使っているのなら、プロファイルフォルダごとそちらに移動させるのもよいかもしれない。あっちは履歴を残してくれることが多いから、元に戻しやすいだろう。

はぁ、珍しく早起きしたのに、これで朝が終わってしまったではないか。。。

2016/05/20

[bb]BeagleBoard(無印)を久々に使う (4) - WiFiが使える

前回で終わるつもりだったけど、いろいろ設定がわからなかったので、メモがてら残します。

 

昔は、LAN接続するのにBuffaloのLUA2-TXを使っていたのですが、動かなくなっていました(壊れた、という意味)。
SDカード経由でプログラムを渡せばいいか、と思ったのですが、Raspberry Pi用に買っていたWi-Fiドングルがあるのを思い出しました。
Raspberry Pi用といいつつ、ノートPCで普通に使っているのですが。。。

もしかしたら動くかも、とBeagleBoardに挿したところ、動きました。
いやあ、さすがですねぇ。


iwconfigでいけるのかと思っていたら、wpa_supplicantがいるようでした。
どちらも、ちゃんとインストールされていたので大丈夫です。
rootfs構築の時にビルド済みのものがあったのかな?

 

ここを見ながらやりました。
Linuxで無線LAN (ゆうちくりんの忘却禄)

まずはiwconfigでインターフェース名を調べる。

$ iwconfig

うちのは、wlx~と長い名前でした。MACアドレスか何かかな?

 

$ wpa_passphrase つなぎたいSSID名 パスキー > wpa_supplicant.conf

うちは、WPA/WPA2-PSK(AES)だったので、protoがRSNになっているものをまねしました。

 

$ sudo wpa_supplicant -iインターフェース名 -cwpa_supplicant.conf &
$ dhclient インターフェース名

-iと-cの間にはスペースはいらないらしい。
最後に&つけて、裏で動かすようにしている。付け忘れたら、Ctrl+Zしてbgだな。

 

つながると、いろいろログが出てくる。
これは、earlyprintkとかでいろいろ有効にしているせいかもしれん。


これでネットワークがつながったので、Windows上のVirtualBoxで動いているXubuntuと接続できる。
NFSでやろうかと思ったけど、なんかめんどくさそうだったので、SSHでやることにした。
なお、仮想マシンのネットワーク設定は、アダプター1がNATで、アダプター2がホストオンリーアダプターになっている。

 

まず、仮想マシンのNATで、ポートフォーワード設定を行う。
プロトコル「TCP」、ホストポート「22222」、ゲストポート「22」。
イメージとしては、BeagleBoardからWindowsのIPアドレスにポート22222番でSSHしに行くと、それをゲスト側に22番として横流しする。
ホストは22のままでも良い気がするが、まあ別にしておこう。

 

BeagleBoardからSSHで接続する。
xxxはLinux側のユーザ名で、yy.yy.yy.yyはWindowsのIPアドレスだ。
あとは、聞かれるままに操作すればよいだろう。
$ ssh -p 22222 xxx@yy.yy.yy.yy

 

ファイルコピーだけしたいなら、scpでよい。
こっちはポート番号の指定が大文字の-Pだ。
$ scp -P 22222 xxx@yy.yy.yy.yy:~/test.txt ./


しかしまあ、こうも簡単に外につなげられるとなると、いろいろ怖いですな。
あまりセキュリティに明るい方では無いので「こう設定しておけば大丈夫!」というのを知っておきたいものだ。

IPAからIoTのガイドラインが出ているらしいので、読むと助けになるのかな?

2016/05/19

[bb]BeagleBoard(無印)を久々に使う (3) - 昔はよかった

いろいろ、試した。
menuconfigのオプションを変え、ソースも変更してみて、YoctoのBeagleboard版も試して。。。。

 

そしてまた、配布元のコメントページに戻って読み直した。
そうすると、気になる記述が見つかった。

C4版でデバイスツリーのを動かしたけど、v3.14だと600MHzまでしか出ないよ?

このコメントは、B6版の人よりも数ヶ月後のコメントだ。
ということは、v3.14ではデバイスツリーがあっても動いていたんだ!

 

それを信じて、安全そうなv3.13をcheckoutして試した。
・・・動く。
動くぞー!!

起動ログもきれいなもので、FAILEDのものがない。
えー、こんなに違うものなの??

もう、何がいいとか悪いとかはわからないが、昔はよかった、ということか。


夕方までほとんどあきらめていたので、BeagleBone Greenを注文してしまったのだな。
まあ、そう高いものでもないし、新しいOSが試せるからいいのだけどね。いいのだけどね。

2016/05/18

[bb]BeagleBoard(無印)を久々に使う (2) - デバイスツリー

東京スカイツリーでもクリスマスツリーでもなく、デバイスツリー。
Linuxのあるバージョンから使われるようになったらしい。
いま試しているのがLinux 4.1.24で、これもデバイスツリーなるものを使っている。

 

記事が探し出せないのだけど、こちらの方の別の記事で「デバイスツリーがあると動かない」ということが書かれていた。
古い BeagleBoard B6 その後 - 私の二次記憶

 

その時に1回だけSDカードにコピーしたデバイスツリーのディレクトリ名を変更して試したけど、立ち上がらなかったのだけど、今やったらログインまで進んだ。
この記事を読んでなかったら、そこは疑うことがなかったな。

しかし、最初は読めなくしてもダメだったので、初期設定からもう少し変えたところの効果もあったと思われる。
それがどれなのかはわからないけどね。。。


起動すると、

  • LED USR0が点滅
  • LED USR1が消灯

となるようなので、コンソール出力先が正しくなくても、起動したかどうかはこれで見えるだろう。

 

古いBeagleBoardって、版数がどうとかじゃなくて、xMよりも前とかそういう話なのかな。。。

今回は新しいLinuxで動かしてみる、が目標だから、デバイスツリーに対応する前のものを使う、というのは無しだ。
デバイスツリーを読まなかったらドライバは読まないのだろうか?
ネットワークとUSBさえ動いてくれればよいのだけど。

それは次回だ。

[bb]BeagleBoard(無印)を久々に使う (1) - kernelまで進まん

部屋の掃除をしていたら、BeagleBoardが出てきた。
な、懐かしい・・・。
当時は画期的だったのだけど、今は似たようなボードがたくさん出てきて、年数も経って忘れ去れてしまったように思う。

でも、Cortex-A8ベースでけっこういいのだよ。
Linuxも動くし、Androidも当時は動くくらいだったのだ。

Raspberry Piが手元にあるけど、この人も久々に使ってみよう。


まずは、Linuxがほしい。
ほしいのだが、これがなかなか探し出せない。
古いというのもあるが、BeagleBoardはシリーズとして、無印、xM、BeagleBone、BeagleBone Blackなどいろいろあり、BeagleBoardで検索してもBeagleBoneの方が出てきやすいのだ。
新しいのはBeagleBone Blackで、略称はBBBらしい。漫画のタイトルかと思ったよ。

 

さて、そういうして見つけたのが、こちら。
BeagleBoard - Linux on ARM - eewiki

ちゃんと「BeagleBoard Cx」と書いてある。
うちにあるのは、C4版だ。

このサイトはかなり手順がきっちり書かれていて、コピペでほとんど実行できるレベルだ。
助かった。

助かったのだけど、kernelが起動しない。。。
たぶん、カーネルの解凍メッセージが表示されて起動していくのだろうが、u-bootの「Starting kernel ...」の後が続かないのだ。
うーむ。


解凍の「Uncompressing~」というメッセージを出すのは、arch/arm/boot/compressed/misc.c辺りのようだ。
だから、少なくともここまでは届いていない。。。か、コンソール出力先がu-bootから切り替わってしまったか。

u-bootではBeagleBoardのP9で出力していて、これはOMAPのUART3になっている。
UART3だから、ttyO2になるはずだし、u-bootもttyO2だから間違いは無いだろう。
記憶では、Uncompressingのメッセージまではu-bootで使っていた出力先だったような気がする。
自信は全くないのだが、Uncompressingのメッセージ以降が出力されない、という現象だった気がするのだ。
まあ、まだカーネルに出力が移っていないから、生きている出力先を使っているだけかもしれない。

生きている出力先?
どうやってzImageの自己解凍処理が生きているUARTを見つけ出すのだろうか。。
カーネルの方はbootargsからconsoleを参照するし、earlyprintkはたぶんCONFIG設定のDEBUG_OMAP3UART3を見てくれると思う。
今まで何気なく出力されていたものが、こんなに意味を持つとは。。。

 

えーっと、decompress_kernel()でputstr()を呼んでる。
putstr()はputc()を呼んでる。
putc()はマクロでicedcc_putc()を使っている。
icedcc_putc()は、中でアセンブラを呼んでいる。どこかのステータスをぐるぐる監視して、解放されたら

asm("mcr p14, 0, %0, c1, c0, 0" : : "r" (ch));

とするだけ。
たぶん、UARTの送信バッファが空いているかチェックしているのだろう。
MCRは、ARMレジスタからコプロセッサにデータを移す命令らしい。
コプロ??
あ、これはCONFIG_DEBUG_ICEDCCのときだけだった。

じゃあ、単に標準のputc()を呼ぶだけか。
OSが無いときに「標準」といわれてもねぇ。。。
まあ、それこそ、u-bootがUART3を使ったように、zImageもUART3を使ってくれると考えた方が楽だな。


今日は、このくらいで許してやろう。。。と強がりたいところだが、見当が付いていない。

このあたりはシングルプロセスだから、JTAGデバッガで追おうと思えば追えるはず。
けど、それをやる気力も無いし、それくらいだったら普通の手段で解決させたいのだ。

[bds]Android Pluginsを少し変更

需要があるのかどうか知らんが、Bluetooth Developer StudioのAndroid Pluginsを少し変更したものをgithubに置いた。
オリジナルは、こちらのAndroid Client。

https://github.com/hirokuma/Android_Client_hiro99ma

 

ささいな変更だ。
だが、改行コードがLFでない、とか、インデントがきれいじゃない、とか、空行がやたらと多い、のようなことが気になる人にはよいかもしれない。

Indication処理に対応しようとして、なんとなく処理は追加したのだけど、動くかどうかまでは見てない。

アプリの見栄えをよくするとか、汎用性があるとか、そういうものにできるとよいのだろうけど、まだそこまでは理解できてない。
まあ、動けばよかろうなのだ。

2016/05/17

Windows10でcygwinのgccがランダムにエラーを起こすが、rebaseallか

わからんシリーズだ。

gccだけじゃない感じではあるが、現象が発生するのがそこだから、タイトルがこうなってしまった。

Windows10 64bit環境にcygwin 32bit版をインストールして使っている。
これが、よくわからないタイミングでエラーを起こす。
毎回同じ場所じゃないし、成功するときもある。
これを、もう1台のWindows10 32bit環境で動かすと、特に問題が起きていない。

ファイルのアクセス権とか、その辺っぽい感触はあるのだが、ウイルス対策ソフトを停止させても変わらない。

 

うーん、困ったときはrebaseallだ。
今のところは動いているので、様子見だ。

2016/05/16

[androidstudio]APKがinstallされないのでInstall Runを外す

EddystoneのAndroidアプリをAndroid Studioでいじっているとき、気になることがあった。

ファイルを変更してデバッグしても、変更した内容がアプリに反映されていないのだ。
Runタブを見ると、「no changes」と出力されて、install –rされないまま元のアプリを立ち上げるだけになっているようだ。

じゃあ、APKが変更されていなかったらスキップする、というオプションを外せばよかろうとやってみたものの変わらない。

USBケーブルを抜いて挿せば、install –rされるのでごまかしていたが、どうにも気持ち悪い。

 

use Android studio 2.0 tip that :no changes to deploy - Stack Overflow

ああ、これですこれです。
Install Runのバグなんじゃないの、ということで、外すとよいらしい。

File > Settings…

ここで「Instant Run」で検索すると、「Build, Execution, Deployment」の下に項目が見つかるので、Enableほにゃららのチェックを外す。

 

うん、よさそうな気がする。

2016/05/15

[nrf]nRF5 SDK for Eddystoneは動くのか? (15) - 16KBでは無理

EIDをSlotに割り当てようとするとAndroidアプリのログにエラーが返ってくる件だが、どうもnRF51822側が最初の要因になっているようだ。

RTTでログを取っていると、EIDのconfigure後にSESが固まってしまった。
JLinkを抜くと動き出したので、何か邪魔しているようだ。
なので、RTTを全部消して動かすと、HardFaultが発生していた。。。

 

SESにはMMDというトレースするようなデバッグができるようなのだが、nRF51ではサポートしていないらしい。
コールスタックを見ると、0x20001350が直前なので、これはRAMアドレスだ。

image

examplesにあるble_app_hrsのgcc Linker Scriptを見ると、RAMの開始は0x20002080にして最初の方はSoftDeviceが使うように空けている。
S130 v2.0.0のリリースノートを読むと、最低でも4.9KB(0x13C8)は使うようになっている。

いま使っているEddystoneサンプルは、Linker ScriptをSESが自動生成してくれるようで、Output Filesに入っていた。
それには、RAMが0x20000000からになっている。
まあ、これは__vectors_ram_load_start__が0x20002080になっているから、いいのかな?

となると、コールセンターに出ているアドレスはSoftDeviceが管理している領域でよいだろう。
とはいえ、いくらSoftDeviceでもRAMにコードを書いて実行するとは考えづらい。

 

ということは・・・スタック不正でHardFaultしたのか?
もしかして、RAMが足りてない??
EIDでごにょごにょするということは、楕円曲線暗号の処理を行うのだろう。
それがどのくらいRAMを必要としているかは、把握していない。
スタックは4KBでやってるのだけど、さて、どうしたらよかろうか。

 

S130ではsd_ble_enable()でSoftDeviceが使用するRAMサイズを処理するようになったが、APIはsoftdevice_enable()の中で呼ぶようになったようだ。
呼んだ後の、戻り値であるble_enable_paramsを見てみよう。

image

attr_tab_sizeは、Attribute Tableのサイズだろう。
これを、SoftDeviceが使う4.9KBに加えたサイズが、実際に使用するサイズになるはず。

0x13C8 + 0x580 = 0x1948

nRF51822_xxAAはRAMが16KBだから、

0x4000 – 0x1948 = 0x26B8

9KBくらいがアプリとして使えるRAMサイズだろう。
たぶん、静的な変数の領域が足りなければリンカがエラーを出してくれるだろうし、ヒープは使わないので、スタックサイズをもっと増やせばよいはずだ。

 

いや・・・そうなのだろうか。
スタックの領域は、RAM領域の後ろからずんずん増えるだけだと思う。
静的変数の領域が足りない、というリンカのエラーは「スタックがこれだけ使うはずだから、それと重なりますよ」というエラーになるはず。
動的にスタックサイズが足りないからといって、HardFaultは発生しないんじゃないだろうか。それで発生するんだったら、コールスタックでももう少しそれっぽいアドレスになっているはず。

ということは、単純にRAMが足りなくて、スタックが静的変数の領域を侵してしまったと考えるのが妥当か。

HardFaultが発生したときのStackPointerは0x20002AF0だった。
MAPファイルを見ると、BSS領域の終わりは0x20003118だ。
うん、ダメだね。


そういうわけで、残念ながらEphemeral IDを16KBのRAMで試すのは無理そうだ。

タイマが多いせいか、それがけっこうRAMを消費しているようだ。
しかし、タイマを減らしても足りないだろう。
暗号化周りもけっこうRAMを使っている感じがする。

幸い、RAMの後ろの方に暗号化関係のメモリが配置されているようで、普通に使う分には大丈夫のようだ。
スタックも、そこまで使ってないのだろう。

2016/05/14

[nrf]nRF5 SDK for Eddystoneは動くのか? (14)

前回は、Slotのデータは変更できるようになったが、EIDを登録しようとするとError133とError8が発生した、というところまでだった。


Error133は、Characteristicが読めない、というエラー。
Error8は、接続状態の変更エラー、のようだ。
どちらもlogcatに出ているから、そうなのだろう。

133は、onCharacteristicRead()のstatusだから、nRF51822が返しているのだろう。
133=0x85で、BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPPでよいのかな?
ペアリング?

じゃあ、8は、NRF_ERROR_INVALID_STATEでよいのか。
つまり、状態が違うからエラーを出して、その状態というのはペアリングしていること、ということなのだろうか。。。。


まずはどのCharacteristicかを調べようとしたが、何回かやってみると、readもwriteも発生していた。

今見つけたのは、readで、Characteristicは「Advertising Interval」だった。
ここの3番目(7503)だ。
nRF Master Controlアプリでアクセスしても、GATT READ NOT PERMITが返ってくる。

Characteristicの説明を見ると、lockedだから、みたいなことが書かれている。
”7506”をREADすると「Locked」と出てくるから、そうなのだろう。
アプリのまねをして、”7507”に0xFFFF…FFを書込むと、Unlockedになった。
その状態で”7503”をREADすると、ちゃんと読めた。

nRF Master Controlアプリでは右上にアイコンが出てきていたので、そこをタップするとなにやらダイアログが表示された。

image

スロットとEID configurationのバインド・・・?

 

これは、CharacteristicとかAndroidアプリとかを見るのではなく、Phisical Webのしくみなどがわからないとどうしようもなくなってきたように思う。
一筋縄ではいきませんな。

[nrf]nRF5 SDK for Eddystoneは動くのか? (13)

ようやく、チュートリアルを取り除いた。
チュートリアルなのかどうかもわからないが、タイマ値を設定しているところを見ると、一定時間したら消えるつもりなのだろう。
消えない理由まで調べられるほどには、私はAndroidのことをわかってないのだった。


チュートリアル画面の下はこうなっていた。

image

このSlot0になっているスピナーの横にある鉛筆をタップすると、該当するスロットで送信するビーコンのデータを設定できるようだ。

試しに、Slot0はそのままで、Slot1にうちのサイトを登録してみた。

image

おお、ちゃんと繰り返されている。

image

http://goo.gl/0jXSXe
うん、うちのサイトにジャンプした。

このスロットごとに変わるビーコンをnRF Master Controlアプリで見ると、色違いで見えるのでちょっときれいだ。

image

 

念のため、nRF51822の電源を入れ直したが、ちゃんとスロットのデータは生きていた。
NVに保存しているのだな。


さて、Shorten URLも動作したし、スロットの設定が変更できるのもわかったのだが、アプリの「BEACONS」タブには何も表示されない。
これは、OAuth2.0のJSONデータを作っただけになっているからだろうか?

READMEのFeaturesを読むと、EIDを登録したら、と書かれているので、それもSlotに割り当てがいるのだろうか。

image

一番下に、10か15、とあるので10を打ち込むと、Error133とError8が発生した。
うーむ。。。

2016/05/13

[nrf]nRF5 SDK for Eddystoneは動くのか? (12)

さて、2回目のゴールデンウィークを迎えてしまったような感じだが、営業活動のブログ書きは続けよう。

 

今まではnRF51822だったが、Androidアプリで操作ができないとどうしようもないので、今回はそちらをやる予定だった。

が、NordicのAndroidアプリはWindowsではビルドできなかった。。。
理由は「ファイル名が長すぎるため」。
NTFSって、もうちょっと制限が緩くなったんじゃなかったっけ??
VC++の定義値からすると32768まで許可していそうなのだが、とにかくAndroid Studioは「240文字を超えたらいかん」ということで9patchの変換か何かで失敗してしまった。

ちっ。

 

そんなわけで、今回はVirtualBox上のLinuxにAndroid Studioをインストールする作業をするのでお休みだ。


メモ

VirtualBoxの準仮想化対応
http://itpro.nikkeibp.co.jp/atcl/column/14/343137/091700014/

 

iBusうんたらかんたら
http://stackoverflow.com/questions/33823742/android-studio-ibus-prior-to-1-5-11-may-cause-input-problems-see-idea-78860-f

 

あとは、ビルドさせて、BuildToolsのバージョンを合わせ、なぜか定義が足りない<string>をいくつか追加したら、とりあえずAPKとしてはできた。
https://github.com/hirokuma/Android-nRF-Beacon-for-Eddystone

 

が、これだけではダメらしい。
2つの重要なステップがある、とのこと。
何のためのステップかというと、Nearby API、Proximity API、URL Shortner APIを有効にするためのステップらしい。

というのはわかるのだが、ここのMarkDownは正しく書けてないと思う。。。
たぶん「-」が行頭に付いているのでリストにしたいのだと思うけど、スペースが入ってないからそうなっていない。

ここも「Two important steps」って書いてあるけど、この行も含めて4つリストに使用としているように見える。
そして「Next」とあるけど、これは「Next:」みたいな感じだろうか? だったら、Next、とか書かずに、1. 2. とかすればよいだけだ。
でも「Next using」で「Next Generate」と、大文字小文字が違っている。
うぅぅ。。。

 

よくわからんが、Google Developer Console Managerというところで、Nearby、Proximity、URL Shortnerの3 APIを有効にすればいいんだろう?

Google Developerのページにリンクがあったので、飛んでみた。
無料とかいう言葉が見えるので、お金がいるパターンもあるのだろうか。。
まあ、ぎりぎりまでやってみよう。

まず、Nearbyを検索。
プロジェクトがいるということで、適当に作る。
作って、有効にすると、「認証情報を作成せよ」と言われる。
これがREADMEに書いてあった「in credentials」か。

image

クリックすると進んで、こうなった。

image

これがREADMEに書いてあった、debug keystoreだのSHA1だのか。
このコマンドを打っても「mystore.keystoreなんてないよ」と言われる。
debug.keystoreは、~/.android/debug.keystoreにあった。パスワードもそのリンクにあったので助かった。でも、空パスワードでもSHA1は見えるみたい。

そうすると、キーが出てくる。
これをAndroidManifest.xmlに反映させるらしいが。。。ああ「YOUR_API_KEY_GOES_HERE」と書いてあるので、そこに書けばよいのだろう。

URL Shortnerも同じようにして作ろうとしたが「アクセスするデータの種類」の選択がいる。
ユーザーデータにすると、OAuth2.0クライアントIDの作成になった。
これがREADMEに書いてあったやつなのか?
よくわからんが、JSONでーただった。

さて、AndroidキーとAndroidクライアントが1つずつできた。
AndroidManifest.xmlにはURL Shortnerのキーも入力するようになっているが、同じものでよいのかな?

AndroidManifest.xmlは間違ってコミットしてしまいそうだけど、除外しておかねば。
こちらを参考に、imlファイルなんかも対象外にしておいた。
既に git 管理しているファイルをあえて無視したい - Qiita

 

で、ここまではいいとして、それからどうするとよいのだろう?
キーはまだ書込んだからよさそうだとして、OAuthクライアントIDなんてどこで使ったらよいのだか。。

とりあえずビルドして動かしてみると、キーを書く前は出ていたエラーが出なくなった。
よくわからんが、困ってから調べることにしよう。

次は消えないチュートリアル画面だが、疲れたので次回だ。

[nrf]nRF5 SDK for Eddystoneは動くのか? (11)

NordicのAndroid Eddystoneアプリを動かすと、登録タブがあって、そこに「ボタンを押せ」みたいなことが書かれている。
ボタンがないとダメなようだ。

そういうわけで、GPIOのP0.02にボタンを割り当てた。
Active LOWで、プルアップ抵抗は内蔵。
だから、ピンとボタンの片方は直結し、ボタンのもう片方はGNDにつなぐだけ。
https://github.com/hirokuma/nrf5-sdk-for-eddystone
別のピンに割り当てたかったら、この辺を2から変更しておくれ。

 

これで動かすと、起動時のビーコンが普通のEddystone-URLになった。
そうか、起動時にボタンを押したのと同じ動作にしていたから変なビーコンだったのか。

登録タブの方でCONNECTを押し、nRF51822のボタンを押すとこうなる。

image

Eddystoneのビーコンは接続できないタイプなのだが、ボタンを押すと接続できるタイプに切り替わるのだ。

 

これで出てきた名前をタップすると、こうなる。

image

よくわからんので、そのままUNLOCKをタップ。

 

image

こんなのが出てきて、一番上の「Slot information」をタップするとこうなる。

image

 

なるほど、だからURLだけしかビーコンで出てこないのか。


この辺はよいのだが、Androidアプリがどうにもうまく動かない。

初回はチュートリアルのために説明画面が出てくるのだが、これがどうやっても消えない。。。
だから、下にあるボタンなどをタップしたくても押せないのだ。

今回撮影したスクリーンショットも、チュートリアルが表示される一瞬前に画面をタップして押せたときの例だ。
これは、OSのバージョン違いなのかなぁ。

それと、ボタンを押して登録できるビーコンを出しているときも、Eddystoneのパケットとしては不正確(Eddystone-URLのURL部分がない)なためか、裏でアプリが異常終了してしまっている。
誰だかわからないけど、Chromeとかだろうか。

 

そんな感じで、何だか進んでいるのかどうかよくわからないことになってきた。

2016/05/12

[nrf]nRF5 SDK for Eddystoneは動くのか? (10)

なんか出るようになったと思う。

image

SESだと無理やり省略する処理がいらないので、ここまで持ってくるのはそこまで大変じゃなかった。
けれども、KeilだとServiceDataの中身まで出力されていたから、そこまではこぎ着けていない。

https://github.com/hirokuma/nrf5-sdk-for-eddystone

 

あれ・・・放置していると、それっぽいデータが出てきた。

image

 

Nexus5で眺めると、ピクト・・・というのか知らんが、あの領域にEddystoneのアイコンが出てきた。

image

広げる。

image

タップする。

image

有効にするをタップして、しばらく待つと・・

image

 

惜しい。
でも、Chromeが反応することはわかった。

 

Advertisingしていたデータは、こうなっている。
URL先のページはあるのだが、リゾルバとかそういう登録をやっていないから進めなかったのか。

image

AndroidのEddystoneアプリを起動すると、GoogleのもNordicのも、Googleアカウントと紐付けようとしていたのだ。
何かありそうだ。

そして・・・ピクトが出たのは最初だけで、それから反応しなくなってしまった。
スクリーンショットを撮っててよかった。

2016/05/11

[nrf]nRF5 SDK for Eddystoneは動くのか? (9) - SES

Keilは、あきらめた。
では、次はどうするか?

GCC + Makefileにしようかと考えていたのだが、Nordic githubのnRF5 SDK for Eddysbtboneを見ると、Embedded Studio版のプロジェクトが入っていた。

Embedded StudioはSEGGERの製品で、略称はSESだ。
eclipseベースかと思わせるが、そうではない。
マルチプラットフォームだから、何かそういうのがあるのかもしれない。

Cortex-M版だと、998ユーロ。
今だと、12.4万円くらい。
IARがいくらくらいなのかわからないけど、なんとなく値段としては、Keil > IAR > SES、になりそうな気がする。

評価だったり、利益目的じゃない教育用だったらFree版を使ってもよいようなので、今回はそれを使おう。
やっぱり、個人だと有償の開発環境は選択しづらいですわ。


まず今日は、ビルドできるところまで確認した。
ブランチは新しく「nrf51_ses」を作った。
https://github.com/hirokuma/nrf5-sdk-for-eddystone

 

ポイントは、やはりSESだ。
設定の仕方がよくわからなかったのだが、これはEddystoneのREADME.mdに手順が書かれていた。
これと、Nordicのdevzone blogの記事をあわせて読むと、なんとなくわかると思う。

私は、Keilのときと同じく、nRF5 SDK v11.0の中のexamples/ble_peripheralの中にnrf5-sdk-for-eddystoneをcloneしたのだけど、SESプロジェクトではそれだとRTTのパスが合わなかったので、変更した。
そういう、ちまちました違いしかコミットしていない。

うちのREADME.mdは、一番下に私のメモを書いているので、気がついたことは記載していこう。

2016/05/10

[nrf]nRF5 SDK for Eddystoneは動くのか? (8) - 挫折

NordicのnRF5 SDK for Eddystoneが更新されていたので、マージした。

image

35,248バイト!
2.5KBも増えたのかぁぁぁぁぁ。。。

 

どこかのデバッグ用オプションが有効になったりしたのがあるかもしれないし、サイズを削り損なっただけかもしれない。

だが、それよりも、新しくコミットされるたびにこういう作業をやるのは、さすがに疲れてしまった。
挫折というか、力尽きた。

4月の新人さん特集みたいな気持ちで、GUIツールでちゃっちゃっとビルドして焼くだけで動き、あとは自分でカスタマイズして遊ぼう、みたいなところを目指していたのだがなぁ。

GCCだと、環境を作るところに力を使うので、そこで嫌になってしまう人が出てくるかもしれない。
だいたい、製品のKeilなんて40万円くらいしたと思うから、それを普通の人は持ってないと思うのだよ。
STM32F0みたいに、シリアル番号を公開して「好きなだけ使いたまえ」となるとうれしいのだがねぇ。

 

残念だが、Keil(32KB制限版)でnRF5 SDK for Eddystoneを動かすのはあきらめよう。

[nrf]nRF Connect v1.0

Nordicのブログに、ツールが追加された記事が載っていた。

nRF Connect v1.0 Release Candidate

RC版だが、これは一体何だろうか?
取りあえずインストールしてみたのだが・・・COMポートというかシリアルポートというか、とにかくそれがないとどうしようもないことがわかった。

サポートしているのは、pca10028, 10031, 10040と、nRF5x DKシリーズだ。
日本だと、nRF5x DKは技適が取れていないように思う。

うーん、UARTなのだから、どのボードでもよさそうではあるのだけど、プロトコルがわからんし、自分でプロトコルを組み込む気力も無い。
互換ボードはないだろうか・・・。

 

Switch Science mbed TY51822r3 | mbed
ここを読むと、メインクロックが32MHzであること以外はnRF51-DK互換だ、と書かれている。

Switch Science mbed TY51822r3 - スイッチサイエンス
こっちは、HRM1017やnRF51-DKと違ってメインクロックが32MHzだ、と書かれている。

何というか、

  • これはできませんが、これはできます
  • これはできますが、これはできません

みたいな感じを受けてしまった。

だいたいnRF51-DKなんかは、ボタンが4つ、LEDも4つあって、それぞれ意味があるはずだ(bspのソースを見た限りでは)。

PDFによると、こうだ。

image

image

 

FirmwareはHEXファイルしかないので、周辺装置を合わせないといけない。
だが、ボタンとLED、UARTさえ合わせてしまえばなんとかなるんじゃ無かろうか?

あっ。。。うちのnRF51822ボードは内蔵クロックを使っているんだった。。。
TY51822r3は32MHzの外付けだから、32M XOSCか。電気特性が違うだけで、アプリ側は気にしなくていいのかな? 理由はわからないが、32MHzの方が16MHzより電力の消費が小さいようだ。

じゃあ買ってみるか?というと、うーん、そこまでしてねぇ、という気持ちだ。
nRF52832だったらまだしも、今からnRF51822をこれだけのために買うのは、懐が許さないところだ。

2016/05/08

[nrf]nRF5 SDK for Eddystoneは動くのか? (7)

最近っぽいC言語もやりたいが、それだけやってるわけにも行かない。
Eddystoneの続きもやろう。


前回は、Eddystoneのソースを新しくして、自分が作ったところをマージするとAdvertisingで何か出ているのがわかったところまでだった。

ただ、Advertisingで何のデータが出ているのか、いや、そもそも何をしようとしているサンプルなのかがわかっていない。

そういうわけで、Eddystoneの仕様を読んでいたのだが、新しく追加されているところを読んでいる途中で力尽きた。


先に、前回の最後に送信したAdvertisingがどういうデータなのか確認しておこう。

image

最初の3バイトが<<Flags>>、次の4バイトが<<Complete List>>、次の18バイトは<<Service Data>>なのだが、FrameTypeが0x00なのでEddystone-UIDと思われる。

まあ、<<Service Data>>の中身を設定しないままになったEddystone-URL、という可能性もなくはないが、それならデータ長はもっと短くてよいはず。

なので、たぶんUIDの初期値がどうなっているかを見ていけば、とりあえずはまともなデータになるだろう。
でも、これだけだったらiBeaconサンプルと同じで、固定データを流すのとあまり変わらないので、面白味がない。


続いて、Eddystoneの新しい仕様。

 

新しく追加されたのは、Ephemeral-IDのところ。
略すとEIDなのだが、これだとEddystone-IDの略と思われても仕方が無いと思う。
EIDの仕様が関係するのは、以下の2箇所。

  • フレームタイプが「TLM」で、それがEncrypted TLMの場合
  • フレームタイプが「EID」の場合

 

Encrypted TLM(以下、ETLM)は、今までのTLM(Unencrypted TLM)のデータをAES-EAXで符号化したデータ+αをAdvertisingする。
AESは128とか256みたいなデータ長がついたものしか知らなかったのだが、EAXというモードがあるらしい。
詳しくないのでEAXのことは調べないが、Eddystone-EIDで使うのと同じようなパラメータを使ってnonce値を生成し、TLMデータをAES-EAXで符号化する、ということになっている。

 

ではEddystone-EIDを読むか、と読み始めたのだが、だんだんと面倒になってきた。
作り方自体はそれほど面倒ではなく、

  1. あるルールで作った値をIDキーでAES128符号化してテンポラリキーを生成
  2. あるルールで作った値をテンポラリキーでAES128符号化して上位8バイトだけ使う

となっている。

そこまではまだよかったのだが、次に「EID configuration」という章が出てきて、リゾルバだの登録だのと言う言葉が現れ、だんだんと「BLE Peripheralがビーコンを勝手に出しておけばいいや」という話ではないということに気付いた。
Physical Webとかが関係しそうだ。

先はまだ長いな。

2016/05/06

[c/c++]C99とかC11とか

私がお仕事でC言語を触ったときは、C89よりも前の仕様だったと思う。
あまり覚えてないけど、void型がなかったりとか、structの変数を直接返したりできないとかではなかったかなぁ。
まだ「C言語はmain関数から始まる」と思っていた時期だったので、いろいろ勉強になった。

なったが、知識が古臭いのは否定できない。。。
さすがに今は、C89くらいの仕様で作っていると思っている。
思っているけど、自信はないですな。


「最近っぽいコードを書きたい」と思うからには、戦略というかコードの作りだけでなく、戦術というかコード本体もある程度は新しくした方がよいのではなかろうか。

C言語で言えば、C99かC11がそれに当たりそうだ。
C++だとC14++があるけど、Cの方はC11までのようだ。
でも、C11はまだ5年くらいしか経っていなくて早い気がする。
だから、C99にしよう。
もしかすると、値段が3種類あると真ん中を選びたくなる、というだけかもしれないが、まあいいや。

 

と、軽くC99と書いたものの、知らないものがたくさんある。
それに、コンパイラ自体も新しくなってきているので、たとえば「#pragma once」をサポートしているコンパイラが多いとかも、さっき調べて知ったくらいだ(VC++の独自拡張と思ってた)。

 

まあ、何でもかんでも新しいものにすると気持ちが悪いので、気に入ったところだけ書き換えていって、あとは環境に合わせていくことになるだろう。

[c/c++]ポインタ変数のconst判定

ポインタ変数は、こんなのだ。

char *pStr;

constにするときは、だいたいこうだ。

const char *pStr;

私がconstなポインタ変数にしたいのは、だいたい関数の引数とか、ダブルクォーテーションでくくった文字列とかで、ROM上に置いたデータを参照するだけなので間違って書き換える処理を書いてしまわないようにしたい、という気持ちだ。

ただ、他の人のソースだと、こういうのを使う人もいる。

char * const pStr;
char const* pStr;

あー、変数への代入不可か、アドレス先への代入不可のどっちかだろうとはわかるのだが、見慣れない書き方をされると動揺してしまう。
まあ、コンパイルしてみればすぐにわかるのだけどね。。。

 

急に、VisualStudio2015のC#でツールを作ってみたくなった。

https://drive.google.com/open?id=0B2_3hJpJ5Ui2LUYyUlBRZ203ams

image

わざわざツールにするくらいだから、すごいことをやっているのかと思われそうだが、そういうのは無い。

structとかenumがあったらダメだし、変数名が入っていてもダメ。
ポインタも1つ分までだ。
作ってる最後の方には、我ながらなぜ作り始めようと思ったのかすらわからなくなったくらいだが、まあいいや。

[c/c++]最近っぽいコードを書けるようになりたい

休みなので、ぐだぐだしていた。
いや、普段からぐだぐだしてるのかもしれないが、そこは忘れてくれ。

どういう経緯か忘れたけど、たぶん私が公開しているNFCライブラリを見てくださった方を見つけた。
このライブラリだと思う。ありがたや。
https://github.com/hirokuma/libhknfcrw_c

 

あ、と思ったのが、こちら。

https://twitter.com/rivarten/status/700385332777193474?lang=ja
image

これは「ごめんなさい!」と思った。
どういう風になっているかというと、static変数がべたべたと確保してあって、各関数はそれを直接アクセスしているのだ。
だから複数向けにしたかったら、まずはこの変数たちを何とかしてやらんといかんのだ。

 

いや、これを読んだ当初は、「あー、私は組み込み屋さんだから、最小限に仕上げたかったんですよー」と心の中で思っていたのだ。

どうせR/Wは1つしか持っていなかったし。
複数考慮するとその分の動作が遅くなるし、メモリも増えがちになるから、もういいことにしておいた。
当時取り組んでいた仕事が、関数コールしてよいシーンとよくないシーンが発生するような動作クロックで、ROMもぎちぎちなプロジェクトだったので、その影響が強く出ていたのは否定しない。

 

しかし・・・いろいろ考えると、そういうものでもないということに気付いてきた。
最近はROMも多いし、RAMも多い。
動作クロックもかなり速い。
なにより、作ったライブラリが省電力対応していないので、自分の言葉に説得力が無くてねぇ。。。

 

まあ、このときは、ライブラリとして仕立てるよりも、「どうやったらRC-S620/Sは制御できるの?」が先だったので、うん、ごめんなさい、というところだ。


これとは別に、仕事でC++の単体テストをしようとした。
そのときにテストスイートを使えば簡単にできるのだろうと思っていたのだけど、そうそう簡単にはいかず、その方法はあきらめてしまった。

 

この2件が近い時期だったので、ちょっとこれじゃまずいんじゃなかろうか、と思うようになってきた。
ツールを使ったりとか、ライブラリを使ったりとか、そういうところは新しいものを取り入れていたのだが、コーディングの技術がそれに追いついていないと言うことに気付いたのだ。

C/C++は枯れてきてて、特に組み込み向けなんて昔の知識にちょろちょろっと新しいのを加えれば済むだろうなどと甘いことを思っていたが、ちゃんと腰を据えて勉強し直すというか、最近の状況に合わせていかないとねぇ。
新しい酒は新しい革袋に、というやつだ。


モダンC言語プログラミング

この本が、よく出てきていたので、買ってみた。
まだ「C言語とオブジェクト指向」しか読んでないけど、途中までは「うんうん」と思っていたが、だんだん「うっ、ここまでやるの?」となってしまった。
まあ、何事も例に過ぎないのだけど、ここまでやれるというのは参考にすべきだろう。

 

長いこと分野が近いコーディングをしてきて、あまり失敗がなくなっていると、それが正しい、と思い込んでいることがあるので、謙虚になるところから始めねばなるまい。

↑↑↑
というのを文字にして自分に読ませないと、私は頑固な方だから、なかなか思い込むことができないのだ。
ときどきくどくなるかもしれんが、すまんな。

2016/05/02

[androidstudio]AndroidStudio 1.5から2.1にする

したくなかったのだが、PCを新しくしたし、今から1.5を探してインストールするのもメリットがすくなさそうなので、Android Studio2.1用のプロジェクトに変更することにした。


前の環境はまったく取り込まず、作ったプロジェクトだけ持ってくることにした。
プロジェクトを開くとSyncエラーが出る。

 

今回私が賢かったのは、プロジェクトをgitで管理していたことだ。
なんでもいいのだけど、だいたいAndroidでなにか作るときは使い捨てのアプリが多いので、何も管理していなかったのだ。
バージョン管理していれば、少なくとも「元に戻せない」ということだけはなくなる。
うん、当たり前やん、と言われそうなのだが。。。

 

そしてようやく気付いたのだが、AndroidStudioのエラー修正提案に従っていくと、app/build.gradleじゃなくて、./build.gradleの方を変更してしまうようだ。
「buildToolsVersion」が新しくなっていたのだが、「バージョンが変わっている」というところまでは見抜いてくれたものの、その提案通りに修正すると、build.gradleの方に項目を追加していた。

  • app/build.gradle
    • buildToolsVersionを現状に合わせる
    • compile 'com.android.support:appcompat-v7:x.x.x'を現状に合わせる
    • compile 'com.android.support:design:x.x.0'を現状に合わせる
  • gradle/wrapper/gradle-wrapper.propertiesをgradle-2.10-all.zipにする

このくらいの変更でいいのかな?

2016/05/01

[nrf]nRF5 SDK for Eddystoneは動くのか? (6)

そろそろgithubで管理しようと思い、Nordicのところからforkしてみた。
すると、ソースが新しくなっているではないか。。。
それを使うと、またAdvertisingがうまくいかなくなっていた。

 

https://github.com/hirokuma/nrf5-sdk-for-eddystone
ブランチは「nrf51」にした。

image

なぜか知らんが、AdvDataが出てきた。
何もしてないから、新しくなったことで何か変わったのかも。
ただ、ゼロが多いから、なんかうまくいっていない感じはする。

[nrf]nRF5 SDK for Eddystoneは動くのか? (5)

第1部は、わしの負けじゃ。。。

image

なんとかADVは出るようになったものの、ROMサイズを小さくするために削ったところが影響して、中身がなくなってしまったようだ。

Serviceを捨ててサイズを減らそうとしていたのだが、Serviceの初期化に使っている値をAdvertisingの初期化にも使っているみたいで、中身を見ずに切り捨ててしまうとこうなったのだ。

減らしたいのは700バイト程度なのだが、少々じゃ減らせない。
GCCでやってしまいたいけど、今回は「なるべくKeilでやる」という縛りを付けてしまったからなぁ。

 

まあ、第2部でがんばりますかね。
第1部は、AdvertisingがnRF51822で出せるようになるまで。
第2部は、新しいEddystoneっぽくAdvertisingするところまで、という目標だけど、はてさてどうなることやら。