Skip to content

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.


# 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