PN7160 with nRF52840

Hello,

I’m using an external NFC reader/controller (NXP PN7160A1HN/C100E) connected via I2C to an nRF52840 module (Raytac MDBT50Q-1MV2) on a custom PCB. (Programming is via SWD using an nRF52840 DK as the debug probe.) 

My current software environment is nRF Connect SDK (NCS) v3.2.0 in VS Code (Windows 11) and Zephyr RTOS v4.2.99. The goal is to start RF discovery and read the UID of a 13.56 MHz passive card using the PN7160 (NCI-over-I2C).

I attempted to integrate PN7160 the “typical Zephyr way” by only editing:

  • src/main.c

  • boards/nrf52840dk_nrf52840.overlay

  • prj.conf

I can configure the I2C pins and PN7160 GPIOs (VEN/IRQ), but initialization is failing (I2C -EIO/NACK during probe or first command), and I’m not sure if my integration approach is correct.

Questions:

  1. In NCS/Zephyr, is it possible to programm PN7160 by only changing `main.c` + `nrf52840dk_nrf52840.overlay` + `prj.conf`, or is it expected that PN7160 requires a proper custom driver?

  2. If a driver is required: what is the recommended approach in NCS to add it (devicetree binding YAML + Kconfig + CMake + driver source), and should it be packaged as an external Zephyr module (zephyr/module.yml + EXTRA_ZEPHYR_MODULES)? Are there example codes how to do this (like a public github repo, I namely could not find it)?

  3. Are there known NCS v3.2.0 / Zephyr 4.2.99 I2C/TWIM behaviors that can cause -EIO on probing/first writes that I should handle differently?

If you have any other handy comments that would help, I’d appreciate them

Thank you!

  • Hi,

    In NCS/Zephyr, is it possible to programm PN7160 by only changing `main.c` + `nrf52840dk_nrf52840.overlay` + `prj.conf`, or is it expected that PN7160 requires a proper custom driver?

    For this I believe you need to create a custom driver. 

    If a driver is required: what is the recommended approach in NCS to add it (devicetree binding YAML + Kconfig + CMake + driver source), and should it be packaged as an external Zephyr module (zephyr/module.yml + EXTRA_ZEPHYR_MODULES)? Are there example codes how to do this (like a public github repo, I namely could not find it)?

    You can for instance have a look at the course on how to do this here.

    Are there known NCS v3.2.0 / Zephyr 4.2.99 I2C/TWIM behaviors that can cause -EIO on probing/first writes that I should handle differently?

    I am not sure if you used an wrong device driver here perhaps, or simply refered to one that that doesn't exist, but I guess it could make sense that this would result in an input/output error.

    Regards,

    Elfving

  • Hi Elfving,

    Thanks for your reply!

    I started implementing the PN7160 as a custom Zephyr driver (NCS v3.2.0 / Zephyr v4.2.99). Could you please confirm if this overall structure is reasonable for an application-local driver (not an external module yet)?

    • NFC/CMakeLists.txt

    • NFC/src/main.c

    • NFC/prj.conf

    • NFC/boards/nrf52840dk_nrf52840.overlay

    • NFC/Kconfig

    • NFC/dts/bindings/nfc/nxp,pn7160.yaml

    • NFC/drivers/nfc/pn7160/CMakeLists.txt

    • NFC/drivers/nfc/pn7160/Kconfig

    • NFC/drivers/nfc/pn7160/pn7160.c

    • NFC/drivers/nfc/pn7160/pn7160.h

    Second question: in the NCI-over-I2C flow, after the host sends the first NCI command (e.g., CORE_RESET), the PN7160 should respond (RSP and/or NTF). In my case, the first TX happens but I don’t reliably get the expected response/IRQ (often -EIO/NACK or a timeout waiting for IRQ).

    From a Zephyr architecture point of view: is this most likely caused by the driver implementation (pn7160.c handling of IRQ/I2C read framing), or could it also be caused by devicetree/binding configuration (IRQ polarity/pulls, wrong I2C instance/pinctrl, etc.)?

    Finally, do you may know any public examples of PN7160 integration on Zephyr/NCS (even if not an official driver), or a similar NCI-over-I2C controller driver that’s a good reference for the IRQ+I2C transaction pattern?

    Thanks again for your time.

    Regards,
    Newtechlearner

  • newtechlearner said:
    I started implementing the PN7160 as a custom Zephyr driver (NCS v3.2.0 / Zephyr v4.2.99). Could you please confirm if this overall structure is reasonable for an application-local driver (not an external module yet)?

    Looks good to me.

    newtechlearner said:
    Second question: in the NCI-over-I2C flow, after the host sends the first NCI command (e.g., CORE_RESET), the PN7160 should respond (RSP and/or NTF). In my case, the first TX happens but I don’t reliably get the expected response/IRQ (often -EIO/NACK or a timeout waiting for IRQ).

    But you do already have the driver working, and do get responses? Do you get the responses you want, they just come later than expected, or are some responses simpy omitted. I don't usually work with things that do not have readymade drivers in Zephyr, so it's hard to say. But HW is typically at fault in situations like these as well. Getting a logic analyzer trace here would be an idea.

    newtechlearner said:

    Finally, do you may know any public examples of PN7160 integration on Zephyr/NCS (even if not an official driver), or a similar NCI-over-I2C controller driver that’s a good reference for the IRQ+I2C transaction pattern?

    No, I tried looking for this earlier, but had issues finding anything, unfortunately. I assume someone NXP will have a reference though.

    Regards,

    Elfving

  • But you do already have the driver working, and do get responses? Do you get the responses you want, they just come later than expected, or are some responses simpy omitted. I don't usually work with things that do not have readymade drivers in Zephyr, so it's hard to say. But HW is typically at fault in situations like these as well. Getting a logic analyzer trace here would be an idea.

    Hi Elfving,

    Thanks for the follow-up.

    Right now I don’t reliably get the expected NCI response after the first TX (e.g., CORE_RESET). In many runs it’s a timeout waiting for IRQ, and in other runs I see -EIO/NACK on I2C reads when attempting to fetch the response frame. So it’s not just “responses arriving late” — they often appear missing.

    A few points that might help narrow it down:

    • The PN7160 hardware (PCB, power rails, pull-ups) has not changed. This same PN7160 board previously worked with an ESP32-C3 (same PN7160 settings; only the MCU + I2C pin mapping changed).

    • On nRF52840 + Zephyr, I can control VEN and see the PN7160 ACK at 0x28 in some tests, but the NCI exchange is inconsistent. (So I think the change of the I2C pin mapping did not affect since I can see the 0x28)

    Given that, I currently suspect a software integration issue, most likely one of:

    1. IRQ configuration mismatch in Zephyr (polarity / pull-up / edge vs level behavior / open-drain assumptions), and/or

    2. NCI-over-I2C read pattern/framing in my custom driver (e.g., PN7160 may NACK reads when no data is ready, and my driver might be handling that incorrectly).

    I agree a logic analyzer trace is the best next step. I can capture:

    • SDA/SCL + IRQ + VEN during: power-on → CORE_RESET write → attempted reads

    • exact timestamps relative to the firmware logs

    From your experience with Zephyr/NCS bring-up: what would you recommend as the next steps or best practices when developing and debugging custom driver code like this, especially to verify whether the issue lies in the driver implementation itself or in the underlying hardware configuration on the nRF52 side? What should I do?

    Thank you very much,
    Newtechlearner

  • Could be something with the driver. 

    You say that this worked previously with the same PN7160 HW, and the same custom board. Is the custom board here also the same? The only difference being you having swapped the ESP32-C3 for a nRF52840 module? From that we can assume that there is not something like a lack of resistors being the problem, but I am still a bit uncertain about this part. Are you sure the connections here are ok?

    Have you tested that the overlay files you use for this module etc. works okay though? So you have tried doing other things with this nRF module, like BLE and flashing an LED etc?

    It would also be an idea to scan for devices on the i2c line. You haven't tested any other i2c devices with this set-up I assume? If you had another device that Zephyr supports by default on hand it would be very practical.

    newtechlearner said:

    From your experience with Zephyr/NCS bring-up: what would you recommend as the next steps or best practices when developing and debugging custom driver code like this, especially to verify whether the issue lies in the driver implementation itself or in the underlying hardware configuration on the nRF52 side? What should I do?

    newtechlearner said:
    From your experience with Zephyr/NCS bring-up: what would you recommend as the next steps or best practices when developing and debugging custom driver code like this

    It is hard to give a general response to that. It might just be that I haven't worked to much on debugging in these situations too much, but i often find that there is something basic that is missing. Getting a logic analyzer trace is a good idea.

    Besides that it is an idea to have a look here and here in case you've forgotten anything.

    Regards,

Related