Geekleboard

Geekな奴がハード開発に関する情報を発信中

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が公開しているサンプルコードをぺたっと貼り付けておきます。(上記説明文のテストコードとは若干異なる)