NXP Nfc模块Framework层移植遇到的坑【二】

8173_M平台下移植NXP的Nfc模块时遇到的问题,同样也是 hal 层与 kernel 通信时出错,不过由于这个项目没有量产计划,所以供应商的支持也比较少,最后的解决方案是 Framework 层将检查 Nfc 固件版本的指令给屏蔽了。

调试背景:
1. 驱动已保证IOCTL通信正常,各引脚可正常上下电。(同样出现过上一篇文章中的 IOCTL 数据定义的问题)
2. 已集成NXP官方代码(github源码,各个仓库已切换至Android_M版本 NFC_NCIHALx_AR0F.4.3.0_M_OpnSrc)。
3. FAE没有分析出具体问题原因。

问题现象:
1. 设置中开启NFC后开关直接关闭。
2. 通过抓取log看出在查询完固件版本后发送了关闭NFC的指令。

分析过程:
1. 在log中有如下语句:

NfcAdaptation: NfcAdaptation::HalDeviceContextCallback: event=1
BrcmNfcNfa: nfc_main_hal_cback event: HAL_NFC_CLOSE_CPLT_EVT(0x1), status=0
尝试从 HalDeviceContextCallback 和 HAL_NFC_CLOSE_CPLT_EVT 进行追踪分析,无果。

2.  HalDeviceContextCallback  和  HAL_NFC_CLOSE_CPLT_EVT   均是在发送关闭的请求后的打印,对于问题分析价值不大,从FAE的邮件中了解到关闭NFC的指令为 21030703800181018201
从新分析log,在该指令发送前有一个IOCTL的指令和一个 HalClose 的打印信息:

NfcAdaptation: NfcAdaptation::HalIoctl
NxpHal : phNxpNciHal_ioctl : enter - arg = 9
NxpHal : phNxpNciHal_ioctl : exit - ret = 0
NfcAdaptation: NfcAdaptation::HalClose
NxpTml : PN54X - Write requested.....
NxpTml : PN54X - Invoking I2C Write.....
NxpNciX : len = 10 > 21030703800181018201
其中ioctl的指令为fw版本检查:

HAL_NFC_IOCTL_FW_MW_VER_CHECK (hardware\libhardware\include\hardware\nfc.h)
尝试从HalClose进行跟踪,其直接调用只有NfcAdaptation.cpp中的DownloadFirmware()函数,log中fw已无需下载,没有执行该函数。
除此之外,在初始化设备时会将HalClose函数作为设备的close函数,在设备关闭时会调用,这部分的调用比较复杂,通过close函数过滤出来的结果太多不好分析。

3. NFC状态值

Line 1306: 01-01 00:00:48.595066 971 1529 I BrcmNfcNfa: nfc_set_state 0 (NONE)->1 (W4_HAL_OPEN)
Line 1333: 01-01 00:00:48.687704 971 1529 I BrcmNfcNfa: nfc_set_state 1 (W4_HAL_OPEN)->2 (CORE_INIT)
Line 1444: 01-01 00:00:48.798997 971 1529 I BrcmNfcNfa: nfc_set_state 2 (CORE_INIT)->0 (NONE)
Line 1585: 01-01 00:00:50.509386 971 1539 I BrcmNfcNfa: nfc_set_state 0 (NONE)->1 (W4_HAL_OPEN)
Line 1604: 01-01 00:00:50.607193 971 1539 I BrcmNfcNfa: nfc_set_state 1 (W4_HAL_OPEN)->2 (CORE_INIT)
Line 1723: 01-01 00:00:50.718533 971 1539 I BrcmNfcNfa: nfc_set_state 2 (CORE_INIT)->0 (NONE)

从观察得知,在NFC从开启到自动关闭的过程中,其状态经历了 0->1->2->0 的改变,在其状态从2变回0之后,有一句初始化报错的打印信息:

BrcmNfcJni: nfcManager_doInitialize: fail nfa enable; error=0x0
在代码中搜索 nfc_set_state,发现只有在 nfc_task.c (external\libnfc-nci\src\nfc\nfc\nfc_task.c) 中有将状态值设为 NFC_STATE_CORE_INIT (对应状态值2) 的操作。


UINT32 nfc_task (UINT32 param)
{
...(初始化变量)
/* main loop */
while (TRUE)
{
event = GKI_wait (0xFFFF, 0);

/* Handle NFC_TASK_EVT_TRANSPORT_READY from NFC HAL */
if (event & NFC_TASK_EVT_TRANSPORT_READY)
{
NFC_TRACE_DEBUG0 ("NFC_TASK got NFC_TASK_EVT_TRANSPORT_READY.");

/* Reset the NFC controller. */
nfc_set_state (NFC_STATE_CORE_INIT);(在这里将状态设置为core_init)
#if(NXP_EXTNS == TRUE)
nci_snd_core_reset (NCI_RESET_TYPE_KEEP_CFG);
#else
nci_snd_core_reset (NCI_RESET_TYPE_RESET_CFG);
#endif
}
if (event & NFC_MBOX_EVT_MASK)
{
/* Process all incoming NCI messages */
while ((p_msg = (BT_HDR *) GKI_read_mbox (NFC_MBOX_ID)) != NULL)
{
/* Determine the input message type. */
switch (p_msg->event & BT_EVT_MASK)
{
...
case BT_EVT_TO_NFC_NCI:
free_buf = nfc_ncif_process_event (p_msg);
break;
...(其他case)
}
...(后续操作省略)
}
在 nfc_task.c   的主函数中,初始化 task 后通过 while(true) 来捕获 kernel 发送的 event,并根据 event 内容作出相应的操作。这里需要注意的有两个函数,一个是 nfc_set_state 函数,这个函数负责设置 nfc 的当前状态;另一个则是 nfc_ncif_process_event 函数。
nfc_ncif_process_event  函数位于  nfc_ncif.c( external\libnfc-nci\src\nfc\nfc\nfc_ncif.c ) 中

该函数中有如下代码:

if ((nfc_cb.nxpCbflag == TRUE)&&(nfc_ncif_proc_proprietary_rsp(mt,gid,oid) == TRUE))
{
nci_proc_prop_nxp_rsp(p_msg);
nfc_cb.nxpCbflag = FALSE;
return (free);
}
通过对 flag 进行判断符合后,执行 nci_proc_core_rsp 函数,该函数位于   nci_hrcv.c (external\libnfc-nci\src\nfc\nci\nci_hrcv.c) 中:


BOOLEAN nci_proc_core_rsp (BT_HDR *p_msg)
{
...(初始化变量)
NCI_MSG_PRS_HDR1 (pp, op_code);
NFC_TRACE_DEBUG1 ("nci_proc_core_rsp opcode:0x%x", op_code);

/* process the message based on the opcode and message type */
switch (op_code)
{
case NCI_MSG_CORE_INIT:
nfc_ncif_proc_init_rsp (p_msg);
free = FALSE;
break;
...(其他case省略)
}
return free;
}
值得注意的是上述函数中有对操作码的打印操作,所以可以看到 log 中在执行完状态值设置后会有相应的 opcode 的打印。

01-01 00:00:48.687704 971 1529 I BrcmNfcNfa: nfc_set_state 1 (W4_HAL_OPEN)->2 (CORE_INIT)
01-01 00:00:48.687754 971 1529 I BrcmNfcNfa: nfc_ncif_send_cmd.
01-01 00:00:48.687795 971 1529 D NfcAdaptation: NfcAdaptation::HalWrite
01-01 00:00:48.687849 971 1529 D NxpExtns: const nxp::CNfcParam* nxp::CNfcConfig::find(const char*) const found MIFARE_READER_ENABLE=(0x1)
01-01 00:00:48.689301 971 1532 D NxpTml : PN54X - Write requested.....
01-01 00:00:48.689386 971 1532 D NxpTml : PN54X - Invoking I2C Write.....
01-01 00:00:48.693252 971 1532 D NxpNciX : len = 4 > 20000100
01-01 00:00:48.693329 971 1532 D NxpTml : PN54X - I2C Write successful.....
01-01 00:00:48.693375 971 1532 D NxpTml : PN54X - Posting Fresh Write message.....
01-01 00:00:48.693495 971 1532 D NxpTml : PN54X - Tml Writer Thread Running................
01-01 00:00:48.693536 971 1534 D NxpHal : write successful status = 0x0
01-01 00:00:48.697552 971 1531 D NxpTml : PN54X - I2C Read successful.....
01-01 00:00:48.697643 971 1531 D NxpNciR : len = 6 > 400003001000
01-01 00:00:48.697678 971 1531 D NxpTml : PN54X - Posting read message.....
01-01 00:00:48.698384 971 1534 D NxpHal : read successful status = 0x0
01-01 00:00:48.698468 971 1534 D NfcAdaptation: NfcAdaptation::HalDeviceContextDataCallback: len=6
01-01 00:00:48.698576 971 1529 I BrcmNfcNfa: NFC received rsp gid:0
01-01 00:00:48.698641 971 1529 I BrcmNfcNfa: nci_proc_core_rsp opcode:0x0
01-01 00:00:48.698646 971 1531 D NxpTml : PN54X - Read requested.....
01-01 00:00:48.698694 971 1531 D NxpTml : PN54X - Invoking I2C Read.....
01-01 00:00:48.698689 971 1529 E BrcmNfcNfa: reset notification nfc_state : #### 1
01-01 00:00:48.698743 971 1529 E BrcmNfcNfa: reset notification sending core init
01-01 00:00:48.698787 971 1529 I BrcmNfcNfa: nfc_ncif_send_cmd.
01-01 00:00:48.698832 971 1529 I BrcmNfcNfa: nfc_ncif_check_cmd_queue : making p_buf NULL.
01-01 00:00:48.698884 971 1529 D NfcAdaptation: NfcAdaptation::HalWrite
01-01 00:00:48.698938 971 1529 D NxpExtns: const nxp::CNfcParam* nxp::CNfcConfig::find(const char*) const found MIFARE_READER_ENABLE=(0x1)
01-01 00:00:48.699043   971  1532 D NxpTml  : PN54X - Write requested.....
01-01 00:00:48.699090   971  1532 D NxpTml  : PN54X - Invoking I2C Write.....
01-01 00:00:48.702307   971  1532 D NxpNciX : len =   3 > 200100
01-01 00:00:48.702369   971  1532 D NxpTml  : PN54X - I2C Write successful.....
01-01 00:00:48.702418   971  1532 D NxpTml  : PN54X - Posting Fresh Write message.....
01-01 00:00:48.702499   971  1532 D NxpTml  : PN54X - Tml Writer Thread Running................
01-01 00:00:48.702605   971  1534 D NxpHal  : write successful status = 0x0
01-01 00:00:48.707096   971  1531 D NxpTml  : PN54X - I2C Read successful.....
01-01 00:00:48.707226   971  1531 D NxpNciR : len =  26 > 40011700030E03000600010203818202C800FF02000405080126
01-01 00:00:48.707273   971  1531 D NxpTml  : PN54X - Posting read message.....
01-01 00:00:48.707380   971  1534 D NxpHal  : read successful status = 0x0
01-01 00:00:48.707434   971  1534 D NxpHal  : NxpNci> FW Version: 8.1.26
01-01 00:00:48.707479   971  1534 D NfcAdaptation: NfcAdaptation::HalDeviceContextDataCallback: len=26
01-01 00:00:48.707607   971  1529 I BrcmNfcNfa: NFC received rsp gid:0
01-01 00:00:48.707680   971  1529 I BrcmNfcNfa: nci_proc_core_rsp opcode:0x1
01-01 00:00:48.707724   971  1529 D NfcAdaptation: NfcAdaptation::HalIoctl
01-01 00:00:48.707768   971  1529 D NxpHal  : phNxpNciHal_ioctl : enter - arg = 7
01-01 00:00:48.707817   971  1529 D NxpFwDnld: Allocating Mem for Dnld Context..
01-01 00:00:48.707912   971  1529 D NxpExtns: const nxp::CNfcParam* nxp::CNfcConfig::find(const char*) const found NXP_FW_NAME=libpn547_fw.so
01-01 00:00:48.708232   971  1531 D NxpTml  : PN54X - Read requested.....
01-01 00:00:48.708306   971  1531 D NxpTml  : PN54X - Invoking I2C Read.....
01-01 00:00:48.710857   971  1529 D NxpFwDnld: @@@/system/vendor/firmware/libpn547_fw.so
01-01 00:00:48.710978   971  1529 D NxpFwDnld: FW Image Length - ImageInfoLen 34590
01-01 00:00:48.711015   971  1529 D NxpFwDnld: FW Image Info Pointer - pImageInfo 8a4d0430
01-01 00:00:48.711047   971  1529 D NxpFwDnld: FW Major Version Num - 1
01-01 00:00:48.711077   971  1529 D NxpFwDnld: FW Minor Version Num - 26
01-01 00:00:48.711109   971  1529 D NxpFwDnld: FW Image Length - 34590
01-01 00:00:48.711140   971  1529 D NxpFwDnld: FW Image Info Pointer - 8a4d0430
01-01 00:00:48.711175   971  1529 D NxpHal  : FW version for FW file = 0x126
01-01 00:00:48.711207   971  1529 D NxpHal  : FW version from device = 0x80126
01-01 00:00:48.711236   971  1529 D NxpHal  : FW update not required
01-01 00:00:48.711268   971  1529 E NxpFwDnld: Freeing Mem for Dnld Context..
01-01 00:00:48.711302   971  1529 D NxpHal  : phNxpNciHal_ioctl : exit - ret = 0
01-01 00:00:48.711337   971  1529 I BrcmNfcNfa: fw_update required  -> 0
01-01 00:00:48.711368   971  1529 I BrcmNfcNfa: FW Version: 8.1.26
01-01 00:00:48.711398   971  1529 D NfcAdaptation: NfcAdaptation::HalIoctl
01-01 00:00:48.711430   971  1529 D NxpHal  : phNxpNciHal_ioctl : enter - arg = 9
01-01 00:00:48.711457   971  1529 D NxpHal  : phNxpNciHal_ioctl : exit - ret = 0
01-01 00:00:48.711494   971  1529 D NfcAdaptation: NfcAdaptation::HalClose
通过对比 log 记录可以确认此函数执行顺序应该与出错时的执行顺序一致。
此 log 中,先是执行了 0x0(NCI_MSG_CORE_RESET) 的操作,然后再执行了 0x1(NCI_MSG_CORE_INIT),在执行  NCI_MSG_CORE_INIT 后可能由于某些原因导致了 NFC 被关闭,然后状态被设置成了 2 (CORE_INIT)->0 (NONE)
【上述变量中的 NCI_MSG_CORE_RESET 和  NCI_MSG_CORE_INIT 定义在   nci_defs.h 中】

接下来就是对于 nfc_ncif_proc_init_rsp 的分析,从函数描述中可以得知此函数的作用是用于响应 init 操作的。
在该函数中定义了一个 UINT8 类型的变量 status,并且最终通过该变量来控制 NFC 的 enable 状态(nfc_enabled (status, NULL);),在最终设值之前对status进行打印,发现 status 的值为 3(NCI_STATUS_FAILED),于是在函数中对 status 进行赋值的地方都打印了一遍 status 的值,发现是在执行了最后一个 else 分支的代码后才被赋值成 NCI_STATUS_FAILED
else
{
#if(NXP_EXTNS == TRUE)
status = NCI_STATUS_FAILED;
retry_cnt = 0;
#endif
NFC_TRACE_DEBUG1 ("nfc_ncif_proc_init_rsp, init failed status=%d", status);// add by linqihan@wisky
nfc_enabled (status, NULL);
GKI_freebuf (p_msg);
}
因此可以判断该函数没有走进最后一个 status == NCI_STATUS_OK 的分支
if (status == NCI_STATUS_OK
#if(NXP_EXTNS == TRUE)
&&
fw_status == NCI_STATUS_OK
&&
NCI_STATUS_OK == fw_mw_ver_status
#endif
)
{
...
}
通过对三个判读值的打印得出,由于 fw_mw_ver_status 的返回值为 255 因此没有执行此分支内容,将该变量的判断代码移除后可以正常打开NFC。
fw_mw_ver_status 是通过 HAL_NFC_IOCTL_FW_MW_VER_CHECK 的 ioctl 操作获取的返回值,咨询 FAE  反馈的结果是,此变量对应的是固件版本的状态,目前固件下载是OK的,可以屏蔽该变量判断,但是仍需要后期查找问题原因。
nfc_cb.p_hal->ioctl(HAL_NFC_IOCTL_FW_MW_VER_CHECK, &fw_mw_ver_status);


猜你喜欢

转载自blog.csdn.net/zhujini2b/article/details/80004084
今日推荐