STM32 Nucleo H723ZG: hardware topology, firmware, CLI, shell commands, radio protocol handling. Use PROACTIVELY whenever discussing hardware, serial ports, USB devices, flashing, DFU, firmware, or any physical connection.
CC1101 (SPI3) ───┐ ┌── USART3 (ST-LINK VCP) → serial shell
433 MHz CCA ├── STM32H723ZG Nucleo-144 ───────┤
nRF52840 (USART2)─┘ FreeRTOS + lwIP ├── Ethernet (LAN8742A) → TCP/UDP :9433
802.15.4 CCX ARM Cortex-M7 @ 550 MHz └── UDP stream → CLI (cli/nucleo.ts)
/dev/tty.usbmodem* (serial shell at 115200 baud)10.0.0.3cd firmware && make flash (OpenOCD via ST-LINK). NEVER use st-flash.reboot shell command or make reset from hostF4:CE:36:70:D6:82:E5:33~/lutron-tools/src/ot-nrf528xx/ (see NCP Firmware section below)firmware/ncp/ot-ncp-ftd-dfu.zip (ready to flash, known working)/dev/cu.usbmodem* or /dev/tty.usbmodem*/nrf sniffer) or RCP mode (/nrf ot)nrfutil nrf5sdk-tools dfu usb-serial| NCP Dongle (on Nucleo) | Sniffer/RCP Dongle (USB) | |
|---|---|---|
| Connected to | STM32 via UART (4 wires soldered) | Mac via USB |
| USB to Mac? | NO (only for DFU recovery) | YES |
| Serial port on Mac | None (goes through Nucleo) | /dev/cu.usbmodem* |
| Firmware | OpenThread NCP | Sniffer or RCP |
| Purpose | Thread mesh member, TX/RX | Passive capture or CLI |
| Red LED = DFU | Must plug USB to Mac to fix | Press reset, flash via USB |
| Port | Device |
|---|---|
/dev/tty.usbmodem* (when only Nucleo connected) | STM32 ST-LINK VCP (shell) |
/dev/cu.usbmodem* (when sniffer dongle plugged in) | nRF52840 sniffer/RCP dongle |
| If TWO usbmodem ports appear | One is ST-LINK, other is sniffer dongle |
The NCP dongle does NOT appear as a serial port on the Mac — it talks to the STM32 over UART, and you interact with it through the Nucleo's shell commands (ot, ccx, spinel).
/dev/tty.usbmodem* is the nRF52840 — it's almost always the STM32 ST-LINKnrfutil to flash the NCP dongle unless its USB is physically plugged into the Macot reset from the shell — it has been removed, but NEVER re-add itfirmware/PROJECT.mdscript/build wrapper in ot-nrf528xx — use the direct cmake invocation10.0.0.3.IMPORTANT: Never use st-flash. Always use make flash (OpenOCD).
cd firmware
# Build (debug)
make build
# Build + flash via OpenOCD
make flash
# Release build
make release
# Reset without reflash
make reset
Build system: CMake with ARM GCC toolchain. Sources listed in firmware/CMakeLists.txt.
OpenOCD config: firmware/openocd.cfg.
Output ELF: firmware/build/lutron-nucleo.elf.
| Task | File | Priority | Purpose |
|---|---|---|---|
cca_task | firmware/src/cca/cca_task.cpp | 3 | CC1101 RX/TX, CCA packet processing, command queue |
ccx_task | firmware/src/ccx/ccx_task.cpp | 3 | nRF52840 Spinel NCP, Thread join, CCX multicast + CoAP unicast |
stream_task | firmware/src/net/stream.cpp | 2 | UDP packet stream to CLI clients (port 9433, binary framing) |
shell_task | firmware/src/shell/shell.cpp | 1 | UART interactive shell |
eth_task | firmware/src/net/eth.c | 2 | lwIP Ethernet, link polling |
| Command | Description |
|---|---|
status | CC1101 state, RSSI, packet counts, heap, uptime |
rx on|off | Enable/disable CCA RX |
tx <hex> | Transmit raw CCA packet (hex bytes) |
cca [cmd] | CCA radio commands |
ccx [cmd] | CCX Thread commands |
ot [cmd] | OpenThread NCP query/control |
spinel [cmd] | Raw Spinel property access |
stream | UDP stream status |
eth | Ethernet PHY debug |
config | Show stored flash settings |
save | Save settings to flash |
reboot | NVIC_SystemReset |
cca ...)| Command | Description |
|---|---|
cca button <dev_id_hex> <name> | Button press (on/off/fav/raise/lower/scene1-4) |
cca level <zone_hex> <target_hex> <%> [fade_qs] | Bridge set-level |
cca broadcast <zone_hex> <%> [fade_qs] | Broadcast level to all devices |
cca pico-level <dev_id_hex> <%> | Pico level control |
cca state <dev_id_hex> <%> | State report |
cca beacon <dev_id_hex> [dur] | Discovery beacon |
cca unpair <zone_hex> <target_hex> | Unpair device |
cca led <zone_hex> <target_hex> <0-3> | LED config |
cca fade <zone_hex> <target_hex> <on_qs> <off_qs> | Fade config |
cca trim <zone_hex> <target_hex> <hi%> <lo%> | Trim config |
cca phase <zone_hex> <target_hex> <byte_hex> | Phase config |
cca save-fav <dev_id_hex> | Save favorite level |
cca vive-level <hub_hex> <zone_hex> <%> [fade] | Vive set-level |
cca vive-raise/lower <hub_hex> <zone_hex> | Vive dim |
cca vive-pair <hub_hex> <zone_hex> [dur] | Vive pairing |
cca pair pico <dev_hex> [type] [dur] | Pico pairing (5btn/2btn/4btn-rl/4btn-scene) |
cca pair bridge <id_hex> <target_hex> [dur] | Bridge pairing |
cca identify <target_hex> | Flash device LED |
cca query <target_hex> | Query device component info |
cca tune ... | CC1101 register/tuning debug |
cca log [on|off] | CCA RX UART log toggle |
ccx ...)| Command | Description |
|---|---|
ccx | Thread status (role, RX/TX counts) |
ccx on <zone> | Send ON to zone (multicast) |
ccx off <zone> | Send OFF to zone |
ccx level <zone> <0-100> | Set level % (multicast) |
ccx scene <id> | Recall scene |
ccx peers | List known Thread peers (RLOC16 → serial) |
ccx promisc [on|off] | Promiscuous mode (raw 802.15.4 frames) |
ccx log [on|off] | CCX RX UART log toggle |
ccx coap preset <addr> <dev_id> <preset_id> <level%> [fade_s] | CoAP preset programming |
ccx coap aha <addr> <k4> <k5> | CoAP AHA LED brightness |
ccx coap get <addr> <uri_path> | CoAP GET |
ccx coap put <addr> <uri_path> <hex_payload> | CoAP PUT |
ccx coap post <addr> <uri_path> <hex_payload> | CoAP POST |
<addr> argument)The CoAP commands accept addresses in three formats:
fd0d:02ef:a82c:0000:abcd:1234:5678:9abcrloc:2C0C → builds full RLOC IPv6 from mesh-local prefixserial:72200096 → looks up RLOC from peer tableot ...)| Command | Description |
|---|---|
ot | Thread state, RLOC16, partition ID |
ot extaddr | Get NCP EUI-64 |
ot eui64 | Get factory EUI-64 |
ot channel | Get/set channel |
ot panid | Get/set PAN ID |
ot masterkey | Get/set network master key |
ot extpanid | Get/set extended PAN ID |
ot rloc16 | Get RLOC16 |
ot leaderdata | Get leader data |
ot netdata | Get network data |
ot addrtable | Get address table |
ot ifconfig [up|down] | Interface up/down |
ot thread [start|stop] | Thread start/stop |
ot reset | DANGEROUS — can brick NCP into DFU bootloader. NEVER USE. |
# Connect to Nucleo
npx tsx cli/nucleo.ts # uses NUCLEO_HOST env var
npx tsx cli/nucleo.ts 10.0.0.3 # direct IP
# Environment
NUCLEO_HOST=10.0.0.3 # default Nucleo IP
The CLI connects over UDP port 9433. Features:
! or use pass to send raw text to STM32 shellrecord / stop for CSV packet capturestatus queries firmware status blob| File | Purpose |
|---|---|
firmware/src/cca/cca_task.cpp | CCA RX/TX task, command queue, packet processing |
firmware/src/cca/cc1101.c | CC1101 SPI driver, register config, RX/TX |
firmware/src/cca/cca_tdma.cpp | TDMA timing, slot tracking |
firmware/src/cca/cca_commands.cpp | CCA command builders (button, level, pair, config) |
firmware/src/cca/cca_pairing.cpp | CCA pairing engine (bridge, pico, vive, hybrid) |
firmware/src/ccx/ccx_task.cpp | CCX task: Thread join, multicast TX, CoAP unicast, peer table |
firmware/src/ccx/coap.c | CoAP message builder (GET/PUT/POST with CBOR payload) |
firmware/src/ccx/ipv6_udp.c | IPv6/UDP packet construction, checksum |
firmware/src/ccx/ccx_msg.c | CCX CBOR message encoder (LEVEL_CONTROL, SCENE_RECALL) |
firmware/src/ccx/ccx_cbor.c | Minimal CBOR encoder |
firmware/src/ccx/smp_serial.c | SMP DFU over Spinel (nRF firmware update) |
firmware/src/net/stream.cpp | UDP stream server (binary framing, multi-client) |
firmware/src/net/eth.c | lwIP Ethernet init, link management |
firmware/src/shell/shell.cpp | UART shell with line editing, history, all commands |
firmware/src/storage/flash_store.cpp | Flash persistence (device IDs, Thread credentials) |
level16 = percent * 0xFEFF / 100byte = seconds * 4 (quarter-seconds)ff03::1 port 9190, CBOR payload[0, { 0: {0: level, 3: fade, 4: delay}, 1: [16, zoneId], 5: seq }][1, { 1: sceneId, 5: seq }]/cg/db/ct/c/AHA, payload [108, {4: <active>, 5: <inactive>}]level16 = percent * 0xFEFF / 100A known-working DFU zip is saved at firmware/ncp/ot-ncp-ftd-dfu.zip.
/dev/tty.usbmodemXXXXnrfutil nrf5sdk-tools dfu usb-serial -pkg firmware/ncp/ot-ncp-ftd-dfu.zip -p /dev/tty.usbmodemXXXXreboot command or power cycle)Source: ~/lutron-tools/src/ot-nrf528xx/
Key config in src/nrf52840/transport-config.h (must be modified from defaults):
#define UART_HWFC_ENABLED 0 // disabled (default is 1)
#define UART_PIN_TX 20 // P0.20 (default is 6 = LED1!)
#define UART_PIN_RX 24 // P0.24 (default is 8 = LED2!)
Build commands (EXACT — do not change):
export PATH="/Applications/ArmGNUToolchain/15.2.rel1/arm-none-eabi/bin:$PATH"
cd ~/lutron-tools/src/ot-nrf528xx
cmake -B build -GNinja \
-DCMAKE_TOOLCHAIN_FILE=src/nrf52840/arm-none-eabi.cmake \
-DCMAKE_BUILD_TYPE=Release \
-DOT_APP_NCP=ON -DOT_APP_CLI=OFF -DOT_APP_RCP=OFF \
-DOT_BOOTLOADER=USB -DNRF_PLATFORM=nrf52840 -DOT_PLATFORM=external \
-DOT_UART_BAUDRATE=460800
ninja -C build ot-ncp-ftd
# Convert + package
arm-none-eabi-objcopy -O ihex build/bin/ot-ncp-ftd /tmp/ot-ncp-ftd-dfu.hex
nrfutil nrf5sdk-tools pkg generate \
--hw-version 52 --sd-req 0x00 \
--application /tmp/ot-ncp-ftd-dfu.hex \
--application-version 7 \
/tmp/ot-ncp-ftd-dfu.zip
CRITICAL build notes:
-DOT_BOOTLOADER=USB — this selects the correct linker script (app at 0x1000, after MBR)-DOT_BOOTLOADER=UART or no bootloader flag = app at 0x0000 = WILL NOT BOOT on PCA10059script/build wrapper does NOT work for our config — use cmake directly| Host | IP | Purpose |
|---|---|---|
| Nucleo | 10.0.0.3 | STM32 (TCP/UDP :9433) |
| RA3 Processor | 10.0.0.1 | LEAP API (:8081), Thread border router |
| Caseta | 10.0.0.2 | LEAP API (:8081) |
| Designer VM | 10.0.0.5 | SSH (user/pass), Designer + SQL Server |
Thread mesh-local prefix: fd0d:2ef:a82c:0::/64
Thread channel: 25, PAN ID: <your-panid>
cd firmware && make flash
npx tsx cli/nucleo.ts
# In CLI: cca level <zone> <target> 50
npx tsx cli/nucleo.ts
# In CLI: ccx level <zone> 75
npx tsx cli/nucleo.ts
# In CLI: ccx coap aha fd0d:02ef:a82c:0000:XXXX:XXXX:XXXX:XXXX 150 20
npx tsx cli/nucleo.ts
# In CLI: ccx
# In CLI: ot
# In CLI: ccx peers
npx tsx cli/nucleo.ts
# In CLI: status
# In CLI: cca tune show
# In CLI: cca tune reg get 0x04