nRF Platform Guide
Xylolabs SDK integration for Nordic Semiconductor nRF microcontrollers.
Supported Targets
| MCU | Core | Clock | RAM | Connectivity | Audio Capability |
|---|---|---|---|---|---|
| nRF9160 | Cortex-M33 | 64 MHz | 256 KB | LTE-M / NB-IoT | Sensors only |
Transport Modes
LTE Modem (nRF9160)
The nRF9160 SiP integrates a Cortex-M33 application core and a dedicated LTE modem
on the same die. The application core communicates with the modem via an IPC link
(shared memory + interrupts). Zephyr's nrf_modem library and socket API abstract
the modem AT commands.
// Rust (Embassy) - Recommended
use nrf_modem::{ConnectionPreference, SystemMode};
// Configure LTE modem transport (nRF9160)
nrf_modem::init(SystemMode {
lte_support: true,
nbiot_support: true,
gnss_support: false,
preference: ConnectionPreference::Lte,
}).await.unwrap();
// Set APN and connect
nrf_modem::send_at("AT+CGDCONT=1,\"IP\",\"your.apn.here\"").await.unwrap();
let socket = nrf_modem::TcpStream::connect(host, port).await.unwrap();
Legacy C equivalent
platform_nrf_config_t cfg = {
.transport = NRF_TRANSPORT_LTE_MODEM,
.wdt_timeout_ms = 30000,
.conn_interval = 0,
.mtu = 1280,
.apn = "your.apn.here", /* or NULL for automatic */
};
platform_nrf_init(&platform, &cfg);
The SDK uses Zephyr's BSD socket API (zsock_connect, zsock_send, zsock_recv) over
the LTE modem. TLS offloading to the modem is supported for low application-core overhead.
Rust Build (Recommended)
# Install dependencies
rustup target add thumbv8m.main-none-eabihf # For nRF9160
cargo install probe-rs-tools
# Build
cd sdk/examples/nrf9160-lte
cargo build --release
# Flash via J-Link
cargo run --release
See sdk/examples/ for all nRF examples.
Legacy C Build System
Zephyr / nRF Connect SDK (west)
The SDK is packaged as a Zephyr module. Add it to your application's west.yml:
# west.yml
manifest:
projects:
- name: xylolabs-sdk
url: https://github.com/your-org/xylolabs-sdk
path: modules/xylolabs
revision: main
Or reference it locally in CMakeLists.txt before the Zephyr find_package:
cmake_minimum_required(VERSION 3.20)
# Add SDK as a Zephyr module
list(APPEND ZEPHYR_EXTRA_MODULES ${CMAKE_CURRENT_SOURCE_DIR}/../sdk/c/nrf)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(my_xylolabs_device)
target_sources(app PRIVATE
src/main.c
src/platform_impl.c
)
target_compile_definitions(app PRIVATE NRF_PLATFORM)
Build Commands
# Install nRF Connect SDK (ncs) and initialize west workspace
west init -m https://github.com/nrfconnect/sdk-nrf --mr v2.6.0 ncs
cd ncs && west update
# Build for nRF9160-DK (LTE transport)
west build -b nrf9160dk/nrf9160/ns -- -DCONF_FILE=prj_lte.conf
# Flash
west flash
# Serial console
west espressif monitor # or: minicom -D /dev/ttyACM0 -b 115200
Kconfig Options (prj.conf)
For LTE (nRF9160):
# prj_lte.conf
CONFIG_NRF_MODEM_LIB=y
CONFIG_LTE_LINK_CONTROL=y
CONFIG_MODEM_INFO=y
CONFIG_NET_SOCKETS_OFFLOAD=y
CONFIG_NET_SOCKETS_POSIX_NAMES=y
CONFIG_XYLOLABS_TRANSPORT_LTE=y
CONFIG_XYLOLABS_AUDIO_CHANNELS=0
Memory Budget
nRF9160 — LTE Sensor Node
| Region | Size |
|---|---|
| nrf_modem library | ~32 KB |
| Zephyr kernel + net stack | ~24 KB |
| XMBP packet buffer | 4 KB |
| TLS credential storage | ~4 KB |
| Sensor buffers | ~2 KB |
| Application stack | ~4 KB |
| Total used | ~70 KB |
| Available | ~186 KB |
Power Consumption
| Mode | nRF9160 |
|---|---|
| Active (sensors) | ~3 mA |
| LTE-M TX (peak) | ~220 mA |
| LTE-M RX | ~6 mA |
| PSM (LTE, RRC idle) | ~2.5 µA |
eDRX and PSM (nRF9160)
Configure eDRX and PSM for minimal LTE-M power draw between transmissions:
// Rust (Embassy) - Recommended
use nrf_modem::send_at;
// Enable PSM: periodic TAU 1 hour, active time 10 s
send_at("AT+CPSMS=1,,,\"00100001\",\"00000101\"").await.unwrap();
// Enable eDRX: 40.96 s paging cycle
send_at("AT+CEDRXS=2,4,\"0101\"").await.unwrap();
Legacy C equivalent
/* Enable PSM: periodic TAU 1 hour, active time 10 s */
lte_lc_psm_req(true);
/* Enable eDRX: 40.96 s paging cycle */
lte_lc_edrx_req(LTE_LC_LTE_MODE_LTEM, "0101");
When PSM is active, the modem powers down between scheduled transmissions. The application
core also enters low-power state via Zephyr's k_sleep() until the next batch interval.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| LIS2DH12 not found at boot | DTS overlay not applied or SPI CS pin wrong | Check west build overlay path; verify cs-gpios matches your board wiring |
| nRF9160 modem init timeout | SIM not inserted or APN misconfigured | Verify SIM and APN; run AT+CEREG? via UART shell to check registration state |
| High current in sleep | GPIO leakage or peripheral not suspended | Ensure SPI CS is driven high, disable LIS2DH12 via powerdown mode before sleep |
| XMBP buffer overflow | Batch flush interval too long | Reduce XYLOLABS_META_BATCH_MS or increase XYLOLABS_XMBP_BUF_SIZE |
| Watchdog reset during LTE connect | LTE attach takes >30 s on cold start | Increase wdt_timeout_ms to 60000 for first boot; feed WDT during modem init |