BLE nRF51822でFlashを使う
nRF51822でデータの永続化をしたくなった場合はpstorageを使うのが正解らしい。
pstorageはFlashアクセスのマネージメントをしてくれる仕組みの様子。
サンプルのソースコードはここ
How can i write 10kB of data to internal flash? - Nordic Developer Zone
なぜpstorageを使うのか?
NVRAMやflashに関するサンプルコードを探すと以下の2つが見つかる
・Source/nrf_nvmc/nrf_nvmc.c
・Source/ble/ble_flash.c
この2つを使うことはあまり推奨されていない。
なぜならこれらコードはSoftDeviceのスケジュール管理を考慮した設計にはなっていないから。
flashはerase/writeに時間がかかるためSoftDeviceのシビアなスケジュールと相性が悪く
- nrf_nvmc.cはそのあたり全く考慮されていない→使った場合おそらくSoftDeviceがこける
- ble_flash.cも一応はそのあたり配慮があるが、結局SoftDeviceをDisableしないと確実にアクセスできない
といった不都合がある。
その点、pstorageはBLEアクセスとFlashアクセスのイベントスケジュール管理をする前提の設計となっているためpstorageが推奨されている、というわけ。
pstorageとはなにか?
nRF51 SDK - S110 SoftDevice: Persistent Storage Manager
特徴をまとめると
- 以下の関数でFlashへアクセスができる
pstorage_store : 書き込み(書き込み前に必ずその領域がクリアされている必要がある)
pstorage_update : 書き込み(クリアして書き込みをしてくれる)
pstorage_load : 読み込み
pstorage_clear : クリア - Flashの先頭アドレスを計算する必要なし
- IDで書き込み領域を区別することができる(インスタンス生成するようなことができる)
- 各領域でブロックサイズ、ブロック数を指定できる
- BLEタスクの邪魔をしないようシステムコールバックに対応
このあたりの設計は非常に勉強になる。
これらふまえて、以下組込み方法。
動作環境
MDK-ARM uVision 4.0
SoftDevice 6.0.0
nrf51 SDK ver.5.2
pstorageを組み込む
まず、システムイベントの登録。BLEタスクとpstorageタスクの切替に使う。
sys_evt_dispatch で pstorage へシステムイベント発生時のイベントを登録。
BLEタスクとアプリケーションタスクの切替にはapp_schedulerを使う。
その場合、事前にスケジュールキューなどの領域が必要なので確保しておく。
おそらくこのapp_schedulerを使うことでpstorageのイベントコールバックが発生する仕組み。
store/update/clear完了のウェイト用にコールバック関数を用意しておく。
で、ようやく本題のコード。
main関数にはscheduler_init()やテストコード用関数を入れておく。
以上のコードを入れ込めばブレークポイントを張ってテストはできると思います。
注意点
SoftDeviceのコールバック中(BLE通信の処理中)には sys_evt_dispatch が呼ばれない。
つまり flash_cb_handler が呼ばれないので注意が必要。
例えばBLEからデータを受け取るコールバック関数内で while(pstorage_wait_flag) { power_manage(); } とするとデッドロックとなる。ループ内かタイマー関数内に記述するのが正解。
Nordicのサンプルコード
最後に、参考にNordicが公開しているサンプルコードをぺたっと貼り付けておきます。(上記説明文のテストコードとは若干異なる)