An LE Audio unicast server (headset) firmware project, with a working example of the Zephyr testing ecosystem progression built alongside it - see docs/testing_ecosystem.md for the why (phase-by-phase history, real bugs found) and docs/testing_guide.md for the how (running and adding tests, day to day).
Target board is nrf5340dk/nrf5340/cpuapp - a standard, upstream-supported
Zephyr board, no custom board definition needed. Real hardware is the plain
nRF5340 DK, not the nRF5340 Audio DK this project originally targeted; the
DK has no I2S codec chip wired up, so audio_handler (I2S output) is
commented out in app_streamctrl.c and excluded from the build in
src/middlewares/CMakeLists.txt until real audio hardware is available.
The DK has 4 LEDs and 4 buttons (led0-led3, sw0-sw3); the app
currently only uses one of each (led0 for connection status, sw0/
button0 wired to a generic press callback).
west.yml pulls nrf from the public
nrfconnect/sdk-nrf, pinned to the
v2.7.0 release tag - no credentials needed, no MY_GITHUB_TOKEN. This
project previously depended on paltatech's private forks (vx_sdk_nrf,
plus a zephyr_boards project for the now-abandoned custom
ble_audio_board); switched to the public upstream for this demo, since
neither fork's Viaanix-specific additions (proprietary cloud logging, an
access-control protocol, the old custom board) are used by this project.
- Zephyr RTOS: 3.6.99
- nRF Connect SDK: v2.7.0
- Zephyr SDK (Toolchain): 0.16.5
- NCS Toolchain installed at:
- Linux:
~/ncs/toolchains/<hash> - Windows:
C:/ncs/toolchains/<hash>
- Linux:
- J-Link debugger for flashing and debugging
gcc-multilib/g++-multilibformake test'snative_simleg, which builds 32-bit (sudo apt-get install gcc-multilib g++-multilibon Linux) — see docs/testing_guide.mdqemu-system-armto runmake test's QEMU leg (sudo apt-get install qemu-system-armon Linux) — see docs/testing_ecosystem.md
Source the environment script to set up paths and toolchain:
source ./start-zephyr-env.shThis script:
- Adds NCS toolchain binaries to PATH
- Sets up Zephyr SDK and toolchain variant
- Exports board root for custom board definitions
- Sources the Zephyr environment
On first setup, update the west manifest and fetch all dependencies:
make west-updatemake buildThis builds the firmware for the configured board (default:
nrf5340dk/nrf5340/cpuapp, set in tools/make/config.mk). The
network core's Bluetooth controller image is built automatically as a
child image (CONFIG_NCS_INCLUDE_RPMSG_CHILD_IMAGE) - no --sysbuild
needed for this NCS revision. Output is zephyr/merged.hex, combining
both cores.
make cleanEdit tools/make/config.mk to change the target board:
BOARD ?= nrf5340dk/nrf5340/cpuappOr override on the command line:
make build BOARD=<other-board>make flashmake flash JLINK_SERIAL=683980738make testRuns tests/ under Twister across native_sim (32-bit host, needs
gcc-multilib), native_sim/native/64 (64-bit host), and mps3/an547
(32-bit QEMU, real ARM cross-compile) — see
docs/testing_guide.md for how tests are
organized and docs/testing_ecosystem.md for
why those platforms. Requires qemu-system-arm (see Prerequisites above)
for the QEMU leg.
make test-cleanmake test-hilFlashes the real production image onto a physical
nrf5340dk/nrf5340/cpuapp and checks its boot log (Bluetooth init,
advertising start) over UART — via Twister's built-in harness: console
regex matching, no pytest involved. Not part of make test — needs real
hardware and a filled-in tools/hardware-map.yml (copy
tools/hardware-map.example.yml and fill in your board's J-Link serial).
See docs/hil_testing.md for setup and current
status.
Five workflows under .github/workflows/, one per concern:
gitlint.yml— commit message format (tools/gitlint/,.gitlint)clang-format.yml— C/C++ formatting (make lint-ci)cmake-format.yml— CMake formatting (make lint-cmake)test.yml—make test(Twister acrossnative_sim/mps3/an547)compile.yml— builds the real production firmware (./prepare_release.sh), fails on any compiler warning, uploads the result as a downloadable Actions artifact
No secrets needed — west.yml addresses the public nrfconnect/sdk-nrf
over HTTPS, so test.yml and compile.yml fetch it with no credentials
at all. See docs/testing_ecosystem.md for
what's verified about these workflows vs. not (none have been run for
real; no way to trigger a GitHub Actions run from the environment they
were written in).
make start-gdb-servermake debug./prepare_release.shBuilds the firmware and packages a versioned release artifact into
release/.
make print-build-pathmake helpBuild artifacts are placed in:
_build_ble_audio_nrf5340dk_nrf5340_cpuapp/
(BOARD's slashes are replaced with underscores for the directory name.)
-
src/— application source code, layered:common/— shared types, macros, and dependency-free helpers (includes firmware version metadata,app_version.c/.h)core/— reserved for low-level system bring-up; currently emptymiddlewares/— one<x>_handler/subfolder per service:led_handler,button_handler,audio_handler(I2S output),codec_handler(LC3),ble_audio_handler(LE Audio unicast server)application/—app_streamctrl.c/.h, the headset state machine that orchestrates the middlewares above
Each layer may only depend on the ones above it in this list (see the
README.mdin each folder).main.cstays a thin entry point that wires everything together. -
boards/— board-specific devicetree overlays and Kconfig fragments -
docs/— design notes, test reports, and other project documentation -
release/— packaged release artifacts (populated byprepare_release.sh) -
tests/—ztestsuites, one per subfolder, run viamake test -
tools/— build system helpers (CMake, Make, gitlint, clang-format/cmake-format)