目的
BLE機能の有効化
前置き
BLE機能が無効化されたプロジェクトから
BLE機能が使えるところまでは確認できたが、以下手順が全て正しいとは限らない。
SDKバージョンは16.0、SoftDeviceはS140を使用。
SDK内のBLE機能が実装されたサンプルコード、
examples/ble_central/ble_app_blinky_c
等の設定を参考にする。
SoftDeviceによって使用が禁止、制限されるペリフェラルがあるため、
現行のファームウェアが使用しているペリフェラルと競合するかをまず確認しておく。
以下参照。
System on Chip resource requirements -> Hardware peripherals
手順
1. プリプロセッサ定義の追加
SoftDeviceの有効化するためプリプロセッサ定義(プロジェクトファイルのc_preprocessor_definitions
)に以下を追加。
c_preprocessor_definitions="(省略)... ;S140;SOFTDEVICE_PRESENT;NRF_SD_BLE_API_VERSION=7"
2. インクルードフォルダの追加
上記手順で有効にしたコンパイルスイッチSOFTDEVICE_PRESENT
によってBLE関連のコードを参照するようになるため、
サンプルコードを参考にインクルードフォルダ(プロジェクトファイルのc_user_include_directories
)を追加。
3. SDKコンフィグ設定
SDKコンフィグ(sdk_config.h)のBLE機能に関する各種設定をサンプルを参考に取り込む。
BLE_
の付いた設定項目はほとんど取り込んだ。
4. リンカ設定にセクション追加
リンカ設定(flash_placement.xml)のBLE機能に関するセクションをサンプルを参考に取り込む。
以下セクションは追加必須と思われる。
.sdh_soc_observers
, .sdh_ble_observers
, .sdh_state_observers
, .sdh_stack_observers
, .sdh_req_observers
5. プロジェクトにCファイル追加
上記手順を実行した辺りでコンパイルを実行すると関数の未定義エラーが発生する。
その関数が定義されたCファイルがSDK内components
以下に存在するはずなのでプロジェクトに追加する。
SDKコンフィグ(sdk_config.h)にBLE_LBS_ENABLED
のような機能の有効/無効フラグがあり、
このフラグによりCファイルの中身が無効となっており、関数の未定義エラーが発生している場合もある。
その場合はフラグを有効に変更する。
6. SoftDeviceの書込み準備
SoftDeviceを書き込むために、
SoftDeviceの書き込まれるFlash領域と、SoftDeviceが使用するRAM領域を空ける必要がある。
S140の場合、SDK内のcomponents/softdevice/s140/doc/s140_nrf52_7.0.1_release-notes.pdf
に、
以下のように記載がある。
Flash: 156 kB (0x27000 bytes)
RAM: 5.6 kB (0x1678 bytes). This is the minimum required memory. The actual requirements depend on the configuration chosen at sd_ble_enable() time.
SoftDeviceはFlash領域の0x00アドレスから、RAM領域の0x00アドレスからを使用するため、
リンカ設定の定義値
FLASH_START
を0x27000に変更、
FLASH_SIZE
を元の値 - 0x27000の値に変更、
RAM_START
を元の値 + 0x3000程度の値に変更(BLE設定次第で5.6KB以上使用するため適当に多めに領域を確保する)、
RAM_SIZE
を元の値 - 0x3000の値に変更する。
※ BLEのコンフィグ変更後にメモリアクセス異常等が発生する場合、SoftDeviceに割り当てたRAM領域の不足が考えられる。
その他開始アドレスを指定しているセクションがある場合は、
上記でずらした分だけアドレスを変更しておく。
7. SoftDeviceの書込み
プロジェクトファイル内のdebug_additional_load_file
にSoftDeviceのhexファイルを指定する。
指定することでファームウェアと一緒に書き込まれる。
debug_additional_load_file="../../../../../../components/softdevice/s140/hex/s140_nrf52_7.0.1_softdevice.hex"
8. 使用ペリフェラルの変更
前置きでも記載したが、
SoftDeviceによって使用が禁止、制限されるペリフェラル( System on Chip resource requirements -> Hardware peripherals)があるため、
競合している場合は、使用するペリフェラルを変更する必要がある。
対応方法はペリフェラルごとに異なる。
使用が禁止されているペリフェラルを使用した場合、
Q&Aにあるように、
app_error_weak.c
のapp_error_fault_handler
がコールされ、
idがNRF_FAULT_ID_APP_MEMACC
で、infoが0x00000800となる。
しかし、複数エラーが発生していることも当然考えられるので、
infoが0x00000800でないからといって使用禁止ペリフェラルを使用していないとは限らない。
TIMERの場合
TIMERやRTC等は、TIMER0、RTC0が使用禁止されているが、TIMER1、RTC1は使用可能なので、
SDKコンフィグ(sdk_config.h)の
TIMER0_ENABLED
、NRFX_TIMER0_ENABLED
を無効化(0)し、
TIMER1_ENABLED
、NRFX_TIMER1_ENABLED
を有効化(1)する。
また、以下のようにインスタンスを定義している箇所があるはずなので、インスタンス番号を変更する。
//const nrf_drv_timer_t timer1 = NRF_DRV_TIMER_INSTANCE(0);
const nrf_drv_timer_t timer1 = NRF_DRV_TIMER_INSTANCE(1);
NVMCの場合
フラッシュアクセスに使用するNVMCは使用が制限されており、
こちらのQ&Aでは、NVMCの使用は推奨しないので、
変わりにfstorageまたはFDSを使用することを薦めている。
fstorage、FDSのサンプルコードも用意されており、対応は可能だが実装変更が必要となってしまう。
POWERの場合
powerの初期化関数に以下の実装があり、
SoftDevice(SOFTDEVICE_PRESENT)有効時の対処が入っているので、
おそらくSoftDeviceを意識せずに使用できると思われる。
ただし実装を見ての通り、SoftDeviceが有効状態(nrf_sdh_is_enabled())の場合はpowerの初期化に失敗する。
これは、SoftDeviceにてpowerは初期化されているからだと思われる。
ret_code_t nrf_drv_power_init(nrf_drv_power_config_t const * p_config)
{
if (m_initialized)
{
return NRF_ERROR_MODULE_ALREADY_INITIALIZED;
}
#ifdef SOFTDEVICE_PRESENT
if (nrf_sdh_is_enabled())
{
return NRF_ERROR_INVALID_STATE;
}
#endif
...
9. ペリフェラル初期化順番確認
上記手順8のPOWERの場合で記載しているが、
SoftDeviceの初期化(ble_stack_init())と他のペリフェラル初期化順番に制限があるものがあるため注意する。