概要
nrf51822 上で起動時間を取得するために RTC (RealTimeClock) の仕組みを使ってみました
RTC の値はデバイスの電源の ON/OFF でリセットされる値になります
環境
- Windows7 64bit
- nRF51822
- nRF51 DK
- nRF51 SDK 9.0.0
実装方法
nRF51 DK に含まれる App Timer (以下タイマー) という機能を使って実現します
nRF51 SDK に含まれているサンプルを見るといろいろなサンプルでこのタイマーを使っているので基本はそれをベースにすれば OK です
今回はバッテリーレベル用のタイマーを定義して、それを例に
流れを説明していきます
初期化
まず、タイマーを使うために APP_TIMER_INIT
というマクロをコールする必要があります
サンプルではだいたいこんな感じで実装されていると思います
APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, false);
基本はこれで問題ないです
タイマーの生成
次にタイマーを生成します
生成するには app_timer_create
をコールします
uint32_t err_code;
err_code = app_timer_create(&m_battery_timer_id, APP_TIMER_MODE_REPEATED, battery_level_meas_timeout_handler);
APP_ERROR_CHECK(err_code);
static app_timer_id_t m_battery_timer_id;
app_timer_id_t
は typedef されている型で実体は uint32_t になります
この ID に対するタイマーを生成していることになります
また、 battery_level_meas_timeout_handler
ですがこれは関数になっており、タイマーがタイムアウトしたときにコールされる関数を指定できます
この辺もサンプルを見ると流れが把握できると思いますが、この関数内でバッテリーレベルの再取得を実施し Characteristics の value の更新を行っています
タイマーが生成できたらタイマーをスタートします
タイマーを開始する
タイマーを開始するには app_timer_start
をコールします
uint32_t err_code;
err_code = app_timer_start(m_battery_timer_id, BATTERY_LEVEL_MEAS_INTERVAL, NULL);
APP_ERROR_CHECK(err_code);
これをコールしたタイミングから RTC によるカウントが開始されます
現在のカウントを取得する
タイマーを開始したら、現在のカウントを取得してみます
現在のカウントを取得するには app_timer_cnt_get
をコールします
uint32_t p_ticks;
app_timer_cnt_get(&p_ticks);
printf("%d \r\n", p_ticks);
こんな感じでカウントしている値を取得できます
ここでちょっとはまったのは app_timer_cnt_get
の返り値を参照してもずっと 0 でした
リファレンスを見たのですが、この関数の返り値は正常に取得できたかのフラグを return しているだけなので常に 0 が返っていました
関数側では、受け取った引数のポインタに対して書き込みを行っているので、引数として渡した変数を参照する必要がありました
で実際にこの値を定期的に出力してみたのですが、値を見ると 1, 2, 3, … のような秒数を刻む値ではなく 3256, 6785, 125678, … のようにガンガン値が増えていました
ちょっとこの値に説明します
カウント値について
以下もしかすると、間違いがあるかもしれません
この値について目視でどの程度増えているのか計測してみたのですが、だいたい 30 秒で 1,000,000 カウント増えている感じでした
なので 1 秒間で約 33,000 ほど増えていることになります
何かそれっぽい値を定義している箇所がないか調べてみたのですが、APP_TIMER_CLOCK_FREQ というマクロが定義されておりこの値が 32768 になっていました
おそらくですが 1 秒間にこの APP_TIMER_CLOCK_FREQ の値だけ増加しており、app_timer_cnt_get
ではそれが取得できているのだと思います
なので、時間を取得したいのであれば、取得した値を APP_TIMER_CLOCK_FREQ で割り算すればそれっぽい起動時間が取得できると思います
また、値の最大値なのですが、約 16, 800,000 くらいになるとまた 0 にリセットされてカウントが始まりました
( 16, 800, 000 / 33,000 = 510 (sec) = 8 min 30 sec )
なので何回リセットされたかどうかも管理しないとダメそうな感じです
最大値を伸ばす方法とリセットされた回数を取得できる方法があるかどうかは、すいません、調査しきれていません、、、
ちょっとこの辺が曖昧な記載なのは、そこまで深く調べていないので自信がないためです
間違いがや追加の情報あればご指摘いただけると助かります
最後に
とりあえず nrf51822 で起動時間っぽい値を取得できるようになりました
完全に使うためにはもう少し実装が必要そうですが、ベースとなる呼び出し方は理解できたと思います
10分くらいでリセットされるタイマーだとちょっと管理が大変なので、半日分くらいは管理できるようにしたいなと思っています