NFCを使ってみる

# はじめに
[前回](https://qiita.com/AkimotoMasane/items/9472deda31811a2a03be)、PN5180のバージョンを読み出してみましたが、ファームウェアのバージョンが古いようです。
今回は、PN5180のファームウェアをアップデートしてみました。

# 使用機器
PN5180 NFC RFセンサーモジュール

:::note info
使用機器について
PN5180とはSPI通信を使用してデータの送受信を行います。
PN5180はスレーブとなります。
マスターにはSTM社のNUCLEOボードを使用しました。
:::

# 接続
ファームウェアのアップデートではREQ（DWL_REQ端子）を使用します。
ファームウェアのアップデートを行うときはREQ（DWL_REQ端子）の出力をHIGHにします。

![接続.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148400/39bf1603-45bd-2134-50fb-58ee70c98686.png)

# ファームウェアの入手
最新のファームウェアを入手するにはNXP社のサイトでユーザー登録する必要があります。
[NFC Cockpit Configuration Tool for NFC ICs](https://www.nxp.jp/products/rfid-nfc/nfc-hf/nfc-readers/nfc-cockpit-configuration-tool-for-nfc-ics:NFC-COCKPIT)をダウンロードします。

ユーザー登録されていない場合、ダウンロードする際にユーザー登録が必要になります。
ダウンロードしたNFC-COCKPITというツールをインストールすると、下記のフォルダ内にファームウェアが格納されています。

C:\nxp\NxpNfcCockpit_v8.0.0.0\firmware\PN5180_SFWU
PN5180Firmware_4.1.sfwu

このファイル（PN5180Firmware_4.1.sfwu）の内容をPN5180に書き込みます。

# ファームウェアの変換
ファームウェア「PN5180Firmware_4.1.sfwu」はバイナリのようなので16進数データに変換します。
データの変換は、[こちら](https://github.com/zGrEaNz/PN5180_Updater)で紹介されている
[ファイルの変換](https://tomeko.net/online_tools/file_to_hex.php?lang=en)でファイルの変換を行うことができます。
変換結果を8ビットの配列としてファームウェアのアップデート時に参照します。

```c:
const uint8_t firmware[] = {
	0x00, 0x0E, ・・・
};
```

# ファームウェアの構造
入手したファームウェア（PN5180Firmware_4.1.sfwu）は
データサイズ（2バイト） + データサイズ分のデータ
の塊で構成されています。

![構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148400/e37dce53-66be-2d44-92c0-e491cb83a810.png)

この構造の塊でファームウェアのファイル（PN5180Firmware_4.1.sfwu）は構成されています。

![構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148400/d52392e7-803f-8ad5-ef52-7f8ffcaef5b5.png)

特に先頭のデータの塊にはファームウェアバージョンが含まれています。
入手したファームウェアは、ファームウェアバージョン4.1になっていました。

![構成.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148400/f59f7105-3168-4f5d-0357-562ef5576df0.png)

# 通信フォーマット
ファームウェアのアップデートを行うには、決められた通信フォーマットに従って送信データを構築する必要があります。通信フォーマットは下記のようになります。

![format.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148400/be6e2f10-f704-ba6c-9ecc-751816c95a29.png)

+ Dir Byte
データの方向を示す値になります。
マスターからPN5180へデータを送信するとき　0x7F
マスターがPN5180からデータを受信するとき　0xFF
を設定します。

+ RFU[15:11]
全て0を設定します。
※RFU : Reserved for Future Use

+ Chunk[10]
1回に通信で送ることができるデータのサイズは256バイトまでになります。
256バイトより大きいデータを送信したい場合、データを分割して送信する必要があります。
分割してデータを送信するときにChunkを使用します。

+ Length[9:0]
Frameのサイズを表します。最大値は256バイトとなります。

+ Frame
送信データになります。
データを送信するとき、Frameの先頭には１バイトのOpCodeを設定します。

+ End
HeaderからFrameまでのCRC16の計算結果を設定します。

:::note info
PN5180Firmware_4.1.sfwu について
ファイルはこの通信フォーマットに合わせて作成されています。
そのため、通信フォーマットにあるOpCodeもファイル内に埋め込まれています（0xC0：SECURE_WRITE）。
ただし、Lengthについては、データの長さを表しているだけとなります。
マスターからPN5180への送信データの最大数となる256バイトに関しては考慮されていません。
また、CRC16もファイルには埋め込まれていないため計算する必要があります。
:::

# アップデート手順
ファームウェアのアップデートを行うためにはPN5180をアップデートモードにする必要があります。
PN5180を起動したら、DWL_REQ端子をHIGHにします。
PN5180をリセットして、リセットを解除するとPN5180はアップデートモードになります。

マスターから、PN5180へファームウェアデータを送信するときは、送信する前にBUSY端子がLOWであることを確認してからファームウェアデータを送信します。
また、アップデートモードでは、マスターからファームウェアデータを送信すると、PN5180から応答データ（Response）が返されます。BUSY端子がHIGHであることを確認してからResponseを受信します。

![flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148400/ab73af14-e1cd-dedc-4a32-c8c179007f31.png)

# ファームウェアの送信
PN5180がアップデートモードになったら、[通信フォーマット](#通信フォーマット)に従ってファームウェアを送信します。

## 256バイト以下のデータを送信する場合
Frameのサイズ（HeaderのLength）が256バイト以下であれば1回の通信でデータを送信することができます。

![format.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148400/b54f3e6f-a753-3478-27dc-1e1c74e8d7e0.png)

マスターからデータを送信すると、PN5180からのResponseが返ってきます。Responseのフォーマットは下記のようになります。

![format.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148400/1e226f16-c0af-61b6-dd39-2ab075ab44f4.png)

ResponseのFrameの最初のデータはSTATになっています。
STATが0x00のときはOKとなります。
STATが0x00以外（0x01 - 0xFF）のときはエラーとなります。

## 256バイトより大きいデータを送信する場合
Frameのサイズ（HeaderのLength）が256より大きい値の場合、複数回に分けてデータを送信する必要があります。
複数回に分けてデータを送信する場合、HeaderのChunkフラグを使用します。
データを送るときにChunkフラグを1とします。
最後のデータを送るときはChunkフラグを0とします。

例）550バイト（0x0226）のデータを送信する場合
![pn5180_202407-ページ7.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148400/7f624594-32f5-516e-a67a-b1e491585ca8.png)

# アップデート後
PN5180のファームウェアをアップデートした後にEEPROMのバージョン情報を読み出した結果です。

|バージョン情報|アップデート前|アップデート後|
|:---|:---|:---|
|Die identifier|0x00 0x00 0x00 0x00 0x00 0x01 0x76 0x0A 0x23 0x14 0x3A 0x56 0x64 0x56 0x20 0x55|0x00 0x00 0x00 0x00 0x00 0x01 0x76 0x0A 0x23 0x14 0x3A 0x56 0x64 0x56 0x20 0x55|
|Product Version|0x05 0x03|0x01 0x04|
|Firmware Version|0x05 0x03|0x01 0x04|
|EEPROM Version|0x00 0x91|0x00 0x99|

バージョン情報を読み出すとバージョンが3.5から4.1になりました。

# 参考
[NXP社](https://www.nxp.jp/products/rfid-nfc/nfc-hf/nfc-readers/full-nfc-forum-compliant-frontend-ic:PN5180)
[GitHub PN5180_Updater](https://github.com/zGrEaNz/PN5180_Updater)

# 編集後記
ファームウェアのバージョンをアップデートすることができたようなので、次回は、FeliCaのデータの読み書きに挑戦したいと思います。