nRF5 SDKをちょっと使ってみたのでメモ
BLEな部分は触らずマイコンみたいに使いました。
環境:
Hardware: nRF52832 搭載の nRF52-DK PCA10040
Software: nRF5 SDK 14.2.0 / SoftDevice S123 5.0.0
Queue
タスク間のデータ転送などに使う。
数年前のnRF5 SDKではmailboxがあったが、現時点ではmailboxが廃止されており、その代わりにQueueを使用します。
Queueはマクロを使って定義する。
NRF_QUEUE_DEF(uint8_t, myQueue, 15, NRF_QUEUE_MODE_OVERFLOW);
ここで定義されるQueueはスコープがstaticなので、ファイル外からアクセスする場合はアクセス用の関数を用意する。
Queue操作のAPIはいろいろとあるけど、4つだけ使用。
nrf_queue_reset(&myQueue);
nrf_queue_push(&myAppQ, &ev);
nrf_queue_is_empty(&myQueue);
nrf_queue_pop(&myQueue, &ev);
このQueueを使ってイベント処理を実装してみた。
doEvent(void)
{
uint8_t e;
if (nrf_queue_is_empty(&myQueue)) {
return;
}
nrf_queue_pop(&myQueue, &e);
swith(e){
....
}
}
アプリケーションタイマ
RTOSのタスクをタイマ起動に置き換えてみた。
今回はFreeRTOSは使いたくなかったので、タイマからの定期起動として実装してみました。
アプリケーションタイマの種類として、周期タイマとシングルショットタイマがある
周期タイマ
APP_TIMER_DEF(my_timer_id);
app_timer_create(&my_timer_id, APP_TIMER_MODE_REPEATED, smac_loop_handler);
app_timer_start(my_timer_id, APP_TIMER_TICKS(1), NULL);
シングルショットタイマ
uint32_t timer_ms = 10;
app_timer_create(&my_timer_id, APP_TIMER_MODE_SINGLE_SHOT, WaitSendTimerCallBack));
uint64_t tick = ( timer_ms * APP_TIMER_CLOCK_FREQ ) / ( 1000 * (APP_TIMER_CONFIG_RTC_FREQUENCY + 1) );
app_timer_start(my_timer_id, tick, NULL);
タイマの周期を変数で指定する場合は、APP_TIMER_TICKSマクロは使えないので、APP_TIMER_TICKS()相当の計算を行う、そのときuint64_tで計算する。
アプリケーションタイマからのコールバックは、タイマ割り込みのコンテキストで実行される。 割り込みを必要とするような処理は行えないことに注意。
ハードウェアタイマ
高精度のカウント処理が使いたいのでハードウェアタイマを使ってみた。
nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
timer_cfg.frequency = NRF_TIMER_FREQ_2MHz;
timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
APP_ERROR_CHECK(nrf_drv_timer_init(&NRF_DRV_TIMER_INSTANCE(1), &timer_cfg, timer_void_event_handler));
nrf_drv_timer_disable(&NRF_DRV_TIMER_INSTANCE(1));
nrf_drv_timer_clear(&NRF_DRV_TIMER_INSTANCE(1));
nrf_drv_timer_enable(&NRF_DRV_TIMER_INSTANCE(1));
カウント値の取得
count = nrf_drv_timer_capture(&NRF_DRV_TIMER_INSTANCE(1), NRF_TIMER_CC_CHANNEL0)
SPIマスタ
SPIの設定
SPIの設定は構造体にパラメータを設定してAPIを呼ぶ
デフォルト設定の定義があるので、これを使う。
/**
* @brief SPI master instance default configuration.
*/
#define NRF_DRV_SPI_DEFAULT_CONFIG \
{ \
.sck_pin = NRF_DRV_SPI_PIN_NOT_USED, \
.mosi_pin = NRF_DRV_SPI_PIN_NOT_USED, \
.miso_pin = NRF_DRV_SPI_PIN_NOT_USED, \
.ss_pin = NRF_DRV_SPI_PIN_NOT_USED, \
.irq_priority = SPI_DEFAULT_CONFIG_IRQ_PRIORITY, \
.orc = 0xFF, \
.frequency = NRF_DRV_SPI_FREQ_4M, \
.mode = NRF_DRV_SPI_MODE_0, \
.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST, \
}
#define SPI_SS_PIN 29
#define SPI_MISO_PIN 28
#define SPI_MOSI_PIN 4
#define SPI_SCK_PIN 3
nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
spi_config.ss_pin = SPI_SS_PIN;
spi_config.miso_pin = SPI_MISO_PIN;
spi_config.mosi_pin = SPI_MOSI_PIN;
spi_config.sck_pin = SPI_SCK_PIN;
spi_config. frequency = NRF_DRV_SPI_FREQ_1M
APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler, NULL));
SPIデータの送受信
uint8_t tx[2] = 0x01;
uint8_t rx[2];
APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, tx, 2, rx, 2));