ページ

2014/10/25

[nrf51]nRF51初期化のまとめ方

advertising_init()で、デバイス名があるだのないだの、あるならshortだのcompleteだの、ということを書いた。

しかし、だ。
そのデバイス名の設定は、gap_params_init()で行っているのだ。

    leds_init();
    timers_init();
    gpiote_init();
    buttons_init();
    scheduler_init();
    ble_stack_init();
    gap_params_init();
    services_init();
    advertising_init();
    conn_params_init();
    sec_params_init();

遠すぎやしないかい?

また、advertising_init()ではサービスのUUID設定も行っている。
SCANのRESPONSEにいるんだけど、なんかそうなるとservices_init()が寂しく感じる。

この辺の初期化は、ble_stack_init()でまとめてしまっても良いのではないだろうか。
まとめた方がというか、まとめないと訳がわからなくなってしまいそうな感じがする。
あんまり1関数のステップ数が多くなると見通しが悪くなるのはわかるけど、わかりやすくなるんだったら1万行あっても1関数にまとめてしまっていいんじゃないの、って思ってる。

 

nRF51822は、Cortex-M0が搭載されたチップ、というだけの目的で使うこともできる。
が、BLEを使う前提でないとこのチップは使わないだろう。
ならば、BLEを使うように書いた方がよいのだと思う。
そして、それを自分で行うために、時間をかけてソースを眺めているのである。

2014/10/23

[nrf51]BLE_ADVDATA_FULL_NAMEとはなんぞや

nRF51822サンプルを読み進めているが、ようやくBLEにたどり着いた。
まずは、Advertisingだ。


ble_advdata_set()を使って初期化するのだが、何をやってるのかよくわからない。
nRF51 SDKのHTMLドキュメントでは、右上の検索ボックスでもひっかからない。doxygenコメントは付いているのに・・・。

第1引数も第2引数もble_advdata_tのポインタを渡す。
最初がadvertisingのデータ、次がscan responseのデータ。
やってることは、第1引数がNULLでなければ、チェックしてエンコード。第2引数がNULLでなければ、チェックしてエンコード。エンコードした結果を使ってsd_ble_gap_adv_data_set()を呼び出す。

つまり、sd_ble_gap_adv_data_set()が本当にやりたい内容なんだけど、使うのが面倒だろうからということでラッパというか便利関数が用意されているというところだろう。


便利関数は良いとして、どういう値を入れるとどうなるのかは把握しておきたい。

いきなりつまずいたのが、これ。

advdata.name_type = BLE_ADVDATA_FULL_NAME;

なにがフルネームなんだろう?
enumで、他にNO_NAMEとSHORT_NAMEがあった。

調べたところ、AD Typeの、0x08 : <<Shortened Local Name>>か、0x09 : <<Complete Local Name>>に変換されるようだ。
ルールはいくつかあるのだが、基本的にはSHORT_NAMEならShortened Local Nameに、FULL_NAMEならComplete Local Nameに変換される。
むかし、PaSoRiが出すAdvertisingデータを眺めたことがあった
BLE機器を探すときに出てくる名前が、この名前になるということのようだ。

 

「ルールはいくつかある」と書いたが、これは名前をエンコードするときに、FULL_NAME指定しているけどAdvertisingパケットに載らないサイズになったら、勝手に切り詰めて短くしますよ、という作りになっているからだ。
詳細は、ble_advdata.hのble_advdata_set()コメントを読むが良かろう。

2014/10/21

[android]Lは2つ!

LOLIPOP、じゃなくて、LOLLIPOP、なのね。。。
みんなも注意しよう!

2014/10/20

[android]LollipopからSmart Lockという機能が付いたらしい

Android 5.0(になるのかな)から、ロックの解除にNFCタグも使えるらしい。
http://getnews.jp/archives/685243
試しておこう。

まず、設定画面>セキュリティで、ロック方法を設定する。
私はいつもパターン入力しているので、それを設定した。
そうすると、設定できる項目がいろいろ現れ、その中に「Smart Lock」がある。
image
Nexus7なので、画面が大きくて済まんね・・・。
とにかく、こういう画面が出てくるので、赤いプラスをタップ。

image
Bluetoothか、さもなくばNFCかの選択を迫られる。
私はNFCなので、下をタップ。

image
タップを促す画面が表示される。

image
タグが見つかると、名前入力する画面になる。

image
おしまい。
複数の登録が可能だ。

では、使い方。
まず、ロックして画面が消えている状態では、何もならない。
これは今まで通りだ。
電源ボタンを押してロック画面を表示させ、かざしてみた。
・・・変化がない・・・・・・。
パターン入力画面になってからかざすのか?
・・それでも変化がない。
なんだ???
正解は、「ロック画面でタップしてから、画面をスワイプ」だ。
そうすると、パターン入力画面が出てこずにホーム画面が出てきた。
ロックが外れる音がするわけじゃないので、気付かんかったわ。。。
何回かやってわかったけど、タグを読めなかったときの音はするみたいだ。
そういえばHCEはロック画面でも使えるような設定があったから、そっちなのかな?

パターンよりも、すごく複雑なパスワードとかPINにしておいて、ほとんど記憶での入力ができないようにしておき、普段はNFCタグを使うとかがよいのかなぁ。
あるいは、外では電話専用にするために、タグは家の中に固定しておくとか。

2014/10/19

[nrf51]softdevice_sys_evt_handler_set()は、何だ? - (3)

ちょっと追った。

softdevice_sys_evt_handler_set()は、sd_common/softdevice_handler.cにある。
これは、m_sys_evt_handlerという変数に覚えるだけ。

使っているのは、intern_softdevice_events_execute()だけ。
これの呼び出し元は、SWI2_IRQHandler()。
名前からすると、ソフトウェア割り込みのハンドラだろう。
スケジューラの関数が登録されていればそちらを呼び、登録されていなければintern_softdevice_events_execute()を呼ぶ。

ここでいうスケジューラの関数は、SOFTDEVICE_HANDLER_INIT()でスケジューラを使うと指定すると、自動的に割り当てている。
softdevice_evt_schedule()という関数で、やっているのはapp_sched_event_put()でスケジューラに登録するだけ。
登録するのは関数呼び出しで、結局はintern_softdevice_events_execute()を呼ぶようにしている。
私のイメージだと、とりあえず発生したイベントだけは吸い上げて、それをスケジューラに登録するんだろうと思ったんだけど、そうではないんだな。

intern_softdevice_events_execute()では、SoftDeviceからのイベントとBLEスタックからのイベントの両方をさばいている。
SoftDeviceの方は必ず処理するが、BLEスタックはBLE_STACK_SUPPORT_REQDが定義されているときだけだ。
softdevice_sys_evt_handler_set()は引数がNULLの場合には処理されないので、それが"Once the application has registered for the events, it is not possible to possible to cancel the registration"と説明している意味だろう。

 

さて、最初の疑問に戻ろう。
「なんでBLEスタック初期化の中で呼び出しているの?」だ。
関数コメントを信じるなら、SWI2_IRQHandler()はBLEスタックイベントの割込ハンドラらしい。
だから、ble_stack_init()でしか呼び出さないということか。

じゃあ、なんでBLEスタックイベントの割込とSoftDeviceのイベントが一緒になってるんだ?
また、SoftDeviceイベントというのは、sd_evt_get()で取得しているので、enum NRF_SOC_EVTSみたいなのだ。
これはNRF_EVT_FLASH_OPERATION_SUCCESSみたいな定義があることから、必ずしも異常発生だけとは限っていない。

あまり考えても仕方ないから、こんな感じになるだろうか。

  • BLEを使うなら、softdevice_sys_evt_handler_set()でコールバック関数を設定した方がよい。
  • FLASH操作するなら、その処理結果がコールバックされるようである。
  • なので、必ずエラー処理にするのではなく、内容によりけり。

 

現在までで整理した内容を、githubにプッシュした。
残るは、main.cのBLE周りですな。
https://github.com/hirokuma/nrf51822_templete