Nordic Semiconductor の nRF54L15 チップは、革新的なグローバルリアルタイムカウンタ(Global Real-Time Counter, GRTC)外設を搭載し、低消費電力アプリケーションにおける時間管理に優れたソリューションを提供しています。この記事では、GRTC の技術的特徴とその利点について詳しく解説します。
GRTC の主要な技術的特徴
全パワーモードでのサポート GRTC の最大の特長は、さまざまなパワーモードでの継続的な可用性です。システムがフルスピードで動作している場合(16MHz 高速クロックを使用)、または低消費電力モードや完全にシャットダウンしている場合(自動的に 32.768kHz クロックに切り替わる)でも、GRTC は正確な時間計測を維持します。このシームレスな切り替えメカニズムにより、システムがどのような状態であっても正確な時間基準を維持することができます。
超高精度と長い計測範囲 52ビットのカウンタ幅と1マイクロ秒の分解能を持つ GRTC は、驚異的な計測能力を持っています。理論上、カウンタのオーバーフローが発生するまでには約142年かかります。この特性は、長期的なデータ記録やイベント追跡が必要なアプリケーションに特に適しています。
消費電力最適化設計 低消費電力モードで 32.768kHz クロックを使用することで、基本的な精度を保ちつつ消費電力を大幅に削減できます。この二つのクロック源のスマートな切り替えメカニズムは、高精度な時間計測と超低消費電力のバランスを理想的に保ち、バッテリー駆動のIoTデバイスにとって理想的な時間管理ソリューションを提供します。
GRTC の適用例
産業用IoT(IIoT) 産業環境では、デバイスは長期間連続して動作し、イベントのタイムスタンプを正確に記録する必要があります。GRTC の長い計測範囲と全モードでの可用性は、産業センサーノードや遠隔監視デバイスに最適です。
医療デバイス ウェアラブル医療デバイスやインプラント型健康監視システムでは、正確な時間計測と低消費電力が重要な要件です。GRTC は、頻繁にバッテリーを交換することなく、生理データの時間系列を継続的に記録し、医療診断に信頼性のある情報を提供します。
開発実践での GRTC
開発者にとって、GRTC の API はシンプルで明確であり、複数の割り込みトリガーモードをサポートしています。異なるクロック源と分周係数を設定することで、時間計測の精度と消費電力のバランスを柔軟に調整できます。また、GRTC は外部イベントの発生時間を正確に記録するタイムスタンプキャプチャ機能を提供しており、イベント駆動型アプリケーションの開発に強力なサポートを提供します。
GRTC カウンタの取得コード
prj.conf にマクロを追加:
CONFIG_POWEROFF=y
初期化関数:
uint64_t user_get_grtc_count() {
uint32_t syscounterl_value, syscounterh_value, syscounterh;
uint64_t syscounter;
uint8_t m = 1;
do {
syscounterl_value = NRF_GRTC->SYSCOUNTER[m].SYSCOUNTERL;
syscounterh = NRF_GRTC->SYSCOUNTER[m].SYSCOUNTERH;
syscounterh_value = (syscounterh & GRTC_SYSCOUNTER_SYSCOUNTERH_VALUE_Msk) >> GRTC_SYSCOUNTER_SYSCOUNTERH_VALUE_Pos;
if (((syscounterh & GRTC_SYSCOUNTER_SYSCOUNTERH_OVERFLOW_Msk) >> GRTC_SYSCOUNTER_SYSCOUNTERH_OVERFLOW_Pos) == GRTC_SYSCOUNTER_SYSCOUNTERH_OVERFLOW_Overflow) {
syscounterh_value--;
}
} while (((syscounterh & GRTC_SYSCOUNTER_SYSCOUNTERH_BUSY_Msk) >> GRTC_SYSCOUNTER_SYSCOUNTERH_BUSY_Pos) != GRTC_SYSCOUNTER_SYSCOUNTERH_BUSY_Ready);
return (uint64_t)(syscounterh_value << 32) + syscounterl_value;
}
// 30秒間のタイマー休止
void test(void) {
int systemoff_count = 0;
for (;;) {
dk_set_led(RUN_STATUS_LED, (++blink_status) % 2);
k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));
printk("time us = %lld \r\n", app_syscounter = user_get_grtc_count());
systemoff_count++;
printf("systemoff_count = %d\r\n", systemoff_count);
if (systemoff_count == 30) {
enter_system_off();
}
}
}