NXP

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

2019-07-12 11:15发布

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=1BrcmNfcNfa: 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::HalIoctlNxpHal : phNxpNciHal_ioctl : enter - arg = 9NxpHal : phNxpNciHal_ioctl : exit - ret = 0NfcAdaptation: NfcAdaptation::HalCloseNxpTml : PN54X - Write requested.....NxpTml : PN54X - Invoking I2C Write.....NxpNciX : len = 10 > 21030703800181018201其中ioctl的指令为fw版本检查:
HAL_NFC_IOCTL_FW_MW_VER_CHECK (hardwarelibhardwareincludehardware fc.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 (externallibnfc-ncisrc fc fc fc_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);#elsenci_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(externallibnfc-ncisrc fc fc fc_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(externallibnfc-ncisrc fc ci ci_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::HalWrite01-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 > 2000010001-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 = 0x001-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 > 40000300100001-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 = 0x001-01 00:00:48.698468 971 1534 D NfcAdaptation: NfcAdaptation::HalDeviceContextDataCallback: len=601-01 00:00:48.698576 971 1529 I BrcmNfcNfa: NFC received rsp gid:001-01 00:00:48.698641 971 1529 I BrcmNfcNfa: nci_proc_core_rsp opcode:0x001-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 : #### 101-01 00:00:48.698743 971 1529 E BrcmNfcNfa: reset notification sending core init01-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::HalWrite01-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 > 20010001-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 = 0x001-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 > 40011700030E03000600010203818202C800FF0200040508012601-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 = 0x001-01 00:00:48.707434   971  1534 D NxpHal  : NxpNci> FW Version: 8.1.2601-01 00:00:48.707479   971  1534 D NfcAdaptation: NfcAdaptation::HalDeviceContextDataCallback: len=2601-01 00:00:48.707607   971  1529 I BrcmNfcNfa: NFC received rsp gid:001-01 00:00:48.707680   971  1529 I BrcmNfcNfa: nci_proc_core_rsp opcode:0x101-01 00:00:48.707724   971  1529 D NfcAdaptation: NfcAdaptation::HalIoctl01-01 00:00:48.707768   971  1529 D NxpHal  : phNxpNciHal_ioctl : enter - arg = 701-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.so01-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.so01-01 00:00:48.710978   971  1529 D NxpFwDnld: FW Image Length - ImageInfoLen 3459001-01 00:00:48.711015   971  1529 D NxpFwDnld: FW Image Info Pointer - pImageInfo 8a4d043001-01 00:00:48.711047   971  1529 D NxpFwDnld: FW Major Version Num - 101-01 00:00:48.711077   971  1529 D NxpFwDnld: FW Minor Version Num - 2601-01 00:00:48.711109   971  1529 D NxpFwDnld: FW Image Length - 3459001-01 00:00:48.711140   971  1529 D NxpFwDnld: FW Image Info Pointer - 8a4d043001-01 00:00:48.711175   971  1529 D NxpHal  : FW version for FW file = 0x12601-01 00:00:48.711207   971  1529 D NxpHal  : FW version from device = 0x8012601-01 00:00:48.711236   971  1529 D NxpHal  : FW update not required01-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 = 001-01 00:00:48.711337   971  1529 I BrcmNfcNfa: fw_update required  -> 001-01 00:00:48.711368   971  1529 I BrcmNfcNfa: FW Version: 8.1.2601-01 00:00:48.711398   971  1529 D NfcAdaptation: NfcAdaptation::HalIoctl01-01 00:00:48.711430   971  1529 D NxpHal  : phNxpNciHal_ioctl : enter - arg = 901-01 00:00:48.711457   971  1529 D NxpHal  : phNxpNciHal_ioctl : exit - ret = 001-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_FAILEDelse{#if(NXP_EXTNS == TRUE)status = NCI_STATUS_FAILED;retry_cnt = 0;#endifNFC_TRACE_DEBUG1 ("nfc_ncif_proc_init_rsp, init failed status=%d", status);// add by linqihan@wiskynfc_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);