Skip to content

Firmware Compatibility

This page is the cross-family reference for firmware developers. It maps firmware builds to PCB articles, defines the GPIO mux master table, describes board variant detection, the system architecture (config flow, coexistence, debug CLI), and provides a side-by-side pin-out comparison across product families.


Firmware Build Matrix

The EverTag platform uses three firmware builds across all product families. A single firmware binary can run on multiple PCB articles within its build group. The firmware detects the specific board variant at runtime.

Firmware Build MCU PCB Articles Product Family Application
Tag/Anchor (nRF54) PAN611 (nRF54L15) 230220, 232200, 232201 Tag nRF54 + Station Wirepas tag/anchor, NFC config, accelerometer (if populated)
Gateway (nRF54) PAN611 (nRF54L15) 232202, 232203, 232204 Station Wirepas gateway + ESP32 WiFi control
Tag/Anchor (nRF52) nRF52 230200, 230202, 230204, 230206 Tag nRF52 (legacy) Wirepas tag, sensor variants

nRF54 vs nRF52

The nRF54 (PAN611) and nRF52 are firmware-incompatible -- they use different ARM architectures and peripheral sets. The Tag/Anchor (nRF54) and Tag/Anchor (nRF52) builds share application-level concepts but are separate builds.

Tag/Anchor vs Gateway Mode

Station boards without gateway chips (232200, 232201) run the same Tag/Anchor firmware as the EverTag Tag nRF54 (230220) and operate as simple Wirepas anchors. An anchor participates in the mesh by relaying packets but is not a traffic sink -- it does not forward data to any IP network.

Station boards with WiFi or LTE (232202, 232203, 232204) run the Gateway firmware and operate in gateway mode. In gateway mode, the nRF54 acts as a Wirepas gateway node (not a simple anchor): it receives mesh data from tags/anchors and forwards it to the ESP32 via UART1 (Wirepas Dual-MCU API), which then routes it to the IP network via WiFi or LTE. This requires ESP32 WiFi control, coexistence arbitration, and the Dual-MCU API -- a fundamentally different application from simple anchoring.

The distinction matters for power management -- see Anchor vs Gateway Battery Behaviour below.

graph LR
    subgraph fw_nrf54_tag ["Tag/Anchor (nRF54) Build"]
        P230220["230220 Tag Base"]
        P232200["232200 Station Base"]
        P232201["232201 Station Bat"]
    end

    subgraph fw_nrf54_gw ["Gateway (nRF54) Build"]
        P232202["232202 Station WiFi"]
        P232203["232203 Station Bat+WiFi"]
        P232204["232204 Station Full"]
    end

    subgraph fw_nrf52 ["Tag/Anchor (nRF52) Build"]
        P230200["230200 Tag Base"]
        P230202["230202 Tag Temp"]
        P230204["230204 Tag Sound/Light"]
        P230206["230206 Tag Digital IO"]
    end

Pin-Out Reference Design

230220 is the reference

The 230220 (EverTag Tag nRF54 Base) is the pin-out reference design for all nRF54-based boards. It is the only board with completed schematics. All future nRF54 boards (232200, 232201, 232202, etc.) must adopt the 230220 pin assignments for shared peripherals to ensure firmware compatibility.

Station boards add pins for Station-specific features (power management, WiFi ESP32 interface, etc.) but must not reassign any pin that is defined in 230220.

Design Rules

  1. GPIO mux directions are preserved across all nRF54 board variants -- an output pin on 230220 must remain an output on all Station boards, and vice versa. This allows pins to be reassigned to different functions (e.g., SPI output → GPIO output for battery control) as long as the direction is respected.
  2. Peripheral initialization is conditional -- after detecting the board variant via ADC, the firmware initializes only the peripherals that are physically present
  3. Unused pins may be reassigned respecting direction -- on Station boards where the SPI accelerometer is not populated, the SPI pins are available for other functions (battery monitoring, future expansion) provided the output/input direction matches the 230220 reference assignment
  4. New boards must not conflict -- any new Station board design must use the 230220 pin assignments for all shared functions
  5. ST25DV04K NFC is present on all boards -- the external I2C NFC controller and 2-layer coil antenna is a standard component across the entire nRF54 platform
  6. nRF54 internal NFC pins (P1.02/P1.03) are GPIO reserve -- they are NOT used for NFC on any board; the ST25DV04K provides NFC on all variants

nRF54L15 SAADC Analog Input Channels

The nRF54L15 has 8 SAADC analog input channels (AIN0--AIN7), all on Port 1. Only these pins support analog-to-digital conversion via the SAADC peripheral. All other GPIO pins are digital-only.

Channel Pin QFN48 Pad Assignment Notes
AIN0 P1.04 13 I2C SCL (ST25DV04K) Occupied on all boards
AIN1 P1.05 12 I2C SDA (ST25DV04K) Occupied on all boards
AIN2 P1.06 11 BAT_VOLTAGE (battery variants) Resistor divider populated on 232201/232203
AIN3 P1.07 10 V_SAMPLE (board variant) Board variant detection on all boards
AIN4 P1.11 B3 Sensor / available Freed -- was UART1 TX (moved to P0.03)
AIN5 P1.12 B1 EXT_DETECT (extension ID) Extension board detection on all boards
AIN6 P1.13 B2 Sensor / available Freed -- was UART1 RX (moved to P0.04)
AIN7 P1.14 C2 Sensor / available Freed -- was ESP32_RESET (moved to P1.10)

Common Pitfall: Not All Port 1 Pins Have Analog

P1.02 and P1.03 are NFC pins (NFC1/NFC2) and do not have SAADC capability. P0.00 is a digital GPIO -- it does not support SAADC despite being used for variant detection (it uses a digital threshold comparator, not ADC). Always verify against this table when assigning analog functions.

Source: nRF54L15 Datasheet v1.0, Table 79 (QFN48 pin assignments). Cross-referenced with PAN B611-1 Product Specification Rev 1.0 which correctly identifies these 8 pins as "Digital I/O / Analog input".


GPIO Mux Master Table (nRF54)

This is the authoritative pin configuration for all nRF54-based boards. The table below is the hardware superset -- it shows every trace routed on the shared Station PCB. The PCB designer routes all pins; population differences (BOM variants) determine which peripherals are active.

Firmware views (Tag/Anchor vs Gateway) are described in the Firmware Architecture section.

Station PCB Pin Superset

These pins have the same mux direction on every nRF54 board. On the shared Station PCB, all traces are routed; peripheral footprints are populated or DNP per BOM variant.

Pin Name Mux Direction Peripheral Function 230220 Tag 232200 Station 232202+ Gateway Notes
A3 P0.00 Input GPIO B_VARIANT Variant detect Variant detect Variant detect Digital GPIO threshold (not SAADC)
1 P0.01 Output GPIO LED_DATA Red LED SK6812MINI-E x2 SK6812MINI-E x2 Daisy-chain: LED1 system + LED2 telematics
2 P0.02 Output UART TX UART0 TX Debug TX Debug TX Debug TX Debug CLI (PC)
19 P2.07 Input UART RX UART0 RX Debug RX Debug RX Debug RX Debug CLI (PC)
3 P0.03 Output SPI CLK SPI CLK ACC CLK Available (O) UART1 TX ACC on 230220; UART1 TX to ESP32 on GW
4 P0.04 Input SPI MISO SPI MISO ACC MISO Available (I) UART1 RX ACC on 230220; UART1 RX from ESP32 on GW
A2 P1.10 Output SPI MOSI SPI MOSI ACC MOSI Available (O) ESP32_RESET ACC on 230220; ESP32 enable/reset on GW
B4 P1.08 Output GPIO (CS) SPI CS ACC CS Available (O) Available (O) ACC on 230220; reassignable output on Stn
20 P2.08 Input GPIO (IRQ) ACC INT1 ACC INT1 Available (I) ESP32 READY ACC on 230220; ESP32 READY on GW
21 P2.09 Input GPIO (IRQ) IRQ ACC INT2 Available (I) Available (I) ACC on 230220; reassignable input on Stn
13 P1.04 Output I2C SCL I2C SCL ST25DV SCL ST25DV SCL ST25DV SCL NFC on all boards
12 P1.05 I/O I2C SDA I2C SDA ST25DV SDA ST25DV SDA ST25DV SDA NFC on all boards
A1 P1.09 Input GPIO ST25DV.GPO NFC GPO NFC GPO NFC GPO NFC on all boards
C1 P1.15 Input GPIO ST25DV.LPD NFC LPD NFC LPD NFC LPD NFC on all boards
22 P2.10 Output GPIO ST25DV.VCC NFC pwr enable NFC pwr enable NFC pwr enable NFC on all boards
18 P2.06 Input GPIO (pullup) SWITCH Button SW1 Service button Service button Side-actuated tactile switch
10 P1.07 Input (ADC) ADC V_SAMPLE Variant ADC Variant ADC Variant ADC Board ID
11 P1.06 Input (ADC) ADC (AIN2) BAT_VOLTAGE Reserved BAT_VOLTAGE BAT_VOLTAGE Battery divider on bat variants; reserved on 230220
B1 P1.12 Input (ADC) ADC EXT_DETECT Extension ADC Extension ADC Extension ADC Extension board ID
5 SWDCLK Input SWD Debug clock SWD SWD SWD
6 SWDIO I/O SWD Debug data SWD SWD SWD
23 nRESET Input Reset Reset Pull-up 100k Pull-up 100k Pull-up 100k Active low
D1 P1.00 - LFXO 32.768 kHz Crystal Crystal Crystal
E1 P1.01 - LFXO 32.768 kHz Crystal Crystal Crystal

SPI Bus Pins -- Reassigned on Gateway Boards

The SPI bus (P0.03/P0.04/P1.10/P1.08) connects to the LIS2DH12TR accelerometer on the 230220 Tag board. On Station boards (232200+) the accelerometer is not populated and these pins are reassigned:

  • Gateway boards (232202+): P0.03 → UART1 TX, P0.04 → UART1 RX, P1.10 → ESP32_RESET. This frees SAADC-capable pins P1.11/P1.13/P1.14 for the occupancy sensor on 232204.
  • Non-gateway Station (232200, 232201): P0.03/P0.04/P1.10 remain available for future assignment. P1.08 is available on all Station boards.
  • P2.09 (ACC INT2 on 230220) is also free on all Station boards.
  • All reassignments preserve the 230220 mux direction (output→output, input→input).

SK6812MINI-E LED Strategy

Station boards have two SK6812MINI-E footprints daisy-chained on a single data pin (P0.01):

  • LED1 (index 0) = System / operational status -- always populated on all Station boards
  • LED2 (index 1) = Gateway status -- DNP on 232200/232201, only populated on gateway variants (232202+)

The 230220 Tag board uses a simple red GPIO LED on the same pin. Firmware detects the board variant and initializes the appropriate LED driver. On non-gateway Station boards, only 1 LED is addressed.

LED1 activation via service button: Short press (< 1s) on P2.06 activates LED1 for 10 seconds. GREEN = no errors (healthy). Error-specific color/pattern if errors present. LED is OFF during normal operation unless errors exist.

SK6812MINI-E is recommended for its small 3.5x3.5mm footprint, integrated capacitor, and wide sourcing availability. WS2812B-Mini is a compatible alternative (same single-wire protocol at 800 kHz).

ST25DV04K NFC on All Boards

The I2C bus (P1.04/P1.05) and ST25DV control pins (P1.09, P1.15, P2.10) connect to the ST25DV04K external NFC controller on every nRF54 board variant. NFC is used for device configuration and provisioning across the entire platform. The nRF54 internal NFC peripheral (P1.02/P1.03) is not used on any board.

GPIO Reserve Pins (P1.02 / P1.03)

These pins are reserved as general-purpose IO (nRF54 internal NFC is not used; the ST25DV04K provides NFC on all boards). P1.02 is an NFC1 pin and P1.03 is an NFC2 pin -- neither has SAADC analog input capability.

Pin Name 230220 / 232200 / 232202 232201 / 232203 / 232204 (Battery) Notes
15 P1.02 / NFC1 GPIO reserve (unused) GPIO reserve (unused) Digital I/O only (not SAADC capable)
14 P1.03 / NFC2 GPIO reserve (unused) CHARGE_ACTIVE (input) MCP73123 STAT1 (open-drain, 10k pull-up to 3V3)

Spare GPIOs Limited on Battery Variants

On boards with battery (232201, 232203, 232204), P1.03 is consumed for CHARGE_ACTIVE. P1.02 remains as the only GPIO reserve pin.

Gateway-Only Pins (232202, 232203, 232204)

These pins are used exclusively on Station boards with WiFi/gateway functionality. On Tag/Anchor boards they remain unconfigured or set as GPIO inputs.

Pin Name Mux Direction Function ESP32-C5 GPIO Notes
3 P0.03 Output UART1 TX to ESP32 GPIO8 (pin 10) Wirepas Dual-MCU API + control/config (was SPI CLK)
4 P0.04 Input UART1 RX from ESP32 GPIO9 (pin 11) Wirepas Dual-MCU API + status/response (was SPI MISO)
A2 P1.10 Output ESP32_RESET EN (pin 3) ESP32 enable/reset control (was SPI MOSI)
20 P2.08 Input ESP32_READY GPIO24 (pin 23) ESP32 boot complete (reused from ACC.INT1)
C4 P2.00 Input COEX_REQUEST GPIO6 (pin 8) ESP32 requests 2.4 GHz airtime
E4 P2.01 Input COEX_PRIORITY GPIO10 (pin 12) ESP32 indicates priority level
D4 P2.02 Output COEX_GRANT GPIO23 (pin 21) nRF54 grants ESP32 airtime

Wirepas Dual-MCU API on UART1

UART1 carries both Wirepas gateway data packets and control/config commands using the Wirepas Dual-MCU API protocol. This is a single UART interface at 115200 baud (upgradable to 921600 for higher throughput). No SPI connection to ESP32 is needed -- the Dual-MCU API multiplexes data and control on one UART.

nRF54 is the Coexistence Arbiter

The 3-wire coexistence interface is controlled by nRF54 via Nordic MPSL (Multi-Protocol Service Layer). nRF54 owns the 2.4 GHz schedule (Wirepas TDMA) and grants ESP32 WiFi airtime during gaps in the Wirepas schedule. See Coexistence Architecture for details.

Battery-Only Pins (232201, 232203, 232204)

These pins are used on Station boards with battery backup. On non-battery boards they remain unassigned. BAT_VOLTAGE (P1.06 / AIN2) is listed in the always-configured table above since the trace is routed on the shared PCB.

Pin Name Mux Direction Function Notes
E3 P2.03 / QSPI_D2 Input BAT_PRESENT MCP73123 PG (open-drain, 10k pull-up). LOW = AC power present
D3 P2.04 / QSPI_D1 Input CHARGE_STATUS MCP73123 STAT2 (open-drain, 10k pull-up). LOW = charge done
C3 P2.05 / QSPI_CS Output CHARGE_ENABLE Enable/disable charging (MCP73123 CE or power-path FET)
14 P1.03 / NFC2 Input CHARGE_ACTIVE MCP73123 STAT1 (open-drain, 10k pull-up). LOW = charging

Unassigned Pins

Pin Name Notes
E3 P2.03 Assigned on battery variants (BAT_PRESENT); unassigned on 230220/232200/232202
D3 P2.04 Assigned on battery variants (CHARGE_STATUS); unassigned on 230220/232200/232202
C3 P2.05 Assigned on battery variants (CHARGE_ENABLE); unassigned on 230220/232200/232202
7 RF N/C (on-board antenna variant used)

Pin Budget -- Shared Station PCB

The shared Station PCB routes all pins from the three tables above: 25 always-configured + 7 gateway-only + 4 battery-only = 36 pin functions. On the most loaded non-sensor variant (232203), 24 unique GPIO pins are actively used. Gateway signals (UART1, ESP32_RESET) now occupy P0.03/P0.04/P1.10 (former SPI pins), freeing SAADC-capable P1.11/P1.13/P1.14 for the occupancy sensor on 232204. Available for sensor on 232204: P1.11 (AIN4), P1.13 (AIN6), P1.14 (AIN7), P1.08, P2.09 = 5 pins supporting SPI, analog, UART, or digital GPIO interfaces. P1.02 remains as GPIO reserve.


Board Variant Detection

Detection Sequence

The firmware runs this sequence at startup before initializing any peripherals:

graph TD
    START["Boot"] --> READ_BASE["1. Read P1.07 ADC - Base Board ID"]
    READ_BASE --> READ_EXT["2. Read P1.12 ADC - Extension Board ID"]
    READ_EXT --> READ_BAT["3. Read P1.06 ADC - BAT_VOLTAGE (battery variants)"]
    READ_BAT --> MUX["4. Configure GPIO mux - same for all variants"]
    MUX --> NFC_INIT["5. Initialize ST25DV04K (I2C) - all boards"]
    NFC_INIT --> INIT["6. Initialize peripherals for detected board"]
    INIT --> APP{"Base board type?"}
    APP -->|"230220 / 232200 / 232201"| TAG_APP["Tag/Anchor Application"]
    APP -->|"232202 / 232203 / 232204"| GW_APP["Gateway Application"]
    GW_APP --> ESP_BOOT["7. Reset ESP32, send config, start coex"]

Base Board Detection (P1.07 -- V_SAMPLE)

All nRF54-based boards use a resistor divider on P1.07 to identify the base board variant. The divider uses a fixed R_top = 100k (1%) and a board-specific R_bottom in 16.5k steps.

graph LR
    VCC["VCC / V_BAT"] --> R_top["R_top: 100k 1%"]
    R_top --> ADC["P1.07 - V_SAMPLE"]
    ADC --> R_bot["R_bottom: board-specific"]
    R_bot --> GND["GND"]

ADC Ratio = R_bottom / (R_top + R_bottom)

Board Article Product R_top R_bottom Nominal Ratio 12-bit ADC ADC Window Firmware Build
230220 Tag nRF54 Base 100k 0 ohm 0.000 0 0--200 Tag/Anchor
232200 Station Base Std 100k 16.5k 0.142 580 400--750 Tag/Anchor
232201 Station Base Bat 100k 33k 0.248 1016 850--1200 Tag/Anchor
232202 Station Base WiFi 100k 49.9k 0.333 1363 1200--1550 Gateway
232203 Station Bat+WiFi 100k 66.5k 0.399 1634 1500--1800 Gateway
232204 Station Full 100k 82.5k 0.452 1851 1750--2050 Gateway
(Reserved) Future expansion 100k 100k 0.500 2048 2000--2250 TBD

230220 First Boards

For 230220, R_bottom = 0 ohm (short to GND). On first prototype boards where R7 is populated with a different value, unsolder R7 to achieve the 0 ohm / GND reading.

Tolerance Analysis

With 1% resistors, worst-case ratio error is approximately ± 2%, which translates to ~80 ADC counts at mid-scale. The 16.5k step size provides ~400+ counts of separation between adjacent boards -- well above the tolerance margin. ADC windows are defined with at least 150 counts of dead-band between adjacent windows.

Extension Board Detection (P1.12 -- EXT_DETECT)

Pin P1.12 (B1) detects the presence and variant of an extension board (e.g., LTE EU or LTE US). This pin is reserved on all nRF54-based boards.

Circuit

The base board has a 100k pull-down resistor from P1.12 to GND. When no extension is connected, the ADC reads ~0V.

The extension board provides its own resistor divider (R_top from VCC, R_bottom to the shared pin) via the board-to-board connector, overriding the base board pull-down.

graph TB
    subgraph base_pcb [Base PCB]
        P112["P1.12 - EXT_DETECT"]
        R_PD["100k pull-down"]
        GND1["GND"]
        P112 --> R_PD
        R_PD --> GND1
    end

    subgraph ext_pcb [Extension PCB - via B2B connector]
        VCC_EXT["VCC"]
        R_TOP_EXT["R_top: 100k 1%"]
        R_BOT_EXT["R_bottom: variant-specific"]
        GND2["GND"]
        VCC_EXT --> R_TOP_EXT
        R_TOP_EXT --> EXT_PIN["To P1.12 via connector"]
        EXT_PIN --> R_BOT_EXT
        R_BOT_EXT --> GND2
    end

    EXT_PIN -.->|"Board-to-board connector"| P112

Extension ADC Map

Extension R_top (on ext) R_bottom (on ext) Nominal Ratio 12-bit ADC ADC Window Notes
None - - (100k pull-down on base) ~0 0 0--200 No extension board connected
232210 Ext LTE EU 100k 16.5k 0.142 580 400--750 SIMCom SIM7672E
232211 Ext LTE US 100k 33k 0.248 1016 850--1200 SIMCom SIM7672NA
(Reserved) 100k 49.9k 0.333 1363 1200--1550 Future extension
(Reserved) 100k 66.5k 0.399 1634 1500--1800 Future extension

Pull-Down Interaction

When an extension board is present, its R_bottom forms a parallel resistance with the 100k pull-down on the base board. For 16.5k R_bottom: effective R = 16.5k || 100k = 14.2k. This shifts the ADC reading slightly lower than the ideal ratio. The ADC windows account for this. For precise calculation: V_adc = VCC * R_eff / (R_top + R_eff), where R_eff = R_bottom || 100k_pulldown.

BAT_VOLTAGE / PCB Revision (P1.06 -- AIN2)

Pin P1.06 (AIN2) is routed to a resistor-divider footprint on the shared Station PCB. On battery variants (232201, 232203, 232204) the divider is populated and provides BAT_VOLTAGE. On non-battery variants (232200, 232202) the divider is not populated and P1.06 reads ~0V. On the 230220 Tag board, P1.06 is not connected and remains available for future PCB revision detection.


Firmware Architecture

All nRF54 boards share a single physical PCB design (the shared Station PCB). The hardware is identical -- only BOM population differs between variants. However, the firmware is split into two separate builds:

Two Firmware Builds

Build Target Boards Wirepas Role Key Peripherals
Tag/Anchor FW 230220, 232200, 232201 Anchor (relay) SPI accelerometer (230220), NFC, battery monitoring
Gateway FW 232202, 232203, 232204 Gateway (sink) ESP32 UART1, coexistence, NFC, battery monitoring

Why Two Builds?

  1. Different Wirepas roles: Anchors relay mesh traffic; gateways are traffic sinks that forward data to the cloud via WiFi/LTE. These are fundamentally different network roles with different Wirepas stack configurations.
  2. Different peripheral sets: Tag/Anchor firmware initializes SPI accelerometer (on 230220) but never touches ESP32 pins. Gateway firmware initializes UART1, coexistence, and ESP32 control but never touches SPI accelerometer.
  3. Separate OTAP area IDs: Wirepas Over-The-Air Programming (OTAP) uses area IDs to target firmware updates. Gateways and anchors have different area IDs so that a gateway firmware update does not accidentally reprogram anchors (and vice versa). This is critical for safe field updates.
  4. Same physical PCB, different software: The shared Station PCB carries all traces for both builds. Unpopulated peripherals are simply not initialized.

Tag/Anchor Firmware

Runs on boards 230220, 232200, 232201 (V_SAMPLE ADC < 1200).

  • Initializes SPI accelerometer on 230220 (conditional on V_SAMPLE = 0)
  • Initializes battery monitoring (P1.06 ADC, P1.03/P2.03/P2.04/P2.05 charger GPIOs) on 232201 (conditional on V_SAMPLE ≈ 1016)
  • Does not initialize UART1, ESP32 control, or coexistence pins
  • Gateway-only pins (P0.03, P0.04, P1.10, P2.00, P2.01, P2.02, P2.08) are left unconfigured or set as inputs
  • Wirepas role: anchor (relay node)
  • 230220 pin map rules and input/output directions are the reference

Gateway Firmware

Runs on boards 232202, 232203, 232204 (V_SAMPLE ADC > 1200).

  • Initializes UART1 (P0.03 TX, P0.04 RX) for Wirepas Dual-MCU API to ESP32
  • Initializes ESP32 control (P1.10 RESET, P2.08 READY)
  • Initializes 3-wire coexistence (P2.00 REQUEST, P2.01 PRIORITY, P2.02 GRANT) via Nordic MPSL
  • Does not initialize SPI accelerometer (no accelerometer on gateway boards)
  • Initializes battery monitoring on 232203/232204 (conditional on V_SAMPLE)
  • Wirepas role: gateway (sink node)
  • Can relax 230220 pin map rules for gateway-only pins if needed (separate build, no 230220 binary compatibility requirement for ESP32 interface pins)

Anchor vs Gateway Battery Behaviour

On battery variants, the firmware behaviour differs significantly between anchor and gateway modes:

Aspect Anchor (232201) Gateway (232203/232204)
Battery role Hold-up during AC power loss Full operation during AC power loss
ESP32 on battery N/A (no ESP32) Stays powered -- gateway link active
Expected runtime Days (nRF54 only, low power) Hours (nRF54 + ESP32 + WiFi)
Shutdown trigger Battery below threshold (~2.5V) Battery below threshold (~3.1V, higher due to ESP32 LDO dropout)
Shutdown sequence nRF54 Wirepas leave → power off ESP32 WiFi disconnect → nRF54 Wirepas leave → power off
Mesh impact Neighbours re-route around dead anchor Critical: if gateway dies without graceful shutdown, mesh traffic is black-holed

Gateway Must Stay Alive on Battery

Gateway nodes are traffic sinks in the Wirepas mesh. If the ESP32 (WiFi uplink) is powered off while the nRF54 remains visible as a gateway, other mesh nodes will continue routing data to it with nowhere to go -- creating a traffic black hole. The ESP32 LDO is therefore fed from the battery-backed power-path output, ensuring both MCUs remain active on battery. Graceful shutdown at low battery gives the mesh time to re-route.

Firmware Mismatch Detection

At boot, after reading V_SAMPLE (P1.07), firmware checks whether the ADC value falls in the expected range for its build type:

Firmware Build Expected V_SAMPLE Range Board Matches
Tag/Anchor FW 0 -- 1200 230220, 232200, 232201
Gateway FW 1200+ 232202, 232203, 232204

On mismatch (e.g., gateway firmware running on a 232200 board):

  1. Log error via UART0: ERR: firmware/board mismatch -- gateway FW on anchor board (V_SAMPLE=580)
  2. Blink LED1 with red fast-flash pattern (500 ms on/off) to alert during production
  3. Optionally halt (do not join Wirepas network) to prevent incorrect network behaviour

This prevents accidental programming of the wrong firmware binary during production or OTAP. The check is a simple ADC range comparison with no additional hardware cost.


System Architecture

nRF54 as System Master

The nRF54 (PAN611) is the system master on all board variants. It:

  • Boots first and detects the board variant
  • Initializes all peripherals
  • Owns the ST25DV04K NFC interface (config read/write)
  • Stores all system configuration in its flash (single source of truth)
  • Manages ESP32 lifecycle (reset, boot, config push) on gateway boards
  • Arbitrates 2.4 GHz coexistence via MPSL
  • Exposes a debug CLI on UART0 for PC interaction
graph TB
    subgraph external [External Interfaces]
        PHONE["Phone / NFC Reader"]
        PC["PC / Debug Tool"]
        BROWSER["Web Browser"]
    end

    subgraph nrf54 [nRF54 - System Master]
        FLASH["Flash: Config Store - Single Source of Truth"]
        CLI["UART0: Debug CLI"]
        MPSL["MPSL: Coex Arbiter"]
        WP["Wirepas Mesh"]
        NFC_DRV["I2C: ST25DV04K Driver"]
    end

    subgraph st25dv [ST25DV04K - NFC]
        NFC_MEM["NFC Memory"]
    end

    subgraph esp32 [ESP32-C5 - Gateway Only]
        WEBUI["Web UI Server"]
        WIFI["WiFi Radio"]
        ESP_UART["UART1: Dual-MCU API"]
    end

    subgraph lte [LTE Modem - Extension Only]
        MODEM["SIMCom SIM7672x<br/>(1.8V I/O, level-shifted)"]
    end

    PHONE -->|"NFC field"| NFC_MEM
    NFC_MEM -->|"I2C"| NFC_DRV
    NFC_DRV --> FLASH

    PC -->|"UART0"| CLI
    CLI --> FLASH

    FLASH -->|"UART1: config push"| ESP_UART
    WP -->|"UART1: gw packets"| ESP_UART
    ESP_UART --> WEBUI
    BROWSER -->|"WiFi"| WEBUI
    WEBUI -->|"config change"| ESP_UART
    ESP_UART -->|"UART1"| FLASH

    MPSL -->|"COEX GRANT"| WIFI
    WIFI -->|"COEX REQUEST"| MPSL

    ESP_UART --> WIFI
    ESP_UART -->|"UART"| MODEM

Configuration Architecture

nRF54 Flash = Single Source of Truth

All configuration data is stored in nRF54 flash only. ESP32 receives its config from nRF54 at boot and caches it in RAM. There is no persistent config on ESP32 -- if ESP32 reboots, nRF54 re-sends the full config.

Config Entry Points

Entry Point Path Latency Available On
NFC (phone) Phone → ST25DV field → nRF54 I2C read → flash store ~100 ms All boards
Debug CLI (PC) PC → UART0 → nRF54 CLI parser → flash store ~10 ms All boards
Web UI (browser) Browser → ESP32 WiFi → UART1 → nRF54 → flash → UART1 ack → ESP32 → browser ~50 ms Gateway boards

Config Data Structure

Configuration data reuses the existing TLV (Type-Length-Value) NFC config structure already defined in the firmware codebase. This ensures a single, consistent config format across all entry points (NFC, UART CLI, Web UI).

TLV Format Reference

The config TLV structure is defined in the firmware source. Each config parameter is encoded as a TLV record with a unique type ID, length, and binary value. The same TLV format is used for:

  • NFC memory (ST25DV04K EEPROM) -- phone reads/writes TLV records via NFC field
  • nRF54 flash -- persistent storage, single source of truth
  • UART1 transport -- TLV records serialized over the Wirepas Dual-MCU API command channel to ESP32

Refer to the firmware TLV implementation for the complete type ID registry and encoding details.

nRF54 stores all config TLV records. When forwarding to ESP32, it sends only the records relevant to WiFi, gateway, LTE, and coexistence. ESP32 does not need Wirepas or BLE config records.

NFC Config Flow

sequenceDiagram
    participant Phone
    participant ST25DV as ST25DV04K
    participant nRF54 as nRF54 (Master)
    participant ESP32 as ESP32-C5

    Phone->>ST25DV: Write config via NFC field
    ST25DV->>nRF54: GPO interrupt (P1.09)
    nRF54->>ST25DV: I2C read new config
    nRF54->>nRF54: Store in flash
    nRF54->>nRF54: Apply nRF54-local config (Wirepas, BLE)
    nRF54->>ESP32: UART1: CONFIG_SET wifi.ssid "NewNet"
    nRF54->>ESP32: UART1: CONFIG_SET wifi.password "..."
    nRF54->>ESP32: UART1: CONFIG_APPLY
    ESP32->>ESP32: Update RAM cache, reconnect WiFi
    ESP32->>nRF54: UART1: CONFIG_ACK

Web UI Config Flow

sequenceDiagram
    participant Browser
    participant ESP32 as ESP32-C5
    participant nRF54 as nRF54 (Master)

    Browser->>ESP32: HTTP POST /api/config {wifi.ssid: "NewNet"}
    ESP32->>nRF54: UART1: CONFIG_SET wifi.ssid "NewNet"
    nRF54->>nRF54: Store in flash (source of truth)
    nRF54->>ESP32: UART1: CONFIG_ACK
    ESP32->>ESP32: Update RAM cache
    ESP32->>Browser: HTTP 200 OK

    Note over Browser,ESP32: Config reads are served from ESP32 RAM cache (fast)
    Browser->>ESP32: HTTP GET /api/config
    ESP32->>Browser: {wifi.ssid: "NewNet", ...} (from RAM cache)

ESP32 Boot Sequence (Gateway Boards)

sequenceDiagram
    participant nRF54 as nRF54 (Master)
    participant ESP32 as ESP32-C5
    participant LTE as LTE Modem

    nRF54->>nRF54: Detect gateway board (ADC)
    nRF54->>ESP32: Assert RESET (P1.10 LOW)
    nRF54->>nRF54: Wait 100ms
    nRF54->>ESP32: Release RESET (P1.10 HIGH)
    ESP32->>ESP32: Boot ESP-IDF
    ESP32->>nRF54: READY signal (P2.08 HIGH)
    nRF54->>ESP32: UART1: CONFIG_SET wifi.ssid ...
    nRF54->>ESP32: UART1: CONFIG_SET gateway.server_url ...
    nRF54->>ESP32: UART1: CONFIG_SET lte.apn ... (if extension detected)
    nRF54->>ESP32: UART1: CONFIG_APPLY
    ESP32->>ESP32: Start WiFi, connect to AP
    ESP32->>nRF54: UART1: STATUS wifi=connected
    ESP32->>LTE: UART: AT+CPIN? (if LTE extension present)
    ESP32->>nRF54: UART1: STATUS lte=registered
    nRF54->>ESP32: UART1: COEX_START
    Note over nRF54,ESP32: Normal operation: Wirepas Dual-MCU packets via UART1, coex active

nRF54 to ESP32 Communication Protocol

A single UART interface connects nRF54 to ESP32 using the Wirepas Dual-MCU API:

Interface Pins Purpose Data Rate
UART1 (Dual-MCU) P0.03 TX, P0.04 RX Wirepas gateway packets + config + status + commands 115200 (up to 921600)

Wirepas Dual-MCU API

The Wirepas Dual-MCU API is the standard protocol for connecting a Wirepas node (nRF54) to a host MCU (ESP32) over a single UART. It multiplexes Wirepas mesh data (gateway uplink/downlink packets) and control commands on a single interface using SLIP-encoded framing. This eliminates the need for a separate SPI data bus and simplifies the hardware design to just 2 signal wires + RESET + READY.

Additional Signals Pin Direction (nRF54) Purpose
ESP32_RESET P1.10 Output nRF54 resets ESP32 during boot
ESP32_READY P2.08 Input ESP32 signals boot complete to nRF54

UART1 Command Protocol

The Wirepas Dual-MCU API handles gateway data natively. For config and management, a text-based command layer is multiplexed on the same UART:

Direction Command Purpose
nRF54 → ESP32 CONFIG_SET <key> <value> Send config parameter
nRF54 → ESP32 CONFIG_APPLY Apply all pending config
nRF54 → ESP32 STATUS_REQ Request ESP32 status
nRF54 → ESP32 COEX_START Enable coexistence arbitration
nRF54 → ESP32 COEX_STOP Disable coexistence
nRF54 → ESP32 RESET Soft reset ESP32
ESP32 → nRF54 CONFIG_ACK Config applied OK
ESP32 → nRF54 STATUS <wifi_state> <lte_state> <gw_state> Status report
ESP32 → nRF54 CONFIG_SET <key> <value> Web UI config change (forwarded to nRF54 flash)
ESP32 → nRF54 ERROR <code> <message> Error report

ESP32 to LTE Modem

The LTE modem (on extension PCB 232210/232211) is managed by ESP32, not nRF54. This is because:

  • ESP32 already handles IP connectivity (WiFi) -- adding LTE as a second transport is natural
  • ESP32 has more UART peripherals and GPIO available for AT command interface
  • ESP32 manages coexistence between WiFi TX and LTE modem
  • nRF54 doesn't need to know LTE details -- it sends gateway data to ESP32, and ESP32 routes it via WiFi or LTE

ESP32 ↔ LTE modem pins (on ESP32 GPIO, via Harwin M20 board-to-board connector):

Function ESP32 Direction B2B Pin B2B Voltage Notes
UART TX → LTE Output 4 3.3V AT commands (level-shifted to 1.8V on ext board)
UART RX ← LTE Input 5 3.3V AT responses (level-shifted from 1.8V on ext board)
LTE_POWER_KEY Output 6 3.3V Modem power on/off (shifted to VBAT domain on ext)
LTE_RESET Output 7 3.3V Modem hard reset (shifted to VBAT domain on ext)
LTE_STATUS Input 8 3.3V Network registration (shifted from 1.8V on ext)
NETLIGHT Input 9 3.3V Modem blink pattern (64ms/800ms=searching, 64ms/3000ms=registered, 64ms/300ms=data) -- decoded by ESP32, relayed to nRF54 for LED2. Shifted from 1.8V on ext board.
LTE_TX_BLANK Output 10 3.3V TX blanking for WiFi/LTE coex (shifted to 1.8V on ext)

Level Shifting on Extension Board

The SIMCom SIM7672E/NA modem operates at 1.8V logic for all UART, STATUS, and NETLIGHT pins. PWRKEY and RESET are in the VBAT domain (3.4--4.2V). Level shifters and NPN/MOSFET driver circuits on the extension board (232210/232211) translate between these voltages and the 3.3V signals on the B2B connector. The ESP32 (and the 232204 base PCB) only sees standard 3.3V logic. See 232210 section 3.7 for details.

SIM card signals (SIM_CLK, SIM_DATA, SIM_RST, SIM_VCC) are routed locally on the extension board between the modem and the nano-SIM holder. They do not cross the B2B connector.


Coexistence Architecture

The Problem

On gateway boards (232202+), two 2.4 GHz radios operate simultaneously:

  • nRF54: Wirepas Mesh (strict TDMA time slots) + BLE
  • ESP32-C5: WiFi 2.4 GHz (802.11ax)

Simultaneous 2.4 GHz transmissions cause RF interference, degrading both Wirepas mesh stability and WiFi throughput.

Solution: nRF54 as Arbiter via Nordic MPSL

nRF54 owns the 2.4 GHz schedule

The nRF54 is the coexistence arbiter because Wirepas TDMA timing is non-negotiable. Missing a Wirepas time slot can cause mesh desynchronization (recovery takes seconds to minutes). WiFi is best-effort and tolerates delays.

If ESP32 were the arbiter, long WiFi TX bursts (TCP, TLS handshake) could starve Wirepas of airtime. The "fox guarding the henhouse" problem is eliminated by making nRF54 the gatekeeper.

Nordic MPSL (Multi-Protocol Service Layer) has built-in coexistence arbitration. It knows the exact Wirepas schedule and can calculate precise GRANT windows for ESP32.

3-Wire Interface

graph LR
    subgraph nrf54 [nRF54 - Arbiter]
        MPSL["MPSL CX"]
        WP["Wirepas Radio"]
    end

    subgraph esp32 [ESP32-C5 - Requester]
        WIFI["WiFi Radio"]
        COEX_DRV["Coex Driver"]
    end

    COEX_DRV -->|"REQUEST (P2.00)"| MPSL
    COEX_DRV -->|"PRIORITY (P2.01)"| MPSL
    MPSL -->|"GRANT (P2.02)"| COEX_DRV
Signal Pin Direction (nRF54) Description
COEX_REQUEST P2.00 Input ESP32 asserts HIGH when it wants to use 2.4 GHz radio
COEX_PRIORITY P2.01 Input ESP32 asserts HIGH for high-priority WiFi operations
COEX_GRANT P2.02 Output nRF54 asserts HIGH to allow ESP32 to transmit

Arbitration Logic

ESP32 REQUEST ESP32 PRIORITY Wirepas Active nRF54 Decision
HIGH HIGH No GRANT -- no conflict
HIGH HIGH Yes (time slot) DENY -- Wirepas slot is sacred
HIGH HIGH Yes (idle listen) GRANT -- nRF54 can defer idle listen
HIGH LOW No GRANT -- no conflict
HIGH LOW Yes DENY -- ESP32 can retry
LOW - - GRANT (don't care) -- ESP32 not requesting

nRF54 MPSL calculates the time until the next Wirepas slot and grants ESP32 a bounded time window. When the window expires, GRANT is de-asserted and ESP32 must stop transmitting.

Multi-Radio Coexistence Map

On a fully-loaded 232204 with LTE extension and future radar:

Radio Frequency Interferes With Coex Method
nRF54 (Wirepas/BLE) 2.4 GHz ESP32 WiFi 2.4 GHz 3-wire MPSL (nRF54 arbiter)
ESP32 WiFi 2.4 / 5 GHz nRF54 2.4 GHz; LTE near-band 3-wire (requests from nRF54); TX blank to LTE
LTE modem 700--2690 MHz WiFi 2.4 GHz (Band 7 ~2.6 GHz) ESP32 manages via TX_BLANK GPIO
Radar (future) 24 or 60 GHz None No coex needed (frequency isolation)

5 GHz WiFi Preferred

On gateway boards, ESP32 should prefer 5 GHz WiFi when available. The 5 GHz band does not interfere with Wirepas 2.4 GHz, eliminating the need for coexistence arbitration during 5 GHz transmissions. The 3-wire coex is only active during 2.4 GHz WiFi activity.


Firmware Initialization by Board Variant

After detecting the board, the firmware initializes peripherals conditionally:

Peripheral 230220 232200 232201 232202 232203 232204
I2C NFC (ST25DV04K) Init Init Init Init Init Init
ST25DV Control (GPO, LPD, VCC) Init Init Init Init Init Init
SPI Accelerometer (LIS2DH12TR) Init Skip Skip Skip Skip Skip
ESP32 UART1 (Wirepas Dual-MCU) Skip Skip Skip Init Init Init
ESP32 Reset + Ready Skip Skip Skip Init Init Init
3-Wire Coexistence (MPSL CX) Skip Skip Skip Init Init Init
LED (Red GPIO) Init Skip Skip Skip Skip Skip
LED (SK6812MINI-E x1 system) Skip Init Init Init Init Init
LED (SK6812MINI-E x2 gateway) Skip Skip Skip Init Init Init
Button (SW1 Tag / Service Stn) Init Init Init Init Init Init
Battery Mgmt (P2.03--P2.05, P1.06, P1.03) Skip Skip Init Skip Init Init
PIR/Radar Sensor Skip Skip Skip Skip Skip Init

Init vs Skip

Init = driver is started, peripheral is used. Skip = driver is not started, pins are available for reassignment (direction preserved). GPIO mux directions (input/output) are preserved across all board variants. ST25DV04K NFC is Init on all boards. LED1 (system, index 0) is always present on Station boards. LED2 (gateway, index 1) is DNP on 232200/232201 and only populated on 232202+ gateway variants. Button (P2.06) is present on all boards: SW1 push button on 230220 Tag, right-angle service button on Station boards.


Debug & Certification Interface

Dual UART Architecture

UART Pins Connected To Baud Rate Purpose
UART0 (Debug) P0.02 (TX), P2.07 (RX) J1: TC2030-CTX-NL → PC 115200 CLI, debug logging, certification test commands
UART1 (ESP32) P0.03 (TX), P0.04 (RX) ESP32-C5 115200* Wirepas Dual-MCU API (data + control/config)

*UART1 defaults to 115200 baud and can be upgraded to 921600 for higher gateway data throughput. Both UARTs operate simultaneously -- a developer can have a PC connected via TC2030 while ESP32 is connected on UART1.

CLI Command Set (UART0)

The nRF54 exposes a text-based CLI on UART0 (115200 8N1) accessible via the TC2030 debug connector. This is used for development, production testing, and RF certification.

Radio Test Commands (RF Certification)

Command Description Certification Use
radio cw <freq_mhz> <power_dbm> Continuous wave, unmodulated carrier FCC/CE conducted power
radio txmod <freq_mhz> <power_dbm> <mod> Modulated TX (BLE/Wirepas) Occupied bandwidth, spurious emissions
radio rx <freq_mhz> Receive mode, report RSSI Receiver sensitivity
radio stop Stop all radio activity Return to idle
ble adv start/stop BLE advertising control BLE certification
wirepas start/stop Wirepas mesh control Mesh protocol testing

Peripheral Test Commands

Command Description
nfc read [addr] [len] Read ST25DV04K memory via I2C
nfc write [addr] [data] Write ST25DV04K memory
nfc mailbox read/write Fast-transfer mailbox access
acc read Read accelerometer XYZ (if populated)
adc read <pin> Read ADC value (variant detect, etc.)
gpio set/get <pin> <0/1> Direct GPIO control
led <idx> <r> <g> <b> / led on/off Set LED color (SK6812: idx 0=system, 1=telematics) or on/off (red)
i2c scan Scan I2C bus for responding devices

ESP32 Management Commands (Gateway Boards)

Command Description
esp reset Assert ESP32 reset line
esp status Query ESP32 status via UART1
esp fwd <cmd> Forward raw command to ESP32 UART1
wifi scan Tell ESP32 to scan and report APs
wifi connect <ssid> <pass> Configure WiFi via ESP32
lte status Query LTE modem status (via ESP32)
coex status Report coexistence state (REQUEST/GRANT/stats)
coex mode <off/2wire/3wire> Set coexistence mode

System Commands

Command Description
config get/set <key> <value> Read/write config in nRF54 flash
config dump Dump all config key-value pairs
config factory-reset Erase all config, return to defaults
variant Report detected board variant, extension, PCB revision
status Full system status (board, radio, peripherals, ESP32, LTE)
version Firmware version, build date, board article
reset System reset
dfu <nrf54/esp32> Enter DFU mode for specified target
log <off/error/warn/info/debug> Set log verbosity

Service Button Behavior (P2.06)

All boards have a button on P2.06 (active-low with internal pull-up):

  • 230220 Tag: Push button (SW1) -- general user input
  • 232200+ Station: Right-angle tactile switch (side-actuated) -- hidden behind enclosure pinhole, accessible via service pin

Station Button Actions

Action Trigger Firmware Behavior
Short press (< 1s) During normal operation Activate LED1 for 10 seconds: GREEN = no errors (healthy), error-specific color/pattern if errors present. LED is OFF during normal operation unless errors exist.
5s hold During normal operation System reboot -- clean restart of nRF54 (and ESP32 if present on gateway boards)
5s hold at power-up Press and hold during AC plug-in Factory default restore -- erase config flash, reset all settings to defaults, reboot

Factory Reset Requires Physical Access

The factory reset (5s hold at power-up) requires physical disconnection of AC power followed by re-connection while holding the button. This prevents accidental factory reset during normal operation. The recessed pinhole prevents end-user access -- only service technicians with a SIM eject tool or paperclip can reach the button.

Certification Test Workflow Example

# 1. Identify the board
> variant
Board: 232202 (Station WiFi), Extension: None, Rev: A

# 2. FCC Part 15 conducted TX power test
> radio cw 2402 0
CW mode: 2402 MHz, 0 dBm. Press 'radio stop' to end.
# ... test engineer measures power at antenna port ...
> radio cw 2441 4
CW mode: 2441 MHz, 4 dBm.
> radio stop
OK

# 3. Verify NFC (all boards)
> nfc read 0 16
00: 4E 44 45 46 00 00 00 00 53 54 32 35 44 56 30 34
> i2c scan
Found: 0x53 (ST25DV04K system), 0x57 (ST25DV04K user)

# 4. WiFi coexistence test
> wifi connect TestAP password123
ESP32: connecting...
ESP32: connected, IP 192.168.1.42
> wirepas start
Wirepas: joined network, node ID 0x1234
> coex status
COEX: 3-wire active, grants=1523, denials=87, avg_window=12ms

# 5. Full system status
> status
Board: 232202, Extension: None, Rev: A
nRF54: FW v1.2.3, built 2026-02-12
Wirepas: joined, network 0x1234, ch 15, role anchor
BLE: advertising, name "EverTag-001"
NFC: ST25DV04K online, mailbox empty
ESP32: online, FW v0.8.1
WiFi: connected, SSID "TestAP", RSSI -45 dBm, IP 192.168.1.42
LTE: not present
Coex: 3-wire, grants 1523, denials 87