Nordic nRF Firmware Dev Guide

A comprehensive guide to developing firmware for Nordic nRF52, nRF53, nRF54, nRF7002, and nRF9160 SoCs — from project planning and toolchain setup through driver integration, wireless protocols, testing, and secure OTA deployment.

1. Planning & Requirements

Define project scope, requirements, and select the appropriate Nordic SoC for your application.

The planning phase is critical for embedded projects. Choosing the right Nordic SoC upfront prevents costly redesigns later. Consider your wireless protocol needs, power budget, processing requirements, and security features when making your selection.

  1. 1

    Select Nordic SoC Based on Requirements

    Choose the right Nordic chip for your application based on connectivity, processing power, and power consumption needs.

    Tips

    • nRF52832/52840: Best for BLE applications, mesh networking, and low-power sensors
    • nRF5340: Dual-core for complex applications requiring both connectivity and processing
    • nRF54 Series: Latest generation with improved power efficiency and performance
    • nRF7002: WiFi 6 companion IC for cloud-connected applications
    • nRF9160: Cellular IoT (LTE-M/NB-IoT) with GPS for asset tracking and remote monitoring
  2. 2

    Define Wireless Connectivity Needs

    Determine which wireless protocols your application requires and ensure your chosen SoC supports them.

    Tips

    • BLE: Short-range, low-power, ideal for wearables and sensors
    • Thread/Zigbee: Mesh networking for smart home and industrial IoT
    • WiFi: High bandwidth for streaming and cloud connectivity
    • LTE-M/NB-IoT: Wide-area coverage for remote assets
    • Consider multi-protocol support (BLE + Thread) for future flexibility
  3. 3

    Create System Architecture

    Design your system architecture considering Nordic's SoftDevice, protocol stacks, and application requirements.

    Reference

    System Architecture Layers:
    - Application Layer: Business Logic, State Machines, Protocol Handlers
    - Middleware Layer: nRF Connect SDK Libraries, Zephyr Subsystems
    - OS Layer: Zephyr RTOS (threads, timers, workqueues)
    - HAL Layer: Nordic HAL / Zephyr Device Drivers
    - Hardware Layer: Nordic SoC + External Peripherals

    Tips

    • Separate hardware-specific code into HAL modules
    • Use Zephyr's native drivers when available
    • Plan memory layout for SoftDevice + application + OTA
  4. 4

    Establish Power Budget

    Calculate expected power consumption and battery life early in the design process.

    Reference

    Power Budget Calculation Example:
    Active Mode (BLE advertising @ 1s interval):
      Radio TX: 4.6mA x 1ms = 4.6uAs per interval
      CPU: 3mA x 0.5ms = 1.5uAs per interval
      Average: ~6uA continuous
    
    Sleep Mode (System ON, RTC running): 1.5uA base
    
    Target: CR2032 (225mAh) for 2 years
      Available: 225mAh / (2 years x 8760 hours) = 12.8uA
      Budget: 10uA average leaves headroom

    Tips

    • Use Nordic Power Profiler Kit II for accurate measurements
    • Account for peak currents when sizing batteries
    • Include all peripherals in power calculations
    • Plan for temperature variations affecting battery capacity
  5. 5

    Plan Peripheral Usage

    Map out which peripherals you need and their pin assignments.

    Tips

    • Check pin multiplexing constraints in the datasheet
    • Reserve pins for programming/debugging (SWD)
    • Consider peripheral power domains for low-power modes
    • Plan for hardware flow control on UART if needed
  6. 6

    Define Security Requirements

    Determine security features needed: secure boot, encryption, TrustZone, key storage.

    Tips

    • nRF52: Software-based security, CryptoCell for crypto acceleration
    • nRF53/54: Arm TrustZone for hardware isolation
    • nRF9160: Trusted Firmware-M (TF-M) for secure processing
    • Plan key provisioning and storage strategy early

2. Development Environment Setup

Configure Nordic's toolchain and nRF Connect SDK for efficient development.

Setting up the development environment correctly saves hours of debugging later. Nordic provides excellent tooling through nRF Connect for Desktop and VS Code extensions. The nRF Connect SDK builds on Zephyr RTOS and provides Nordic-specific drivers and libraries.

  1. 1

    Install nRF Connect for Desktop

    Download and install nRF Connect for Desktop, which provides access to all Nordic development tools.

    Reference

    Key apps to install via nRF Connect for Desktop:
    - Toolchain Manager: Install and manage SDK versions
    - Programmer: Flash firmware to devices
    - Bluetooth Low Energy: Debug BLE connections
    - Power Profiler: Analyze power consumption
    - Serial Terminal: UART communication

    Tips

    • Keep nRF Connect for Desktop updated for latest tool versions
    • Install all recommended apps for comprehensive development support
    • Toolchain Manager handles SDK and toolchain version management
  2. 2

    Set Up nRF Connect SDK with Zephyr

    Use Toolchain Manager to install the nRF Connect SDK which includes Zephyr RTOS and all necessary tools.

    Reference

    SDK structure after installation:
    ~/ncs/
    ├── nrf/           # Nordic-specific code and samples
    ├── zephyr/        # Zephyr RTOS core
    ├── modules/       # Third-party modules (mbedTLS, etc.)
    ├── bootloader/    # MCUboot bootloader
    └── tools/         # Build tools
    
    Verify installation:
    $ west --version
    $ cmake --version

    Tips

    • Use LTS (Long Term Support) SDK versions for production projects
    • nRF Connect SDK v2.x uses west for build management
    • Keep a backup of working SDK versions before upgrading
  3. 3

    Configure VS Code with nRF Connect Extension

    Install VS Code and the nRF Connect Extension Pack for the best development experience.

    Tips

    • Install the full nRF Connect Extension Pack (includes C/C++, CMake, DTS)
    • Use the nRF Connect sidebar for build, flash, and debug operations
    • Configure IntelliSense for accurate code completion
  4. 4

    Install nRF Command Line Tools

    Install command-line tools for scripting, automation, and CI/CD integration.

    Reference

    Key commands:
    $ nrfutil version             # Check installation
    $ nrfutil device list         # List connected devices
    $ nrfutil device program --firmware app.hex  # Flash firmware
    $ nrfutil device reset        # Reset device
    $ nrfutil device recover      # Recover locked device
    
    West build commands (Zephyr):
    $ west build -b nrf52840dk_nrf52840  # Build for target
    $ west flash                          # Flash to device
    $ west debug                          # Start debug session

    Tips

    • Add nrfutil to your PATH for easy access
    • Use --snr flag to target specific device when multiple connected
    • Combine with west for streamlined workflow
  5. 5

    Set Up Development Kit

    Connect and configure your Nordic Development Kit for programming and debugging.

    Tips

    • Update DK firmware using nRF Connect Programmer
    • Check jumper settings for power source selection
    • Install USB drivers if not automatically detected
    • Use board's onboard J-Link for debugging (no external debugger needed)
  6. 6

    Initialize Git Repository

    Set up version control with proper structure for Nordic/Zephyr projects.

    Reference

    Recommended .gitignore for nRF Connect SDK projects:
    build/
    *.pyc
    __pycache__/
    .west/
    *.log
    *.elf
    *.hex
    *.bin
    .vscode/settings.json
    *.DS_Store

    Tips

    • Track prj.conf, overlay files, and Kconfig in version control
    • Don't commit build directories or SDK files
    • Use Git tags to mark firmware releases
    • Include hardware revision in commit history

3. Hardware Abstraction & Drivers

Leverage Nordic's HAL and Zephyr drivers for hardware initialization and peripheral access.

The nRF Connect SDK provides comprehensive hardware abstraction through Zephyr's device driver model and Nordic-specific HAL layers. Using Device Tree for configuration keeps your C code clean and makes porting between boards straightforward.

  1. 1

    Configure Device Tree

    Use Device Tree Source (DTS) files and overlays to configure hardware without modifying C code.

    Reference

    Example overlay file (nrf52840dk.overlay):
    Enable I2C with BME280 sensor at address 0x76
    Configure GPIO for status LED on pin P0.13
    Use aliases for hardware-independent code access

    Tips

    • Use overlays instead of modifying board DTS files
    • Check compatible strings in Zephyr bindings documentation
    • Use aliases for hardware-independent code
    • Validate overlays with 'west build' before flashing
  2. 2

    Initialize Clock System

    Configure high-frequency and low-frequency clocks for optimal performance and power consumption.

    Reference

    Clock configuration in prj.conf:
    CONFIG_CLOCK_CONTROL=y
    CONFIG_CLOCK_CONTROL_NRF=y
    
    Notes:
    - HFCLK (64MHz) is needed for radio and high-speed peripherals
    - LFCLK (32.768kHz) runs always for RTC and timers
    - Clocks are managed automatically by Zephyr in most cases

    Tips

    • HFCLK (64MHz) is needed for radio and high-speed peripherals
    • LFCLK (32.768kHz) runs always for RTC and timers
    • Use external 32kHz crystal for best BLE timing accuracy
    • Clocks are managed automatically by Zephyr in most cases
  3. 3

    Set Up GPIO

    Configure GPIO pins for inputs, outputs, and interrupts using Zephyr's GPIO API.

    Reference

    GPIO setup pattern:
    1. Get GPIO device from Device Tree using GPIO_DT_SPEC_GET
    2. Check gpio_is_ready_dt() before using GPIO
    3. Configure with gpio_pin_configure_dt()
    4. For buttons: add interrupt with gpio_pin_interrupt_configure_dt()
    5. Use gpio_init_callback() and gpio_add_callback() for ISR

    Tips

    • Always check gpio_is_ready_dt() before using GPIO
    • Use GPIO_DT_SPEC_GET for compile-time device tree access
    • Configure interrupt polarity based on hardware (pull-up/pull-down)
    • Debounce button inputs in software or hardware
  4. 4

    Configure Serial Interfaces (UART, SPI, I2C)

    Set up communication peripherals using Zephyr device drivers.

    Reference

    Enable peripherals in prj.conf:
    CONFIG_UART_ASYNC_API=y
    CONFIG_I2C=y
    CONFIG_SPI=y
    
    Pattern for I2C:
    1. Get device with DEVICE_DT_GET(DT_NODELABEL(i2c0))
    2. Check device_is_ready() before use
    3. Use i2c_write_read() for register access

    Tips

    • Use async APIs for non-blocking operations
    • Check max clock frequencies in peripheral datasheets
    • Configure DMA for high-throughput transfers
    • Handle bus errors and implement retry logic
  5. 5

    Implement Interrupt Handlers

    Handle hardware interrupts efficiently using Zephyr's ISR management.

    Reference

    ISR best practice pattern:
    1. Keep ISR short - just submit work with k_work_submit()
    2. Use k_work_init() to initialize work item in main()
    3. Do heavy processing in work handler, not ISR
    4. Use volatile for data shared between ISR and main

    Tips

    • Keep ISRs as short as possible
    • Use work queues to defer processing
    • Avoid blocking calls (malloc, printf) in ISRs
    • Use atomic operations for shared data
  6. 6

    Set Up Power Management

    Configure power management for optimal battery life using Nordic's PM API.

    Reference

    Power management in prj.conf:
    CONFIG_PM=y
    CONFIG_PM_DEVICE=y
    CONFIG_PM_DEVICE_RUNTIME=y
    
    Use pm_device_action_run() to suspend/resume peripherals
    Use pm_policy_state_lock_get/put() during critical operations

    Tips

    • Zephyr automatically enters low-power modes when idle
    • Use PM_DEVICE to control individual peripheral power
    • Lock power states during time-critical operations
    • Profile power with and without PM enabled

4. Wireless Protocol Integration

Integrate Nordic's wireless protocols and implement application logic.

Nordic provides production-ready protocol stacks in the nRF Connect SDK. The Bluetooth stack is based on Zephyr's implementation with Nordic optimizations. Thread, Zigbee, and Matter support enable smart home applications, while cellular IoT is supported on the nRF9160.

  1. 1

    Configure Bluetooth Low Energy

    Set up BLE with Zephyr's Bluetooth stack for advertising, connections, and GATT services.

    Reference

    BLE configuration in prj.conf:
    CONFIG_BT=y
    CONFIG_BT_PERIPHERAL=y
    CONFIG_BT_DEVICE_NAME="MyDevice"
    CONFIG_BT_DEVICE_APPEARANCE=833
    CONFIG_BT_MAX_CONN=1
    CONFIG_BT_MAX_PAIRED=2
    
    Initialization flow:
    1. bt_enable(NULL) to initialize stack
    2. Define advertising data with BT_DATA macros
    3. Register connection callbacks with BT_CONN_CB_DEFINE
    4. Start advertising with bt_le_adv_start()

    Tips

    • Use BT_CONN_CB_DEFINE for static callback registration
    • Configure connection parameters for your power/latency needs
    • Enable CONFIG_BT_SETTINGS to persist bonding information
    • Use nRF Connect mobile app for testing and debugging
  2. 2

    Implement GATT Services

    Create custom BLE services and characteristics for your application.

    Reference

    GATT service pattern:
    1. Define custom 128-bit UUIDs with BT_UUID_DECLARE_128
    2. Create read/write handlers for characteristics
    3. Use BT_GATT_SERVICE_DEFINE to declare service
    4. Include BT_GATT_CCC for notification support
    5. Use bt_gatt_notify() to send notifications

    Tips

    • Use 128-bit UUIDs for custom services
    • Include CCC (Client Characteristic Configuration) for notifications
    • Test with nRF Connect mobile app's GATT viewer
    • Consider using Nordic's GATT Service samples as templates
  3. 3

    Add Thread/Zigbee Support

    Enable mesh networking protocols for smart home and industrial IoT applications.

    Reference

    Thread configuration in prj.conf:
    CONFIG_NETWORKING=y
    CONFIG_NET_L2_OPENTHREAD=y
    CONFIG_OPENTHREAD_NORDIC_LIBRARY_MTD=y
    CONFIG_OPENTHREAD_CHANNEL=11
    CONFIG_OPENTHREAD_PANID=4660
    
    Use OpenThread API via openthread_get_default_context()

    Tips

    • Thread requires IEEE 802.15.4 radio (nRF52840, nRF5340)
    • Use OpenThread CLI sample for initial testing
    • Configure network credentials via CLI or programmatically
    • Consider Matter for cross-ecosystem compatibility
  4. 4

    Configure WiFi for nRF7002

    Set up WiFi connectivity using the nRF7002 companion IC.

    Reference

    WiFi configuration in prj.conf:
    CONFIG_WIFI=y
    CONFIG_WIFI_NRF700X=y
    CONFIG_WPA_SUPP=y
    CONFIG_NET_L2_WIFI_MGMT=y
    CONFIG_NET_DHCPV4=y
    
    Use net_mgmt(NET_REQUEST_WIFI_CONNECT, ...) to connect

    Tips

    • nRF7002 requires nRF5340 or nRF52840 as host
    • Enable WPA3 for enhanced security
    • Use low-power modes (TWT) for battery-powered devices
    • Test with different access points for compatibility
  5. 5

    Implement LTE-M/NB-IoT for nRF9160

    Set up cellular connectivity for wide-area IoT applications.

    Reference

    LTE configuration in prj.conf:
    CONFIG_LTE_LINK_CONTROL=y
    CONFIG_NRF_MODEM_LIB=y
    CONFIG_MODEM_INFO=y
    
    Initialization:
    1. nrf_modem_lib_init() to start modem
    2. lte_lc_register_handler() for events
    3. lte_lc_connect_async() to connect to network

    Tips

    • Use LTE-M for mobility, NB-IoT for stationary sensors
    • Configure PSM (Power Saving Mode) and eDRX for power optimization
    • Test with nRF Cloud for easy connectivity verification
    • Handle network registration and connection loss gracefully

    Resources

  6. 6

    Develop Application State Machines

    Implement application logic using state machines for reliable operation.

    Reference

    State machine pattern:
    1. Define states as enum (INIT, IDLE, ADVERTISING, CONNECTED, etc.)
    2. Create state handler functions for each state
    3. Use function pointer array for state dispatch
    4. Implement transition_to() function for state changes
    5. Consider Zephyr's SMF for complex state machines

    Tips

    • Use state machines for complex control flow
    • Document state transitions with diagrams
    • Handle all edge cases and error states
    • Use Zephyr's SMF (State Machine Framework) for complex state machines

5. Testing & Validation

Test firmware using Nordic's tools and validate wireless performance.

Thorough testing is essential for reliable embedded systems. Nordic provides excellent tools for BLE testing, power profiling, and RF analysis. Combine automated testing with manual validation on real hardware to catch issues before deployment.

  1. 1

    Use nRF Connect Mobile App

    Test BLE functionality with Nordic's mobile app for Android and iOS.

    Tips

    • Scan for your device's advertising packets
    • Connect and explore GATT services and characteristics
    • Read, write, and enable notifications on characteristics
    • View connection parameters and signal strength
    • Log data for later analysis
  2. 2

    Perform Power Profiling

    Measure actual power consumption using Power Profiler Kit II (PPK2).

    Reference

    Production configuration for accurate profiling:
    CONFIG_LOG=n           # Disable logging
    CONFIG_ASSERT=n        # Disable asserts
    CONFIG_DEBUG=n         # Disable debug
    
    Test all modes: advertising, connected, data transfer, sleep
    Calculate: Battery Life = Capacity (mAh) / Average Current (mA)

    Tips

    • Measure each operating mode separately
    • Account for peak currents (radio TX)
    • Test at expected temperature range
    • Compare measurements against datasheet values
    • Use PPK2 trigger mode for event-based capture
  3. 3

    Test RF Performance

    Validate wireless range and reliability using nRF Sniffer and other tools.

    Reference

    RF testing checklist:
    1. Range testing at various distances
    2. Test through walls and obstacles
    3. Measure RSSI and packet loss
    4. Test with WiFi and other 2.4GHz interference
    5. Verify antenna matching and radiation pattern

    Tips

    • Use nRF Sniffer to capture and analyze packets
    • Test with multiple phone models for BLE
    • Document RF test results for certification
    • Consider antenna placement in enclosure design

    Resources

  4. 4

    Validate Protocol Compliance

    Ensure your implementation meets protocol standards and passes certification tests.

    Tips

    • Run Bluetooth SIG qualification tests
    • Test with official certification equipment if available
    • Document compliance for regulatory submissions
    • Use Nordic's pre-certified modules to simplify certification
  5. 5

    Conduct Integration Testing

    Test complete system integration with all components and interfaces.

    Reference

    Integration test checklist:
    Hardware: All sensors, actuators, power supply, reset sequence
    Software: All tasks, inter-task communication, error handling
    System: End-to-end data flow, mobile app, cloud connectivity, OTA

    Tips

    • Create automated test scripts where possible
    • Test failure scenarios (power loss, disconnect)
    • Verify behavior across temperature range
    • Document test procedures for repeatability
  6. 6

    Perform Long-Term Stability Testing

    Run extended tests to catch memory leaks, timing issues, and rare bugs.

    Tips

    • Run for days or weeks in realistic conditions
    • Monitor memory usage over time
    • Log errors and unexpected behaviors
    • Test rapid connect/disconnect cycles
    • Stress test with maximum data rates

6. Deployment & OTA Updates

Deploy firmware and implement secure OTA updates using Nordic's DFU.

Proper deployment includes secure bootloading, over-the-air update capability, and protection against unauthorized access. Nordic's MCUboot integration provides a robust foundation for secure firmware updates.

  1. 1

    Implement Device Firmware Update (DFU)

    Set up Nordic's DFU for firmware updates over BLE, UART, or USB.

    Reference

    DFU over BLE configuration in prj.conf:
    CONFIG_BOOTLOADER_MCUBOOT=y
    CONFIG_MCUBOOT_SIGNATURE_KEY_FILE="path/to/key.pem"
    CONFIG_NCS_SAMPLE_MCUMGR_BT_OTA_DFU=y
    CONFIG_MCUMGR=y
    CONFIG_MCUMGR_GRP_IMG=y
    CONFIG_MCUMGR_GRP_OS=y

    Tips

    • Use MCUmgr protocol for standardized update flow
    • Test updates with nRF Connect mobile app
    • Plan partition sizes for largest expected image
    • Implement update progress indication in UI
  2. 2

    Configure Secure Bootloader (MCUboot)

    Set up MCUboot for verified boot and secure update installation.

    Reference

    MCUboot configuration in prj.conf:
    CONFIG_BOOTLOADER_MCUBOOT=y
    CONFIG_MCUBOOT_SIGNATURE_KEY_FILE="priv-key.pem"
    CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y
    CONFIG_MCUBOOT_IMAGE_VERSION="1.0.0"
    
    Build signed image:
    $ west build -b nrf52840dk_nrf52840
    Output: build/zephyr/app_signed.hex

    Tips

    • Store signing keys securely (HSM for production)
    • Use different keys for development and production
    • Enable encryption for sensitive firmware
    • Test rollback protection mechanism

    Resources

  3. 3

    Set Up OTA Infrastructure

    Deploy backend infrastructure for managing and distributing firmware updates.

    Tips

    • Use nRF Cloud for quick prototyping
    • Implement version checking before download
    • Support delta updates to reduce bandwidth
    • Track update success/failure rates
    • Plan for fleet segmentation (staged rollouts)

    Resources

  4. 4

    Enable Security Features

    Configure TrustZone, secure key storage, and access protection.

    Reference

    TrustZone configuration for nRF5340/nRF9160:
    CONFIG_ARM_TRUSTZONE_M=y
    CONFIG_SPM=y  # Secure Partition Manager
    
    Access protection:
    - APPROTECT: Blocks debugger access
    - SECUREAPPROTECT: Blocks secure domain access
    - Use KMU (Key Management Unit) for secure key storage

    Tips

    • Enable APPROTECT in production to prevent debugging
    • Use TF-M for advanced secure processing (nRF91)
    • Implement secure provisioning for keys
    • Test that protection cannot be bypassed
  5. 5

    Create Production Firmware

    Build optimized, protected firmware for production deployment.

    Reference

    Production prj.conf settings:
    CONFIG_LOG=n
    CONFIG_ASSERT=n
    CONFIG_DEBUG=n
    CONFIG_PRINTK=n
    CONFIG_SIZE_OPTIMIZATIONS=y
    CONFIG_STACK_CANARIES=y
    CONFIG_HW_STACK_PROTECTION=y
    
    Build: west build -b board -- -DCONF_FILE=prj_release.conf

    Tips

    • Create separate debug and release configurations
    • Remove all debug output for production
    • Enable hardware stack protection
    • Verify final image size fits in flash
    • Store build artifacts with version tags
  6. 6

    Establish Monitoring and Diagnostics

    Implement logging and monitoring for deployed devices.

    Tips

    • Use nRF Cloud for device monitoring
    • Implement error logging with persistence
    • Add heartbeat/health check functionality
    • Plan for remote diagnostics capability
    • Track key metrics (battery, connectivity, errors)

Nordic Development Tools

IDEs

VS Code with nRF Connect Extension, SEGGER Embedded Studio, Keil MDK

SDK

nRF Connect SDK, nRF5 SDK, Zephyr RTOS

Debuggers

J-Link, nRF52/53/54/9160 DK onboard debugger

Programming Tools

nRF Command Line Tools, nrfutil, west (Zephyr)

Testing Tools

nRF Connect for Mobile, Power Profiler Kit II, nRF Sniffer

Wireless Tools

nRF Cloud, Bluetooth Mesh SDK, Thread/Zigbee SDK

AI-Powered

Skip the boilerplate — generate your nRF project

FirmwareMaestro scaffolds a complete nRF Connect SDK + Zephyr project tailored to your hardware, with sensible Kconfig, Device Tree overlays, and MCUboot wiring out of the box.