Build and Flash Firmware
Use the GroveNFC development API to customize the module's functionality, NFC processing, and host protocol. Firmware runs on the RP2040 and links against the supplied NFC static libraries.
Obtain the Firmware Project
The GroveNFC repository provides product firmware, hardware information, and development packages. To customize module firmware, download the 20261001 API development package. It contains the CMake project, application source, interface headers, and precompiled NFC libraries.
Cloning the repository alone does not place CMakeLists.txt at its root. Extract the development package and build from its GroveNFC_API-20261001 directory.
For a command-line workflow:
mkdir -p grovenfc-development
cd grovenfc-development
curl -fL https://raw.githubusercontent.com/NFC-funs/GroveNFC/main/API/GroveNFC_API-20261001.zip -o GroveNFC_API-20261001.zip
unzip GroveNFC_API-20261001.zipKeep the supplied libNFC directory: the NFC libraries are required for linking. Ready-to-install product firmware in the repository's Firmware directory is separate from the customizable API project, and may expose additional features.
Development Environment
Pico SDK
2.3.0
C / C++
C11 / C++17
Board target
pico
ARM toolchain
13_3_Rel1
picotool
2.3.0
USB dependencies
TinyUSB and FatFs
Earlier projects use Pico SDK 2.1.0. Match the SDK and dependencies to the project you are building.
Project Structure
Pico_NFC.c
Initialization, dual-core loops, and tag Flash storage
4-I2C/X_I2C.h / .c
Slave address, register layout, and IIC interrupts
4-I2C/X_RegPara.h
Mode, RF, CRC, status, and command constants
4-I2C/I2C_Function.c
NFC operations triggered by register writes
4-I2C/X_Ver.h
Hardware and firmware version identifiers
2-NFC/ISO14A
ISO14443A selection and NTAG application logic
2-NFC/ISO14B
ISO14443B application logic
2-NFC/ISO15
ISO15693 inventory and memory operations
2-NFC/Felica
FeliCa application logic
libNFC
Hardware interface headers and precompiled NFC libraries
1-USB
USB descriptors, MSC, CDC, and FAT12
CMakeLists.txt
Pico SDK configuration and library linking
Core1 processes NFC operations requested through IIC. Core0 handles USB tasks and Flash storage. Keep host transactions serialized because the reference IIC implementation has one pending-command slot and a shared data buffer.
Prepare the SDK and Build Tools
Install Git, CMake, a native build tool such as Make or Ninja, and an ARM bare-metal toolchain providing arm-none-eabi-gcc. Match the toolchain to the project configuration where possible. Install curl and unzip if using the download commands above.
From the grovenfc-development directory, obtain the matching Raspberry Pi Pico SDK and its submodules:
Submodules supply dependencies such as TinyUSB. Confirm that these paths exist before configuring:
pico-sdk/pico_sdk_init.cmakepico-sdk/lib/tinyusb/lib/fatfs/source/ff.cGroveNFC_API-20261001/libNFC/ISO14A/lib_ps_iso14a.a
The FatFs path above is used directly by this project's CMake configuration. If it is absent, resolve the SDK dependency layout before building.
Build the Firmware
With the SDK and extracted project alongside each other in grovenfc-development:
Run these commands in the directory containing Pico_NFC.c and CMakeLists.txt. Use build-local rather than the distributed build directory, which contains an existing machine-specific CMake cache. If the SDK is installed elsewhere, replace the PICO_SDK_PATH value with its absolute path.
The output directory contains:
build-local/Pico_NFC.uf2
Firmware image for UF2 installation
build-local/GroveNFC_API_YYYYMMDD_HHMM.uf2
Timestamped copy of the UF2 image
build-local/Pico_NFC.elf
Executable with debugging information
build-local/Pico_NFC.bin / .hex
Additional firmware formats
To install the UF2, enter the board's RP2040 BOOTSEL USB mode using the procedure for your hardware revision. Copy the UF2 to the bootloader drive, usually named RPI-RP2. The device restarts after installation. The bootloader drive is separate from GroveNFC's normal USB tag-data storage drive.
After restarting, read the hardware and firmware version registers and run the IIC REQA example to check the custom firmware's host interface. Do not infer feature support from the filename alone.
Build Troubleshooting
PICO_SDK_PATH is missing or invalid
Point it to the SDK root containing pico_sdk_init.cmake
arm-none-eabi-gcc cannot be found
Install the ARM bare-metal toolchain and add its executable directory to PATH
TinyUSB / FatFs files are missing
Initialize SDK submodules and check the exact FatFs path used by CMake
lib_ps_*.a cannot be found
Preserve the development package's directory structure and supplied libraries
CMake refers to another machine's paths
Configure a fresh build directory rather than reusing the distributed cache
Built firmware lacks a product feature
Check the API project's handlers and firmware compatibility table; product firmware and API firmware have different feature coverage
NFC Application Flows
ISO14443A
Wake/discover, anticollision, select, then exchange tag commands
X_RF14443A_GetUid, X_RF14443A_AntiCL1, X_RF14443A_SelCL1, cascade-level 2 equivalents
ISO14443B
Request, assign/select, then read identification data
X_RF14443B_reqb, X_RF14443B_attrib, X_RF14443B_getuid
FeliCa
Activate reader reception and perform polling
X_Felica_req
ISO15693
Inventory, then addressed block operations
X_15693_getuid, X_15693_readsingleblock, X_15693_writesingleblock, X_15693_readmultiblock
Initialize the system and NFC hardware, enable the RF field, initialize the protocol's PIO receiver, perform the operation, deinitialize the receiver, and disable the field. The earlier example application demonstrates these flows through TEST_14443A, TEST_14443B, TEST_FELICA, TEST_15693ASK, and TEST_15693FSK build switches.
The ISO14443A UID helper supports the 4-byte and 7-byte flows. Its output buffer includes cascade data and BCC bytes; allocate the buffer required by the API and extract the UID rather than presenting the entire buffer as a UID. The X_RF14443A_Reqa helper sends WUPA (0x52) internally despite its name.
ISO15693 inventory returns response metadata alongside the UID. Pass the API's response buffer to subsequent application helpers according to their declarations. Block size and count depend on tag type; use X_15693_info where applicable.
Debugging and Storage
Debug UART
UART1, 921600 baud, TX GPIO4, RX GPIO5
BUSY output
GPIO19, active high
IIC
I2C0, SDA GPIO16, SCL GPIO17
Tag RAM
4096 bytes
Flash tag storage
64 KiB, sixteen 4 KiB slots
USB file-storage region
128 KiB, FAT12
GPIO numbers identify internal signals. Confirm signal exposure against your board revision. USB MSC and internal FatFs share storage; coordinate access so that the host and firmware do not modify the same files concurrently.
Extending the Host Interface
Implement handlers before exposing new mode values or shortcut commands. Keep register definitions and dispatch conditions consistent, enforce buffer bounds, and provide completion handling for long operations. Validate the product-facing behavior of your custom build before distributing it.
Consult the IIC Operation Guide for reference-firmware compatibility limits. The API Header Reference provides declarations and constants for module development.