在 AOSP Kernel 下載及編譯 一文中有提到,
我們當時有先下載了一整包 Kernel 可以提供修改及燒錄。
省略還要跳到該文章研究的時間,我就直接說位置了:
root_aosp_kernel_dir 等於你當初下載好的 AOSP kernel 原始碼位置,{root_aosp_kernel_dir}/private/msm-google/drivers/nfc/pn544/
因為我當初選的是 Google Pixel XL 的程式包,
所以 private
後面會是 msm-google
的資料夾名稱,
端看你要在哪一個裝置上驗證而有所差異。
內容大致上長這樣:
.
├── i2c.c
├── Kconfig
├── Makefile
├── mei.c
├── pn544.c
└── pn544.h
可以看到目前沒有編譯後的中間檔產生,
所以我們需要加一些設定讓它可以自動幫我們編譯。
那我們就會需要改到 Kconfig
和 Makefile
了:
private/msm-google/drivers/nfc/Makefile
1 #
2 # Makefile for nfc devices
3 #
4
5 obj-$(**CONFIG_NFC_PN544**) += pn544/
... ...
private/msm-google/drivers/nfc/pn544/Kconfig
1 **config NFC_PN544**
2 tristate "NXP PN544 NFC driver"
3 depends on NFC_HCI
4 select CRC_CCITT
5 default n
6 ---help---
7 NXP PN544 core driver.
8 This is a driver based on the HCI NFC kernel layers and
9 will thus not work with NXP libnfc library.
10
11 To compile this driver as a module, choose m here. The module will
12 be called pn544.
13 Say N if unsure.
這時候我們只要加在 .config 之中,
我們下編譯指令的時候就會同時編譯到這個模組:
private/msm-google/arch/arm64/configs/marlin_defconfig
230 CONFIG_CFG80211_INTERNAL_REGDB=y
231 CONFIG_RFKILL=y
232 CONFIG_NFC_PN551=y
233 **CONFIG_NFC_PN544=y**
234 CONFIG_IPC_ROUTER=y
你會發現 PN551 早就被編譯進來了,
我猜應該和 Pixel XL 原本就支援這顆模組有關。
至於我這裡為什麼要設成 y ?
因為這樣我們的映像檔才會包含這個模組,
不然它預設是 m ,
只會產生一個 .ko 檔讓你自行安裝進手機喲!
但你會發現 build 完怎麼都沒有編譯到這個模組!
那是因為 drivers/Kconfig 裡面找不到 nfc ,
也就是說 drivers 最上層就不打算把 nfc 整個包含進來編譯。
這時你可以手動加入 (我是有點懶得再繼續追了所以直接把 nfc 整個 source 進來):
204
205 source "drivers/nfc/Kconfig"
206
207 endmenu
假如你原先下載好後有編譯第一次過,
再重新執行一次 ./build/build/sh
會發生錯誤, (怎麼問題一堆...)
這是 AOSP 內核編輯系統的設定,
主要是不讓你因變更預設的內核組態而造成 Android 系統的問題。
AOSP 官方有規定必須加入的 CONFIG 及不可加入的 CONFIG。
這些可以從 kernel/config/README.md
仔細去看,
這裡我們先省略檢查相容性的部份,
可以將 kernel/private/msm/build.config
中的POST_DEFCONFIG_CMDS='check_defconfig'
和 EXTRA_CMDS
拿掉:
3 POST_DEFCONFIG_CMDS="compression_tool_and_files lz4"
4 EXTRA_CMDS=''
之後再執行一次就可以看到編譯成功啦,
而且看 log 也有看到 pn544 模組有編譯進映像檔。
... ...
2413 CC drivers/nfc/pn544/pn544.o
... ...
2425 CC drivers/nfc/pn551.o
... ...
2435 LD drivers/nfc/pn544/built-in.o
2436 LD drivers/nfc/built-in.o
你已經確定這隻驅動有編譯進映像檔了,
這時候你就要修改對應的 device tree ,
你可以稍微參考一下 pn551 的模組是怎麼設定的:
private/msm-google/drivers/nfc/pn551.c
... ...
818 static struct of_device_id pn551_match_table[] = {
819 { .compatible = "nxp,pn551-nfc",},
820 { },
821 };
... ...
後來你可以在資料夾全域搜尋找到剛剛 compatible 內的字串,
因為 device tree 就是用這個關鍵字和驅動去配對的,
而且這裡看起來蠻合理的,因為 Google Pixel XL 當初是給 HTC 組裝的嘛 (笑)。
private/msm-google/arch/arm64/boot/dts/htc/msm8996-htc-nfc.dtsi
45 &i2c_8 {
... ...
66 nxp_pn551_nfc@28 {
67 compatible = "nxp,pn551-nfc";
68 reg = <0x28>;
69 interrupt-parent = <&tlmm>;
70 interrupts = <50 0x4>;
71 nxp,ven-gpio = <&tlmm 12 0x00>;
72 nxp,irq-gpio = <&tlmm 50 0x00>;
73 nxp,fwdl-gpio = <&tlmm 74 0x00>;
74 nfc_i2c_sda = <&tlmm 6 0x00>;
75 nfc_i2c_scl = <&tlmm 7 0x00>;
76 nxp,ven_isinvert = <0>;
77 };
78 };
你可以看到上面有宣告很多 GPIO 設定,
一般就是看模組的規格書上寫需要哪些,
基本的就是上電、斷電控制的 ven-gpio
和中斷控制的 irq-gpio
,
還有韌體下載控制的 fwdl-gpio
。
因為我們並不是真的要把 pn544 晶片的某一顆模組焊上去 Pixel 測試,
只是假設我們之後能有一塊開發板,
又很剛好拿到一顆 NFC 模組要在板子上能正常運作,
你就會需要稍微看看這些該怎麼實作而已。
最後記得要在 init.xxxx.rc
的 on boot
後面加上權限的調整,
不然上層在呼叫 Kernel 層的時候會出現權限不足的錯誤發生:
setprop ro.nfc.port "I2C"
chmod 0660 /dev/pn544
chown nfc nfc /dev/pn544
在 on post-fs-data
後加上:
... ...
++ mkdir /data/nfc 0770 nfc nfc
++ mkdir /etc/param
++ # Set indication (checked by vold) that we have finished this action
++ setprop vold.post_fs_data_done 1
... ...
剩下上層的部份就只是照著擺放的位置加上去,
然後 device tree 的部份也很看平台差異,
參考連結我已經放在下面了,所以 NFC Kernel 就僅止於此。
NFC 這系列就先這樣囉,假如有全部看完的人,
非常感謝各位願意賞臉看完。
Android 平台(Linux3.10) NXP NFC(PN547PN548)