Porting nRF52833 custom-board BLE application from NCS 2.8.0 to 3.4.0

Hi,

We have a BLE peripheral on nRF52833-QIAA (custom board based on nrf52833) building with NCS 2.8.0, sysbuild, extended advertising, GATT, a prebuilt custom bootloader, and static partitions (pm_static). We need to move to NCS 3.4.0.

  1. Can we jump 2.8.0 -> 3.4.0 directly, or must we go through intermediate NCS releases?

  2. In 3.4.0, is SoftDevice Controller required for nRF52833, or can we keep the Zephyr BT controller (bt_ctlr_set_public_addr(), bt_le_ext_adv_*)?

  3. Will our existing sysbuild + pm_static layout (custom bootloader at 0x0, app at 0x3000) still work, and can we still DFU an application-only hex onto devices that already have the current bootloader?

  4. Is TinyCrypt still supported in 3.4.0, or do we have to switch to PSA / Mbed TLS?

  5. For a custom nRF52833 board, what usually breaks first in this upgrade (board files, BT APIs, Partition Manager, or flash size)?

Thanks in advance.

Parents
  • hi jitendra,

    thanks for posting doubt here,

    1. Direct 2.8.0 → 3.4.0 jump?

    • Yes, no sequential upgrade needed — but read migration notes 3.0→3.4 cumulatively (Zephyr 3.7→4.4).
    • Biggest 3.0 break was parent/child multi-image removal — you're on sysbuild already, so skipped.
    • 3.4.0 is Nordic's first LTS (5 yrs patch-only) and the last release supporting nRF52 — land here and stop.

    2. SoftDevice Controller required?

    • SDC is default and the only production-supported controller. Zephyr LL still builds (bt-ll-sw-split snippet) but is EXPERIMENTAL/unsupported.
    • bt_ctlr_set_public_addr() works on SDC — implemented in sdk-nrf/subsys/bluetooth/controller/hci_driver.c.
    • bt_le_ext_adv_* is host API — unchanged. No code change needed.

    3. sysbuild + pm_static + app-only DFU?

    • Partition Manager deprecated but still works; removal end of 2026, so LTS keeps it for the full window. Your 0x0/0x3000 layout is preservable.
    • App-only DFU works only if your bootloader's image contract (header/trailer/CRC/jump offset) is unchanged — that's yours to own.
    • Main trap: NCS 3.0's ZMS settings backend is incompatible with legacy. Set CONFIG_SETTINGS_ZMS_LEGACY=y and keep the storage partition byte-identical, or fielded units lose all bonds.
    • Test DFU on a golden unit still running the 2.8.0 app, not on erased boards.

    4. TinyCrypt?

    • Removed from Zephyr entirely — mandatory move to PSA Crypto.
    • Don't go via legacy Mbed TLS: 3.4.0 ships Mbed TLS 4.1.0 with deprecated mbedtls_ APIs removed. Use CONFIG_PSA_CRYPTO for crypto, CONFIG_MBEDTLS only for TLS/X.509.
    • nRF52833 has no CryptoCell → software nrf_oberon, bigger than TinyCrypt. Budget for it.
    • Also: BLE legacy pairing off by default since 3.0 — disable CONFIG_BT_SMP_SC_PAIR_ONLY if needed.

    5. What breaks first?

    1. Kconfig/DTS churn — high volume, low risk
    2. TinyCrypt → PSA — guaranteed
    3. RAM/flash footprint — on 52833, RAM binds first
    4. PM/DFU — hit last, highest consequence (bricked/wiped units, not build errors)
    5. Board files — least likely; 2.8.0 is already HWMv2

    Also: west flash now defaults to nRF Util not nrfjprog (breaks CI silently); HAL defines like NRF52833_XXAA deprecated → use Kconfig symbols.

    thanks and regards

    NIshant

Reply
  • hi jitendra,

    thanks for posting doubt here,

    1. Direct 2.8.0 → 3.4.0 jump?

    • Yes, no sequential upgrade needed — but read migration notes 3.0→3.4 cumulatively (Zephyr 3.7→4.4).
    • Biggest 3.0 break was parent/child multi-image removal — you're on sysbuild already, so skipped.
    • 3.4.0 is Nordic's first LTS (5 yrs patch-only) and the last release supporting nRF52 — land here and stop.

    2. SoftDevice Controller required?

    • SDC is default and the only production-supported controller. Zephyr LL still builds (bt-ll-sw-split snippet) but is EXPERIMENTAL/unsupported.
    • bt_ctlr_set_public_addr() works on SDC — implemented in sdk-nrf/subsys/bluetooth/controller/hci_driver.c.
    • bt_le_ext_adv_* is host API — unchanged. No code change needed.

    3. sysbuild + pm_static + app-only DFU?

    • Partition Manager deprecated but still works; removal end of 2026, so LTS keeps it for the full window. Your 0x0/0x3000 layout is preservable.
    • App-only DFU works only if your bootloader's image contract (header/trailer/CRC/jump offset) is unchanged — that's yours to own.
    • Main trap: NCS 3.0's ZMS settings backend is incompatible with legacy. Set CONFIG_SETTINGS_ZMS_LEGACY=y and keep the storage partition byte-identical, or fielded units lose all bonds.
    • Test DFU on a golden unit still running the 2.8.0 app, not on erased boards.

    4. TinyCrypt?

    • Removed from Zephyr entirely — mandatory move to PSA Crypto.
    • Don't go via legacy Mbed TLS: 3.4.0 ships Mbed TLS 4.1.0 with deprecated mbedtls_ APIs removed. Use CONFIG_PSA_CRYPTO for crypto, CONFIG_MBEDTLS only for TLS/X.509.
    • nRF52833 has no CryptoCell → software nrf_oberon, bigger than TinyCrypt. Budget for it.
    • Also: BLE legacy pairing off by default since 3.0 — disable CONFIG_BT_SMP_SC_PAIR_ONLY if needed.

    5. What breaks first?

    1. Kconfig/DTS churn — high volume, low risk
    2. TinyCrypt → PSA — guaranteed
    3. RAM/flash footprint — on 52833, RAM binds first
    4. PM/DFU — hit last, highest consequence (bricked/wiped units, not build errors)
    5. Board files — least likely; 2.8.0 is already HWMv2

    Also: west flash now defaults to nRF Util not nrfjprog (breaks CI silently); HAL defines like NRF52833_XXAA deprecated → use Kconfig symbols.

    thanks and regards

    NIshant

Children
  • Hi Nishant, 

    Thanks, this is very useful.

    We will target NCS 3.4.0 LTS directly, use SoftDevice Controller, keep the existing pm_static layout, and plan the TinyCrypt -> PSA / nrf_oberon move.

    A few follow-ups before we start the port:

    1. SDC Kconfig
    On 2.8.0 we have CONFIG_BT=y, CONFIG_BT_HCI=y, CONFIG_BT_PERIPHERAL=y, CONFIG_BT_EXT_ADV=y.
    For production SDC on nRF52833 in 3.4.0, what should we add/remove? In particular: do we keep CONFIG_BT_HCI=y, and should we avoid the bt-ll-sw-split snippet?

    2. TinyCrypt -> PSA for SHA-256 + ECDSA
    We use TinyCrypt only for SHA-256 and ECC-DSA verify (firmware image signature), not for BLE pairing.
    What is the recommended 3.4.0 replacement on nRF52833 (no CryptoCell) - CONFIG_PSA_CRYPTO + nrf_oberon, and which PSA APIs replace tc_sha256_* / uECC_verify?
    Any typical flash/RAM delta vs TinyCrypt on 52833?

    3. Settings / ZMS
    Application settings are stored with our own flash layout, not Zephyr Settings/NVS. We do use BLE GATT connections.
    Does CONFIG_SETTINGS_ZMS_LEGACY=y still apply for BT bonds only, or can we ignore ZMS if we do not use Zephyr Settings for app data?
    If we currently have no bonds stored, can we leave ZMS at the 3.4 default?

    4. Custom DFU contract
    OTA writes the new app to a fixed offset (0x41000) and the existing bootloader swaps/jumps.
    Besides keeping load address and slot size the same, is there anything in 3.4.0 that still changes the image header/trailer for a plain zephyr.hex (not MCUboot signed)?
    We will test DFU on a golden unit that still runs the 2.8.0 app, as you suggested.

    5. RAM on nRF52833
    You noted RAM binds first. With SDC + nrf_oberon + ext-adv + GATT, what is the usual way to measure and cut RAM in 3.4.0 (CONFIG_BT_BUF_*, controller buffers, oberon)?
    Any known-good starting point for a peripheral with two ext-adv sets?

    6. NFC
    We use CONFIG_NFC_T4T_NRFXLIB + NDEF. Is that path still supported on nRF52833 in 3.4.0, or did Kconfig/API names change?

  • hi jitendra,

    1. SDC Kconfig — Add nothing. Keep CONFIG_BT/BT_PERIPHERAL/BT_EXT_ADV, add CONFIG_BT_EXT_ADV_MAX_ADV_SET=2. CONFIG_BT_HCI no longer picks a controller (that's DT zephyr,bt-hci now) — leave it or drop it. Skip bt-ll-sw-split. bt_ctlr_set_public_addr() works on SDC. Diff your generated .config for BT_CTLR_* symbols that silently disappeared.

    2. TinyCrypt → PSAtc_sha256_*psa_hash_compute(); uECC_verify()psa_verify_hash(key, PSA_ALG_ECDSA(PSA_ALG_SHA_256), ...) after psa_crypto_init().

    CONFIG_NRF_SECURITY=y
    CONFIG_PSA_WANT_ALG_SHA_256=y
    CONFIG_PSA_WANT_ALG_ECDSA=y
    CONFIG_PSA_WANT_ECC_SECP_R1_256=y
    CONFIG_PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY=y
    

    Gotcha: uECC pubkeys are raw 64-byte X‖Y, PSA wants 0x04‖X‖Y (65 bytes). Signatures pass through unchanged. If signature verify is your only crypto, use ocrypto directly (CONFIG_NRF_OBERON=y, ocrypto_sha256 / ocrypto_ecdsa_p256_verify) — same shape as TinyCrypt, no PSA core, several KB smaller. PSA full stack ≈ +15–25 KB flash; ocrypto ≈ +6–10 KB.

    3. ZMS — correction: doesn't apply to you. ZMS is for RRAM parts (nRF54L/H); nRF52833 still uses NVS. Don't set SETTINGS_ZMS_LEGACY. No bonds stored → leave 3.4 defaults. Just keep the storage partition offset/size identical. Confirm: grep -E "CONFIG_SETTINGS_(NVS|ZMS)" build/<app>/zephyr/.config

    4. DFU contract — Unsigned zephyr.hex has no header/trailer; nothing in 3.4.0 changes that. Verify CONFIG_ROM_START_OFFSET=0 and CONFIG_FLASH_LOAD_OFFSET=0x3000 in the generated config. Real trap is tooling: artifact path is now build/<app_image>/zephyr/zephyr.hex, not build/zephyr/. Also check the hex for a stray UICR segment at 0x10001000 that your packer must strip.

    5. RAM — flash actually binds first. App 0x3000 → OTA 0x41000 = 248 KB per slot. Build a bare 3.4.0 peripheral against your pm_static before porting app code to see where the baseline lands; if it doesn't fit, it's a layout problem, not a Kconfig one. Then west build -d build/<app_image> -t ram_report / rom_report, plus CONFIG_THREAD_ANALYZER=y for stack slack. Starting point:

    CONFIG_BT_MAX_CONN=1
    CONFIG_BT_EXT_ADV_MAX_ADV_SET=2
    CONFIG_BT_BUF_ACL_TX_COUNT=3
    CONFIG_BT_BUF_ACL_TX_SIZE=27
    CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA=2   # renamed from _RX_COUNT since 2.8.0
    CONFIG_BT_BUF_ACL_RX_SIZE=27
    CONFIG_BT_BUF_EVT_RX_COUNT=4
    CONFIG_BT_ATT_PREPARE_COUNT=0
    CONFIG_BT_RX_STACK_SIZE=2048
    

    Disable BT_CTLR_PHY_CODED/PHY_2M if unused — SDC sizes buffers to what you enable.

    6. NFCCONFIG_NFC_T4T_NRFXLIB + NDEF still supported on nRF52833, names unchanged. Check nfct is enabled in your board DTS and no leftover UICR/GPIO claim on the NFC pins.

    Thanks and regards 

    Nishant

  • Thanks , this gives us a clear plan.

    We will:

    • Stay on SDC (no bt-ll-sw-split)
    • Replace TinyCrypt with nrf_oberon / ocrypto for SHA-256 + ECDSA verify only
    • Leave ZMS alone and keep the storage partition identical
    • Confirm CONFIG_ROM_START_OFFSET=0, CONFIG_FLASH_LOAD_OFFSET=0x3000, and the new zephyr.hex path
    • Keep NFC as-is

    Two clarifications:

    1. BT buffers vs DFU
    We are connectable and transfer firmware over GATT, so today we use:

    CONFIG_BT_BUF_ACL_TX_SIZE=251
    CONFIG_BT_BUF_ACL_RX_SIZE=251
    CONFIG_BT_L2CAP_TX_MTU=247

    If we drop ACL size to 27 as in your RAM starting point, OTA will fail. For a peripheral that must keep large MTU for DFU, which of CONFIG_BT_BUF_* / CONFIG_BT_MAX_CONN=1 can we still cut, and which must stay large?

    Also: please confirm the 3.4.0 name is CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA (replacing CONFIG_BT_BUF_ACL_RX_COUNT).

    2. UICR in the hex
    Public address is programmed into UICR separately (0x10001088). If 3.4.0 emits a UICR segment at 0x10001000 in zephyr.hex, is the usual fix a linker/Kconfig option, or should we strip that segment in our packer?

    We will first build a bare 3.4.0 peripheral against our pm_static and check rom_report / ram_report before porting application code.

  • 1. Buffers

    CONFIG_BT_BUF_ACL_RX_COUNT_EXTRA — confirmed for 3.4.0, but it replaced BT_BUF_ACL_RX_COUNT back in NCS 2.7, so 2.8.0 already has it. RX_COUNT = 1 + EXTRA, EXTRA defaults to BT_MAX_CONN.

    Why 27 breaks you: RX size is your inbound MTU. TX size is only the fragment size — small TX works, just slowly.

    • Keep 251/247: BT_BUF_ACL_RX_SIZE; plus BT_BUF_ACL_TX_SIZE + L2CAP_TX_MTU if you notify outbound.
    • Still cuttable: BT_MAX_CONN=1, BT_BUF_EVT_RX_COUNT → 4–6 (default is 10), BT_L2CAP_TX_BUF_COUNT=2, SDC TX/RX_PACKET_COUNT.
    • Don't: EXTRA=2 (default is already 1 — pure waste); BT_ATT_PREPARE_COUNT=0 if DFU uses long writes.
    • Set BT_CTLR_ADV_DATA_LEN_MAX explicitly — no default, clamps to 31, multiplied by adv-set count.

    2. UICR

    Neither — it shouldn't appear. On nRF52 the &uicr props become compile definitions written by the HAL at runtime, not hex content. No Kconfig suppresses it; if a segment shows up, something you enabled asked for it.

    Crop in the packer anyway as an assertion: srec_cat zephyr.hex -Intel -crop 0x41000 0x80000 -Output app.hex -Intel.

    Bigger risk is the programming hex — nrfutil's default erase mode would wipe the page holding your address at 0x10001088.

    Bare peripheral against pm_static first is the right order.

Related