NCP-UART-HW Firmware¶
Network Co-Processor (NCP) firmware for the EFR32 radio: EFR32MG1B232F256GM48 on the Lidl Silvercrest Smart Home Gateway (BOARD=lidl, the default), EFR32MG13P732F512IM32 on the Sengled Smart Hub G4 (BOARD=sengled-e39-g8c). Both ship prebuilt.
This firmware enables communication with Zigbee coordinators like Zigbee2MQTT and Home Assistant ZHA via EZSP (EmberZNet Serial Protocol).
Multi-board: this firmware also builds for other RTL8196E hubs via
BOARD=(defaultlidl); e.g.BOARD=sengled-e39-g8cfor the Sengled Smart Hub G4, whose prebuilt is committed and validated end-to-end on real hardware (#130) — see../boards/README.md.
Features¶
- EZSP v13 - EmberZNet 7.5.1 serial protocol
- Zigbee PRO R22 - Full Zigbee 3.0 support
- Green Power - Support for battery-free devices
- Source routing - 100-entry route table for large networks
- Up to 32 children - Sleepy end-devices supported
- Hardware flow control - RTS/CTS for reliable TCP operation
Hardware¶
| Component | Specification |
|---|---|
| Zigbee SoC | EFR32MG1B232F256GM48 |
| Flash | 256KB |
| RAM | 32KB |
| Radio | 2.4GHz IEEE 802.15.4 |
| UART | PA0 (TX), PA1 (RX), PA4 (RTS), PA5 (CTS) @ 115200 baud |
Option 1: Flash Pre-built Firmware (Recommended)¶
Pre-built firmware is available in the firmware/ directory. From the
repository root:
# Lidl Silvercrest (default board)
./flash_efr32.sh -y ncp # default baud 115200, gateway from gateway.env
./flash_efr32.sh -y ncp 460800 # 460800 baud (faster, max-tested 892857)
./flash_efr32.sh -y -g 10.0.0.5 ncp # custom gateway IP
# Sengled Smart Hub G4: validated NCP image, default baud 115200
./flash_efr32.sh -y --board sengled-e39-g8c -g 10.0.0.6 ncp
./flash_efr32.sh --help # full CLI reference
The script handles everything: pulse nRST for a clean chip state, switch
the in-kernel UART bridge to flash mode, run the Xmodem upload, write the
matching FIRMWARE_BAUD=<baud> to /userdata/etc/radio.conf so the bridge
arms at the right speed on next boot, then reboot.
Supported NCP bauds (pre-built GBLs): 115200, 230400, 460800, 691200, 892857. For a custom baud, see Option 2 below.
Legacy env-var interface (deprecated, kept for v3.0.x compat):
FW_CHOICE=2 BAUD_CHOICE=460800 CONFIRM=y ./flash_efr32.shstill works with a deprecation warning. Prefer the flag form above.Need other formats (.s37, .hex, .bin)? Build from source (Option 2), they will be in
build/debug/.
Gateway state after flash¶
flash_efr32.sh writes the matching baud to /userdata/etc/radio.conf so
the gateway-side init scripts arm the bridge correctly on next boot. For
NCP at baud <B>:
FIRMWARE=ncp # what's in the EFR32 application slot
FIRMWARE_VERSION=7.5.1 # EmberZNet version embedded in the GBL
FIRMWARE_BAUD=<B> # chip-side UART baud — S50uart_bridge reads this and
# arms TCP:8888 at <B> (no MODE= line; otbr-agent off)
FIRMWARE_BAUD is the single source of truth (chip-side baud =
host-side baud, since both ends of the UART link must agree); the
FIRMWARE* companion keys are informational. See
3-Main-SoC-Realtek-RTL8196E/34-Userdata/README.md
for the full key reference.
The init script S50uart_bridge reads this on boot. Z2M/ZHA then connect
to tcp://<gw>:8888 — no baud setting needed on the client side, the
bridge handles it.
Option 2: Build from Source¶
For users who want to customize network parameters or use a different EmberZNet version.
Prerequisites¶
Install Silicon Labs tools (see 1-Build-Environment/12-silabs-toolchain/):
Or use Docker (see 1-Build-Environment/ for setup):
docker run --rm -v $(pwd):/workspace rtl8196e-gateway-builder \
/workspace/2-Zigbee-Radio-Silabs-EFR32/24-NCP-UART-HW/build_ncp.sh
Build¶
cd 2-Zigbee-Radio-Silabs-EFR32/24-NCP-UART-HW
./build_ncp.sh # default baud 115200
./build_ncp.sh 460800 # custom baud (any value; warns if outside tested set)
./build_ncp.sh --help # show baud options + defaults
Output¶
The output filename embeds the EmberZNet version and the chosen baud:
firmware/
├── ncp-uart-hw-7.5.1-115200-hw.gbl # default (-hw = RTS/CTS flow, #145)
├── ncp-uart-hw-7.5.1-230400-hw.gbl # if you ran ./build_ncp.sh 230400
├── ncp-uart-hw-7.5.1-460800-hw.gbl
├── ncp-uart-hw-7.5.1-691200-hw.gbl
└── ncp-uart-hw-7.5.1-892857-hw.gbl
flash_efr32.sh resolves the right file via a glob — no need to keep
filenames in sync manually.
Other formats (.s37, .hex, .bin) are available in
build/debug/after compilation. Use these for J-Link/SWD flashing or debugging.
Clean¶
Flash¶
Via network (same as Option 1):
Via J-Link/SWD (if you have physical access to the SWD pads):
Usage¶
Architecture¶
+-------------------+ UART +-------------------+ Ethernet +---------------------+
| EFR32MG1B (NCP) | 115200 | RTL8196E | TCP/IP | Host (x86/ARM) |
| | baud | (Gateway SoC) | | |
| EmberZNet Stack |<----------->| in-kernel |<------------>| Zigbee2MQTT |
| + EZSP Protocol | ttyS1 | UART<->TCP bridge| port 8888 | or |
| | | (rtl8196e-uart- | | Home Assistant ZHA |
| HW Flow Control | | bridge) | | |
+-------------------+ +-------------------+ +---------------------+
The RTL8196E kernel bridges the EFR32's UART to TCP:8888 via the in-kernel
rtl8196e-uart-bridge driver (replaces the former serialgateway daemon).
See 34-Userdata for gateway setup.
Zigbee2MQTT Configuration¶
Edit configuration.yaml:
Home Assistant ZHA Configuration¶
Add integration with:
- Serial port path: socket://192.168.1.88:8888
Note: Baudrate and flow control are handled by the in-kernel UART bridge on the gateway side, not by the client application. Change the rate via
echo <baud> > /sys/module/rtl8196e_uart_bridge/parameters/baud.
Customization¶
Changing Baudrate¶
Default is 115200. With the in-kernel UART bridge on kernel 6.18, rates up to 892857 are supported (115200, 230400, 460800, 691200, 892857 tested). See 25-RCP-UART-HW for the math behind 892857.
# 1. Build the GBL at the desired baud
cd 2-Zigbee-Radio-Silabs-EFR32/24-NCP-UART-HW && ./build_ncp.sh 460800
# 2. Flash — radio.conf FIRMWARE_BAUD is updated automatically
./flash_efr32.sh -y ncp 460800
NCP/EZSP doesn't have cpcd's POSIX baud restriction, so all 5 tested values work end-to-end (Z2M ember adapter, ZHA).
Network parameters¶
The build process applies patches to optimize the firmware for these gateways. See patches/README.md for details.
Network Parameters¶
Edit patches/apply_config.sh to modify. For a complete guide, see the Zigbee Network Sizing Guide.
| Parameter | Default | Range | RAM/Entry |
|---|---|---|---|
EMBER_MAX_END_DEVICE_CHILDREN |
32 | 0-64 | ~40 bytes |
EMBER_PACKET_BUFFER_COUNT |
255 | 20-255 | ~36 bytes |
EMBER_SOURCE_ROUTE_TABLE_SIZE |
100 | 2-255 | ~12 bytes |
EMBER_BINDING_TABLE_SIZE |
32 | 1-127 | ~20 bytes |
EMBER_ADDRESS_TABLE_SIZE |
12 | 1-256 | ~16 bytes |
EMBER_NEIGHBOR_TABLE_SIZE |
26 | 16/26 | ~32 bytes |
EMBER_KEY_TABLE_SIZE |
12 | 1-127 | ~32 bytes |
Network Size Presets¶
| Preset | Devices | Children | Buffers | Routes | Bindings |
|---|---|---|---|---|---|
| Small | <20 | 10 | 75 | 20 | 10 |
| Medium | 20-50 | 20 | 150 | 50 | 20 |
| Large (default) | 50-100 | 32 | 255 | 100 | 32 |
| Very Large | 100-150 | 48 | 255 | 150 | 48 |
Warning: The EFR32MG1B has only 32KB RAM. Current configuration uses ~27KB. Increasing parameters beyond presets may cause instability.
Technical Details¶
Memory Usage¶
| Resource | Used | Available |
|---|---|---|
| Flash | ~200 KB (78%) | 256 KB |
| RAM | ~24 KB (75%) | 32 KB |
| NVM3 | 36 KB | Network data storage |
Optimizations Applied¶
To fit in 256KB flash, the following were removed:
| Component | Savings | Reason |
|---|---|---|
| Debug print | ~12 KB | No debug output needed |
| ZLL / touchlink | ~4 KB | Not used |
| Virtual UART | ~1 KB | Not needed |
| PTI (Packet Trace) | ~2 KB | No debug probe |
Features¶
- RTL8196E Boot Delay: 1-second delay for host UART initialization
- Hardware Flow Control: RTS/CTS required for reliable TCP operation
- NVM3 Storage: 36KB for network credentials and tokens
Troubleshooting¶
No response from NCP¶
- Verify TCP connection:
nc -zv <gateway-ip> 8888 - Check baud rate matches (115200) on firmware side and on the gateway
(
cat /sys/module/rtl8196e_uart_bridge/parameters/baud) - Verify hardware flow control is on:
cat /sys/module/rtl8196e_uart_bridge/parameters/flow_control→1
EZSP communication errors¶
- Ensure Z2M/ZHA is configured for
emberadapter - Check for EZSP version mismatch (this firmware is EZSP v13)
- Re-enable hardware flow control if left off by a failed flash:
echo 1 > /sys/module/rtl8196e_uart_bridge/parameters/flow_control
Device won't pair¶
- Enable permit join in Z2M/ZHA
- Factory reset the device
- Move device closer to coordinator for initial pairing
Files¶
24-NCP-UART-HW/
├── build_ncp.sh # Build script
├── README.md # This file
├── firmware/ # Pre-built firmware files
│ ├── ncp-uart-hw-7.5.1.gbl
└── patches/
├── README.md # Patch documentation
├── apply_config.sh # Configuration script
├── ncp-uart-hw.slcp # Project config
├── main.c # Entry point (1s delay)
└── sl_*.h # Configuration headers
Related Projects¶
25-RCP-UART-HW/- RCP firmware (CPC protocol, for cpcd + zigbeed)26-OT-RCP/- OpenThread RCP (for zigbee-on-host)27-Router/- Autonomous Zigbee router (no host needed)
References¶
License¶
Educational and personal use. Silicon Labs SDK components under their respective licenses.