Skip to content

Nano 33 BLE NFC driver - trying to set one up #440

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Gerriko opened this issue Apr 1, 2022 · 14 comments
Open

Nano 33 BLE NFC driver - trying to set one up #440

Gerriko opened this issue Apr 1, 2022 · 14 comments

Comments

@Gerriko
Copy link
Contributor

Gerriko commented Apr 1, 2022

I spotted an article showing how to link precompiled libraries inside Arduino. So I thought to try this out with my Arduino Nano 33 BLE board as the Nordic Semiconductor's nRF52 SDK for the nRF52840 SoC uses two precompiled libraries to handle part of the NFC tag functionality (namely nfc_t2t_lib_#### and nfc_t4t_lib_####).

So I created a new library folder inside my Arduino libraries folder and gave it a name (e.g. nRF52_NFC). Inside this folder I then created a folder called cortex-m4 and inside this another one called fpv4-sp-d16-softfp.

I then went to the ./components/nfc/t2t_lib folder (for t2t_lib) within my Nordic Semiconductor nRF52 SDK folder and copied nfc_t2t_lib.h and nfc_t2t_lib_gcc.a. The nfc_t2t_lib.h file went inside the library folder (e.g. nRF52_NFC) and the nfc_t2t_lib_gcc.a file went inside fpv4-sp-d16-softfp. Then nfc_t2t_lib_gcc needed to be renamed to libnfc_t2t_lib.a. The "lib" prefix is required.

I then created my library.properties file within the library folder and added the following, in addition the standard requirements:

architectures=mbed_nano
precompiled=true
includes=nfc_t2t_lib.h
ldflags=-lnfc_t2t_lib

This all worked, as in, I could get Arduino to accept the .a file as a precompiled library... but that is only 1% of the solution.

As soon as I add the function nfc_t2t_setup(nfc_callback, NULL); or nfc_t4t_setup(nfc_callback, NULL); inside my Arduino code (setup routine) all the interface issues/errors start.

Note that for the nfc_callback I simply added this function inside my Arduino code.

/**
 * @brief Callback function for handling NFC events.
 */
static void nfc_callback(void * p_context, nfc_t2t_event_t event, const uint8_t * p_data, size_t data_length)
{
    (void)p_context;

    switch (event)
    {
        case NFC_T2T_EVENT_FIELD_ON:
            Serial.println("\r\nNFC_T2T_EVENT_FIELD_ON");
            break;
        case NFC_T2T_EVENT_FIELD_OFF:
            Serial.println("\r\nNFC_T2T_EVENT_FIELD_OFF");
            break;
        default:
            break;
    }
}

This is where I need help. For example, if I add in the functions from nfc_platform.h, for example, it then bumps into clock related issues. So I am not sure where mbedOS clock drivers can be used versus relying on nRF drivers for clocks etc.

Before I try take this further, has anyone looked at adding NFC as part of making compatible ArduinoCore-mbed library.

Any guidance appreciated in tackling this issue.

@Gerriko
Copy link
Contributor Author

Gerriko commented Apr 1, 2022

@datoslabs
Copy link

@Gerriko, have you tried using the Arduino-mbed build-in PN512 driver? I started researching the feasibility of using Arduino Nano 33 BLE as NFC controller today and came across your posts in the Arduino Forum; based on Nordic's SDK documentation, it appears that Adafruit NFC Shield library is compatible with Nordic's PCA10040 nRF52 DK, hence, I am wondering if it might work with Nano 33 BLE.

@Gerriko
Copy link
Contributor Author

Gerriko commented Jul 22, 2022

The PN512 is a NFC front-end while the nRF52840 (Nano 33 BLE) emulates a type-2 or type-4 tag (like an NFC card, for example). As such the mbed PN512 driver would not be unsuitable for this application. You would probably use the NFC EEPROM driver to help here (https://os.mbed.com/docs/mbed-os/v6.15/apis/nfc-eeprom.html) - for handling messaging etc. rather than a low-level clock signal and data transfer driver.

The best source for how to do it is from Particle.io's implementation for their Particle Argon/Xenon boards.
https://github.com/particle-iot/device-os
Here, from what I could gather, they implemented the nrfx/HAL clock drivers.

I could do that but then this but, in my opinion, this probably overrides (or maybe conflicts) with Mbed's clock handling (a bit too low-level for me). As such I am still waiting for guidance on this clock implementation use-case.

@datoslabs
Copy link

I am still new to this so I apologize in advance if I am mixing things. I found an example on PlatformIO NFC smart poster examples for nRF52 dev boards using mbed OS: https://github.com/platformio/platform-nordicnrf52/blob/master/examples/mbed-rtos-nfc/src/main.cpp; it uses the included PN512 driver to initialize NFCController to receive and send messages. I was under the impression that nRF52 can be used as an NFC EEPROM as well as NFC Controller, am I mistaken?

@Gerriko
Copy link
Contributor Author

Gerriko commented Jul 22, 2022

No you are helping bring fresh eyes to solving this issue. Yes, that example is emulating a tag alright. The problem here is how the PN512 driver is initialised is not compatible with the nRF52840 board. The nRF52840 has two dedicated pins for its NFC tag which need to be driven by timer4 (I believe) via a clock timer.

If you look carefully at the example you gave, the constructor of the class NFCProcess, _pn512_transport is initialised for SPI - see PN512SPITransportDriver

_pn512_transport (PinName mosi, PinName miso, PinName sclk, PinName ssel, PinName irq, PinName rst);

@Gerriko
Copy link
Contributor Author

Gerriko commented Jul 23, 2022

it uses the included PN512 driver to initialize NFCController to receive and send messages

Yes you are right! I hadn't considered this. I see this driver class is initialised via
nfc_transceiver_t *PN512Driver::initialize(nfc_scheduler_timer_t *scheduler_timer)
which just means I need to know which timer to use (as per original question) for thenfc_scheduler_timer_t parameter.

Regarding your other question " I was under the impression nRF52 can be used as an NFC EEPROM as well as NFC Controller"... I was under the impression that it can only act as NFC EEPROM.

You need to look for mbed's implementation of the EEPROM driver, which is handled by M24srDriver

This implements the ST M24SR series Dynamic NFC Tags, which are I2C based. I suspect that all that needs to be done here is change the I2C transport driver to suit nRF52.

@datoslabs
Copy link

The nRF52840 has two dedicated pins for its NFC tag which need to be driven by timer4 (I believe) via a clock timer.

WRT the 2 dedicated pins, are you referring to D8/P0.10 and D7/P0.09? My understanding is that these 2 pins are for connecting with the NFC antenna but to communicate with the NFC controller, one would still need to use I2C or SPI. On Nano 33 BLE, SPI uses D11(Mosi), D12(Miso), D13(SCK), + another Digital Pin for CS, which matches with the initialization of PN512SPITransportDriver. If one utilizes an external NFC controller like the Adafruit NFC Shield, they would need to physically connect the external controller to D11-13 if they want to interface with the controller via SPI; however, since nRF52840 has a built-in NFC controller, we can skip the physical connection but would still need to interface via SPI, is this incorrect?

@datoslabs
Copy link

I think our last post crossed paths during transmission, lol. You are right that nRF52 only supports NFC Tag (type 2 and 4) and not NFC Controller (ie ability to initiate and read from an NFC tag among other functionalities); being new to NFC spec, I was confused by the different terminologies.

WRT M24srDriver, I had noticed it in the Mbed OS Github but did not look under the hood as I may need the functionality offered in type 4; having said that, I will spend more time to understand it better.

I am unsure why it is required to call *PN512Driver::initialize(nfc_scheduler_timer_t *scheduler_timer); based on the PlatformIO demo code I posted earlier; it appears that instantiating PN512Driver with PN512SPITransportDriver is sufficient. The NFCController (referring to the Mbed OS library, not the NFC standard/spec) then registers itself as the delegate/callback to handle NFC events, isn't this what you are trying to achieve using the Nano 33 BLE NFC feature?

@Gerriko
Copy link
Contributor Author

Gerriko commented Jul 23, 2022

My understanding is that these 2 pins are for connecting with the NFC antenna but to communicate with the NFC controller, one would still need to use I2C or SPI. On Nano 33 BLE, SPI uses D11(Mosi), D12(Miso), D13(SCK), + another Digital Pin for CS, which matches with the initialization of PN512SPITransportDriver

I checked the nRF52 documentation again and from what I can gather, NFC uses Direct Memory Access (EasyDMA with 106 kbps data rate) for reading and writing of data packets from and to the Data RAM and not I2C or SPI. The documentation is quite detailed. For example, it tells us that the NFCT peripheral includes a frame timing controller that continuously keeps track of the number of the 13.56 MHz RF carrier clock periods since the end of the EoF of the last received frame. Hence the need for a dedicated timer etc.

https://infocenter.nordicsemi.com/index.jsp?topic=%2Fps_nrf52840%2Fnfc.html&cp=4_0_0_5_13

https://infocenter.nordicsemi.com/index.jsp?topic=%2Fps_nrf52840%2Feasydma.html&cp=4_0_0_3_5

@datoslabs
Copy link

Thank you for the explanation, it makes more sense to me now. It looks like the Mbed OS's PN512 driver is intended for use with an external NFC addon/shield based on PN512 chip, not nRF52's build-in NFC feature.

I have been doing additional research and saw the XIAO BLE NFC tutorial (nRF52840) which uses Adafruit nRF52 Arduino Core. Based on the source code https://github.com/0hotpotman0/BLE_52840_Core/tree/main/libraries/nfc (I am not sure if this is the official repository for XIAO BLE), it appears to take the same approach you have taken linking to pre-compiled t2t and t4t library. Upon further investigation, it looks like it's calling libnfc_t2t_lib_gcc's nfc_t2t_emulation_start(void) method with dependencies to nrfx library. Have you come across this?

@Gerriko
Copy link
Contributor Author

Gerriko commented Jul 26, 2022

Brilliant. Good to know. I had not seen this before.

The part answer to my question is...

#include "nrf_clock.h"

I was wondering if mbed clock functions could be used instead. But failing that,  this header file will do the trick.

I would be curious to know if this library works out the box.

@Gerriko
Copy link
Contributor Author

Gerriko commented Jul 30, 2022

@datoslabs I had a chance to look at this again in more detail. I tried the library you referred to but it did not work out the box.

So I went back to where I had started from and found that I had a couple of issues with files/folders missing from the Arduino Core.

Firstly, "nrf_nfct.h" is missing. It should've been included inside:
/packages/arduino/hardware/mbed_nano/3.2.0/cores/arduino/mbed/targets/TARGET_NORDIC/TARGET_NRF5x/TARGET_SDK_15_0/modules/nrfx/hal
To resolve I added a hal folder in my draft library and inserted the file. This resolved the matter.

Secondly, the nfc platform folder (from nRF52 SDK components/nfc) is required. Then nrfx_nfct.h needs to be added as this is called by nfc_platform.h
To resolve I simply added the platform folder into my library source folder.

Thirdly, t2t_parser/t4t_parser folders required for message parsing as well as ndef folders. I found that the original ndef folder from the nRF52 SDK is split into folders and this causes problems too. You have to manually flatten, which takes a good while.

Then there are NFC config issues relating to sdk_config.h. In particular the LF Clock needs enabling. I have not been able sort this out.

I've also discovered that buried within the sdk_config.h (line 12057) is #include "nrf5x_lf_clk_helper.h"
I have no idea what the heck this is. It is unique to Arduino. Anyhow is appears that sdk_config.h must be called before mbed_config.h as I get warnings, which originate from nrf5x_lf_clk_helper.h, but shouldn't be warnings as things like MBED_CONF_NORDIC_NRF_LF_CLOCK_SRC are already set in mbed_config.

That's as far as I've got. Let's just say this is proving rather messy to resolve. But I have made progress.

@Gerriko
Copy link
Contributor Author

Gerriko commented Jul 31, 2022

I've hacked together something that now compiles but it still is not working when uploaded to my nano board. Not sure if it's software or hardware (e.g. antenna).
Not sure what's the best way to share for testing as it is very messy and hacky as I had to disable quite a few sdk_config defines etc in the libraries as they were not being detected correctly. As such, I cannot guarantee it won't mess up the board.

@Gerriko
Copy link
Contributor Author

Gerriko commented Oct 11, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants