Open-source Arduino board package for Seeed XIAO nRF54L15 with a clean register-level implementation.
- Core name:
Nrf54L15-Clean-Implementation - Board:
XIAO nRF54L15 (Nrf54L15-Clean-Implementation) - FQBN:
nrf54l15clean:nrf54l15clean:xiao_nrf54l15 - No Zephyr runtime dependency
- No nRF Connect SDK runtime dependency
This repo is intentionally different from the Zephyr-based core:
- Uses direct register programming for core + HAL behavior.
- Ships as a normal Arduino Boards Manager package.
- Does not require users to install large external SDKs to build/upload.
Add this URL to Arduino IDE / Arduino CLI Additional Boards Manager URLs:
https://raw.githubusercontent.com/lolren/NRF54L15-Clean-Arduino-core/main/package_nrf54l15clean_stable_index.json
If your IDE/CLI already cached an older index, remove cache and update indexes:
- Linux:
rm -f ~/.arduino15/package_nrf54l15clean_index.json ~/.arduino15/package_nrf54l15clean_stable_index.json - Then run:
arduino-cli core update-index
Then install package Nrf54L15-Clean-Implementation and select board:
XIAO nRF54L15 (Nrf54L15-Clean-Implementation)
If upload reports No connected debug probes but lsusb shows
2886:0066 Seeed Studio XIAO nrf54 CMSIS-DAP, add a udev rule:
cat <<'RULE' | sudo tee /etc/udev/rules.d/60-seeed-xiao-nrf54-cmsis-dap.rules >/dev/null
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="2886", ATTRS{idProduct}=="0066", MODE="0660", GROUP="plugdev", TAG+="uaccess"
SUBSYSTEM=="usb", ATTR{idVendor}=="2886", ATTR{idProduct}=="0066", MODE="0660", GROUP="plugdev", TAG+="uaccess"
RULE
sudo udevadm control --reload-rules
sudo udevadm trigger --attr-match=idVendor=2886 --attr-match=idProduct=0066| Peripheral | Default pins | Notes |
|---|---|---|
Wire (I2C primary) |
SDA=D4(P1.10), SCL=D5(P1.11) |
Sketch compatibility default |
Wire1 (I2C secondary) |
SDA=D12(P0.04), SCL=D11(P0.03) |
Back-pad bus |
SPI |
MOSI=D10(P2.02), MISO=D9(P2.04), SCK=D8(P2.01), SS=D2(P1.06) |
Runtime clock via SPISettings |
Serial1 / Serial2 |
TX=D6(P2.08), RX=D7(P2.07) |
Serial2 is alias of Serial1 |
Serial |
USB bridge (default) | Can be switched to header UART via Tools menu |
| Arduino pin | MCU pin | ADC input | Typical role |
|---|---|---|---|
D0 / A0 |
P1.04 |
AIN0 |
GPIO / ADC |
D1 / A1 |
P1.05 |
AIN1 |
GPIO / ADC |
D2 / A2 |
P1.06 |
AIN2 |
GPIO / ADC / SS |
D3 / A3 |
P1.07 |
AIN3 |
GPIO / ADC |
D4 / A4 |
P1.10 |
N/A | Wire SDA |
D5 / A5 |
P1.11 |
AIN4 |
Wire SCL |
D6 |
P2.08 |
N/A | Serial1/2 TX |
D7 |
P2.07 |
N/A | Serial1/2 RX |
D8 |
P2.01 |
N/A | SPI SCK |
D9 |
P2.04 |
N/A | SPI MISO |
D10 |
P2.02 |
N/A | SPI MOSI |
D11 |
P0.03 |
N/A | Back pad / Wire1 SCL |
D12 |
P0.04 |
N/A | Back pad / Wire1 SDA |
D13 |
P2.10 |
N/A | Back pad GPIO |
D14 |
P2.09 |
N/A | Back pad GPIO |
D15 |
P2.06 |
N/A | Back pad GPIO |
LED_BUILTIN (16) |
P2.00 |
N/A | User LED (active-low) |
PIN_BUTTON (17) |
P0.00 |
N/A | User button (active-low) |
PIN_SAMD11_RX (18) |
P1.09 |
N/A | USB bridge route |
PIN_SAMD11_TX (19) |
P1.08 |
N/A | USB bridge route |
Additional board-control nets exposed in HAL:
| Function | MCU pin | Symbol |
|---|---|---|
| VBAT divider enable | P1.15 |
kPinVbatEnable |
| VBAT ADC sense | P1.14 |
kPinVbatSense / A7 |
| RF switch control | P2.05 |
kPinRfSwitchCtl |
| MCU pin | Arduino alias |
|---|---|
P0.00 |
PIN_BUTTON |
P0.03 |
D11 |
P0.04 |
D12 |
P1.04 |
D0/A0 |
P1.05 |
D1/A1 |
P1.06 |
D2/A2 |
P1.07 |
D3/A3 |
P1.08 |
PIN_SAMD11_TX |
P1.09 |
PIN_SAMD11_RX |
P1.10 |
D4/A4 |
P1.11 |
D5/A5 |
P1.14 |
A7 / VBAT sense |
P1.15 |
VBAT enable |
P2.00 |
LED_BUILTIN |
P2.01 |
D8 |
P2.02 |
D10 |
P2.04 |
D9 |
P2.05 |
RF switch control |
P2.06 |
D15 |
P2.07 |
D7 |
P2.08 |
D6 |
P2.09 |
D14 |
P2.10 |
D13 |
- GPIO:
pinMode,digitalRead,digitalWrite,attachInterrupt,detachInterrupt - ADC/PWM:
analogRead,analogReadResolution(bits),analogWrite,analogWriteResolution - UART:
Serial,Serial1,Serial2 - I2C:
Wire+Wire1, repeated-start, target/slave callbacks - SPI: transactions + runtime frequency/mode/order
- Timing/power:
millis,micros, delays, optional low-power idle profile
Library path:
hardware/nrf54l15clean/0.1.0/libraries/Nrf54L15-Clean-Implementation
Implemented blocks:
ClockControl,Gpio,Spim,Twim,UarteSaadc,Timer,Pwm,GpiotePowerManager,Grtc,TempSensor,Watchdog,PdmBleRadio(custom peripheral LL + ATT/GATT subset)BoardControl(battery sense + antenna route control)
#include "nrf54l15_hal.h"
using namespace xiao_nrf54l15;
int32_t vbatMv = 0;
uint8_t vbatPct = 0;
BoardControl::sampleBatteryMilliVolts(&vbatMv);
BoardControl::sampleBatteryPercent(&vbatPct);
BoardControl::setAntennaPath(BoardAntennaPath::kCeramic);
BoardControl::setAntennaPath(BoardAntennaPath::kExternal);
BoardControl::setAntennaPath(BoardAntennaPath::kControlHighImpedance);Important RF note:
kControlHighImpedancereleasesP2.05drive; it does not power-gate the RF switch IC.
- Upload method: Auto / pyOCD / OpenOCD
- CPU frequency: 64 MHz / 128 MHz
- BLE support: On / Off
- BLE TX power:
-20,-8,0,+8dBm - BLE timing profile: Interop / Balanced low-power / Aggressive low-power
- BLE trace: Off / On
- Power profile: Balanced / Low power (WFI idle)
- Peripheral auto-gating: Off / 2 ms / 200 us
- Antenna route: Ceramic / External U.FL
- Serial routing: USB bridge / Header UART
Core examples:
hardware/nrf54l15clean/0.1.0/examples/01.Basics/AnalogReadSerial/AnalogReadSerial.inohardware/nrf54l15clean/0.1.0/examples/03.Peripherals/PeripheralProbe/PeripheralProbe.inohardware/nrf54l15clean/0.1.0/examples/03.Peripherals/InterruptPwmApiProbe/InterruptPwmApiProbe.inohardware/nrf54l15clean/0.1.0/examples/03.Peripherals/WireRepeatedStartProbe/WireRepeatedStartProbe.inohardware/nrf54l15clean/0.1.0/examples/03.Peripherals/WireTargetResponder/WireTargetResponder.ino
Library examples (HAL + BLE + power):
.../examples/BoardBatteryAntennaBusControl/BoardBatteryAntennaBusControl.ino.../examples/InterruptWatchdogLowPower/InterruptWatchdogLowPower.ino.../examples/BleAdvertiser/BleAdvertiser.ino.../examples/BlePassiveScanner/BlePassiveScanner.ino.../examples/BleActiveScanner/BleActiveScanner.ino.../examples/BleConnectionPeripheral/BleConnectionPeripheral.ino.../examples/BleGattBasicPeripheral/BleGattBasicPeripheral.ino.../examples/BleCustomGattRuntime/BleCustomGattRuntime.ino.../examples/BleBatteryNotifyPeripheral/BleBatteryNotifyPeripheral.ino.../examples/BlePairingEncryptionStatus/BlePairingEncryptionStatus.ino.../examples/BleBondPersistenceProbe/BleBondPersistenceProbe.ino.../examples/BleConnectionTimingMetrics/BleConnectionTimingMetrics.ino
Validated and stable with host adapter + hardware:
- Advertising
- Passive scanning
- Active scanning (
SCAN_REQ/SCAN_RSP) - Connect/disconnect
- GATT discovery/read
- Battery notify CCCD flow
Current gap (tracked):
- Pairing/bond persistence is still partial.
- Successful
Paired: yes/Bonded: yesoutcomes are observed. - Repeated runs are still unstable due intermittent auth timeouts and Intel host-controller crash artifacts (
Hardware Error 0x0c).
- Successful
Channel sounding status:
- BLE channel sounding / AoA/AoD style feature parity is not implemented yet in this clean core.
- It is tracked as advanced future work due significant PHY + timing + controller complexity.
FEATURE_PARITY.mdTODO.mdPOWER_PROFILE_MEASUREMENTS.mddocs/BLE_CLI_MATRIX_SUMMARY.mddocs/BLE_REGRESSION_RUNBOOK.mddocs/BUG_TRACKER.mdscripts/ble_cli_matrix.shscripts/ble_pair_bond_regression.sh
Use one of:
~/Arduino/hardware/...sketchbook override (active development)~/.arduino15/packages/...package-layout override
Example compile:
arduino-cli compile --fqbn nrf54l15clean:nrf54l15clean:xiao_nrf54l15 \
hardware/nrf54l15clean/0.1.0/examples/03.Peripherals/InterruptPwmApiProbe/InterruptPwmApiProbe.inoExample BLE matrix run:
bash scripts/ble_cli_matrix.sh --port /dev/ttyACM0 --sudoExample pair/bond regression run:
bash scripts/ble_pair_bond_regression.sh --port /dev/ttyACM0 --sudo --attempts 10 --mode pair-bondExample bonded reconnect regression run:
bash scripts/ble_pair_bond_regression.sh --port /dev/ttyACM0 --sudo --attempts 5 --mode bonded-reconnect --example BleBondPersistenceProbeIf multiple host adapters are present:
bash scripts/ble_pair_bond_regression.sh --sudo --controller AA:BB:CC:DD:EE:FF --btmon-iface hci1