NFCをリード・ライトするためにRaspbianをビルドする

Raspberry Pi 3でNFCの読み書きをする場合、USBカードリーダーを接続する方法とI2Cで接続されるボードを搭載する方法の二つがあります。本記事では、[PN7120というNFCコントローラー](https://www.nxp.com/products/identification-and-security/nfc/nfc-reader-ics/development-kits-for-pn7120-plugn-play-nfc-controller:OM5577)をI2Cで接続する際に必要となる、RaspbianカーネルにNFCドライバーを組み込んでビルドする手順をシェアします。

PN7120 NFCコントローラの製造元であるNXPからリリースされている[クイックスタートガイド](http://akizukidenshi.com/download/ds/nxp/AN11646.pdf)や[アプリケーションノート](https://www.nxp.com/docs/en/application-note/AN11697.pdf)も参考にしてください。

#カーネルソースのダウンロード#
NFCコントローラーのデバイスドライバーを組み込むためには、カーネルソースとカーネルヘッダが必要でカーネルをビルドしなおす必要があります。

```shell
#必要となる依存モジュールをインストールします
sudo apt-get install bc libncurses5-dev

#ホームディレクトリへ移動
cd ~/

#最新のカーネルソースを取得する
git clone --depth=1 https://github.com/raspberrypi/linux

#カーネルビルドの準備を行う
cd linux
KERNEL=kernel7
make bcm2709_defconfig

#カーネルソースの場所： /home/YOUR_USER_NAME/linux
#カーネルモジュールの場所： /lib/modules/{カーネルバージョン}
#現在稼働中のカーネルバージョンの確認方法： uname –a
#表示されるカーネルバージョン例：
#Linux raspberrypi 4.9.28-v7+ #998 SMP Mon May 15 16:55:39 BST 2017 armv7l GNU/Linux
```
#NFCドライバーの組み込み#
NFCドライバーは、カーネルモジュールとしてカーネルに組み込んで使用するため、カーネルとドライバーのビルドが必要です。カーネルモジュールはカーネルバージョンに依存しており、モジュールまたはカーネルのバージョンが変わるたびに再構築が必要となります。（以下のコマンドは`/home/YOUR_USER_NAME/linux`をカレントディレクトリとして実行する前提となっています）

```shell
#NFCコントローラーのドライバーソースを取得します
cd drivers/misc
sudo git clone https://github.com/NXPNFCLinux/nxp-pn5xx.git

#~/linux/Makefileファイルを修正します
cd ~/linux
sudo vi Makefile
#この行に「nfc」の文字列を追加　→　`EXTRAVERSION = nfc

#NFCドライバーの定義を追加します
sudo vi drivers/misc/Makefile
#この1行を追加　→ obj-$(CONFIG_NFC_NXP_PN5XX) += nxp-pn5xx/

sudo vi drivers/misc/Kconfig
#この一行を追加 → source "drivers/misc/nxp-pn5xx/Kconfig"

#以下の内容を`/home/YOUR_USER_NAME/nxp-pn54x-nfc.dts`として書き込みます。
&i2c1 {
	status = "okay";
	pn7120: pn7120@28 {
		compatible = "nxp,pn547";
		reg = <0x28>;
		clock-frequency = <400000>;
		interrupt-parent = <&gpio>;
		interrupts = <23 0x0>;
		interrupt-gpios = <&gpio 23 0>;
		enable-gpios = <&gpio 24 0>;
		firmware-gpios = <&gpio 25 0>;
	};
};

#dtsディレクトリにコピーします。
sudo cp ../nxp-pn54x-nfc.dts arch/arm/boot/dts/

#NFCドライバーをデバイスツリーに追加します
sudo vi arch/arm/boot/dts/bcm2710.dtsi
#この一行を追加 → #include "nxp-pn54x-nfc.dts"

#以下のコマンドでカーネルオプションの設定メニューを表示し設定します
sudo apt-get install libncurses5-dev libncursesw5-dev
sudo make menuconfig
#[Device Drivers]→[Misc devices]→[< > NXP PN5XX based driver]を選択。
「< >」内に「M」を入力しSaveしてExit。

#ビルド前の環境をバックアップします
sudo tar zcvf /var/backups/bootback.tar.gz /boot

#以下のコマンドでカーネルを再構築します（所要時間：約80分）
sudo apt-get install time bc
sudo time make -j4 zImage modules dtbs

#以下のコマンドでビルドされたドライバーなどの成果物をインストールします。
sudo make modules_install
sudo cp arch/arm/boot/dts/*.dtb /boot/
sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/
sudo scripts/mkknlimg arch/arm/boot/zImage /boot/$KERNEL.img

#一般ユーザーにNFCデバイス（/dev/pn544）のリード・ライト権限を与えます
sudo vi /etc/udev/rules.d/pn5xx_i2c.rules
#ACTION=="add", KERNEL=="pn544", MODE="0666" をセットして保存します。

#再起動します。
sudo reboot

#再起動後に再接続して以下のコマンドでビルドがうまくいっているかどうか確認します。
#uname –a コマンドの結果に、MakefileのEXTRAVERSIONで設定したnfcが表示されるか確認します。
#Linux raspberrypi 4.9.36nfc-v7+ #1 SMP Thu Jul 13 16:32:33 JST 2017 armv7l GNU/Linux
#lsmodコマンドの結果にpn5xx_i2cが含まれているか確認します。
#ls /dev/pn544コマンドで該当デバイスが存在するか確認します。
```

#NFCライブラリのビルド#
`libnfc`ライブラリをビルドします。

```shell
#以下のコマンドでlibnfcソースをダウンロードします。
cd ~/
git clone https://github.com/NXPNFCLinux/linux_libnfc-nci.git
cd linux_libnfc-nci/

#以下のコマンドでビルドに必要な依存パッケージをインストールします
sudo apt-get install automake autoconf libtool

#以下のコマンドでビルドオプションを設定しビルドします
./bootstrap
./configure
sudo make　-j4
sudo make install
```

以上でカーネルとnfcライブラリのビルドは終了です。