EYSGCNZWY(nRF51822)をArduinoIDE＋Nucleoで開発する ~Serial通信をBluetoothで無線化~

#はじめに
　ArduinoIDEとNucleoを用いたEYSGCNZWY(nRF51822)の開発方法についてのまとめです。
　
　＊Windows環境を対象としています。
　＊Nucleo32系列のようにデバッグピンの出てないボードは対象外です。

#使用したハードウェア
- EYSGCNZWY(nRF51822搭載のBluetoothモジュール)
- Nucleo-F401RE


#STEP1. EYSGCNZWYの準備
　開発用に以下の線を出します。
　**注意：図はTop Viewなので実際に基板をひっくり返して見たときには上下が逆になります。**　

　・電源　－　2, 4（2はアナログ用電源なので問題なければ4と繋げてOK、DC/DCを使う場合は1と2を繋げる）
　・GND　－　3, 5, 13, 21, 41 ~ 45, 47, 48（いずれか１つでOK）
　・SWDIO　－　14
　・SWDCLK　－　15
　
　また、基板上のチップアンテナを使用する場合は22, 23をショート。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16031/78a98080-f2d3-85fb-a529-6b4b7e9ca512.png)</div>
![無題2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16031/47fc55cc-9d3e-acb3-dcbf-0c635b224c6e.png)

#STEP2. Nucleoの準備
　EYSGCNZWYに搭載されているnRF51822はSWDで開発を行います。そこでNucleoのボード上にあるSWD対応デバッガのST-Linkを使用するわけですが、何故か私の環境ではArduinoIDE上でST-Linkをうまく認識させることができませんでした。そこで今回はST-LinkをJ-Link化させた上で、ドライバをWinUSBに変更しArduinoIDE上で扱えるようにしました。手順は以下の通りです。

1　ST-Linkのドライバをインストール
　　https://www.st.com/ja/development-tools/stsw-link009.html

2　Nucleo上のST-Linkのファームウェアを更新
　　https://www.st.com/ja/development-tools/stsw-link007.html

3　J-Linkのドライバ(J-Link Software and Documentation Pack)とST-Link Reflash Utilityをインストール
　　https://www.segger.com/downloads/jlink

4　ST-LinkをJ-Link化
 　1. ST-Link Reflash Utilityを起動
 　2. ライセンスについての同意 ✕ ２
 　3. Upgrade to J-Linkを選択
 　4. J-Link化が完了したらST-Link Reflash Utilityを終了
 　＊ST-Link Reflash Utilityを使ってST-Linkに戻すこともできます。
![jlink-stlink-stlinkreflash-3-upgradetojlink.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16031/c3f31ee5-3ff1-fc02-530c-4a55a5a7489a.png)


5　Zadigをインストール
　　https://zadig.akeo.ie/

6　J-LinkのドライバをWinUSBに変更
 　1. Zadigを起動
 　2. OptionsのList All Devicesを選択
 　3. Driverがjlinkと表示されるデバイスをリストの中から見つける
 　4. 変更されるドライバがWinUSBで有ることを確認しReplace Driverを押す
 　5. ドライバが変更されたらZadigを終了
 　＊デバイスマネージャーからドライバをもとに戻すことができます。
 ![無題3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16031/c849eee7-b2b8-d693-abca-54263bc6aea3.png)

#STEP3. ArduinoIDE周りの準備
####ボードの追加
　まずはnRF51822を扱えるようにするためボード情報を追加します。ArduinoIDEの環境設定を開いて”追加のボードマネージャーのURL”に```https://sandeepmistry.github.io/arduino-nRF5/package_nRF5_boards_index.json```を追加してください。その後、ツールからボード＞ボードマネージャーを開いて```Nordic Semiconductor nRF5 Boards```をインストールしてください。

####SoftDevice書き込みツールのインストール
　nRF5xシリーズでは、アプリケーションプログラムとは別にSoftDeviceと呼ばれるプロトコルスタックを書き込んでおくことでアプリの変更や修正などの影響を受けずに開発をすることができます。EYSGCNZWYの場合、デフォルトではS120というバージョンのSoftDeviceが書き込まれていますが、追加したボード情報はS110もしくはS130にしか対応していないためどちらかのバージョンを新たに書き込む必要があります。そこでArduinoIDEにSoftDevice書き込みツールをインストールします。手順は以下の通りです。

1.　SoftDevice書き込みツールをダウンロード
　　https://github.com/sandeepmistry/arduino-nRF5/releases/download/tools/nRF5FlashSoftDevice.jar

2.　スケッチが保存されるフォルダ(```~\Documents\Arduino\```)に```tools\nRF5FlashSoftDevice\tool\```という階層でフォルダを作成しtoolの中にダウンロードした書き込みツールを入れる


3.　任意のSoftDeviceをダウンロード
　　S110：https://www.nordicsemi.com/Software-and-tools/Software/S110/Download#infotabs
　　S130：https://www.nordicsemi.com/Software-and-tools/Software/S130/Download#infotabs

4.　中身の```s1?0_nrf51_?.?.?_softdevice.hex```を```~\AppData\Local\Arduino15\packages\sandeepmistry\hardware\nRF5\0.6.0\cores\nRF5\SDK\components\softdevice\s1?0\hex```に入れる(バージョンの一致するフォルダに入れること)

####HFCLKの設定変更
　EYSGCNZWYは32MHzの水晶振動子が搭載されています。しかし前述の```Nordic Semiconductor nRF5 Boards```の中でも最終的に書き込むボードとして選択することになる```Generic nRF51```ではデフォルトで16MHzの水晶振動子を使う設定となっています。このためBluetoothを正しく動作させるためにボードの初期化プログラムを修正する必要があります。修正が必要なファイル及びプログラムは以下の通りです。

ファイル：
```~\AppData\Local\Arduino15\packages\sandeepmistry\hardware\nRF5\0.6.0\cores\nRF5\SDK\components\toolchain\system_nrf51.c```

プログラム：
 関数SystemInitの中に以下を追加

```C
if (*(uint32_t *)0x10001008 == 0xFFFFFFFF)
{
 NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
 while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
 *(uint32_t *)0x10001008 = 0xFFFFFF00;
 NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
 while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
 NVIC_SystemReset();
 while (true){}
}
``` 

#STEP3. ソフトウェアの実装
####BLEのライブラリをインストール
　BLEを簡単に扱えるようにするためにライブラリを使用します。ArduinoIDEのライブラリを管理を開いて```BLEPeripheral```をインストールしてください。

####Serial通信用プログラムの配置
　BLEPeripheralにはSerial通信をするためのプログラムがサンプルとして用意されています。オリジナルアプリケーションを作成する際にはこのプログラムを任意のスケッチフォルダに配置することでBLEで無線化したSerial通信が可能となります。対象ファイルは以下の２つです。

Serial通信用プログラム：
```~\Documents\Arduino\libraries\BLEPeripheral\examples\serial\BLESerial.cpp"```
```~\Documents\Arduino\libraries\BLEPeripheral\examples\serial\BLESerial.h"```

####お試しプログラム
　Serial通信のReadとWriteを行う簡単なプログラム例は以下の通りです。

```c
#include <BLEPeripheral.h>
#include "BLESerial.h"

BLESerial bleSerial;
int ble_command;

void setup() {  
  bleSerial.setLocalName("Test Device");
  bleSerial.begin();
}

void loop() {
  bleSerial.poll();
  ble_command = bleSerial.read();

  if (ble_command == 1) {
    bleSerial.println("OK");
  }

  bleSerial.print(".");
  
  delay( 1000 );
}
```

####書き込み設定
　書き込む際の設定例は以下の通りです。

- ボード：Generic nRF51
- Chip：32 kB RAM, 256 kB flash(xxac)
- Softdevice：S130
- Low Frequency Clock：Crystal Oscillator
- 書き込み装置：J-Link

####書き込み
　書き込み設定で選択したSoftDeviceを書き込んでおく必要があるので、ツールから```nRF5 Flash SoftDevice```を選択してSoftDeviceを書き込みます(１度だけで大丈夫です)。その後、通常通りデバックを行いプログラムを書き込んでください。

####エラーがno matching function for call to 'BLESerial::BLESerial()'の場合
　BLESerial.h内の宣言を以下のように修正してください。

変更前：
```BLESerial(unsigned char req, unsigned char rdy, unsigned char rst);```

変更後：
```BLESerial(unsigned char req = BLE_DEFAULT_REQ, unsigned char rdy = BLE_DEFAULT_RDY, unsigned char rst = BLE_DEFAULT_RST);```