harp.core.esp32 is an ESP-IDF component that implements the Harp binary protocol on Espressif targets. It provides the standard Harp core registers, application-register dispatch, timestamping and synchronization, persistent core configuration, and optional outbound TCP transport.
The component supports two host transports:
- native USB CDC on ESP32-S2 and ESP32-S3;
- UART on all supported ESP32 targets.
TCP can run alongside either transport. Replies are returned through the transport that supplied the request; unsolicited events are sent to every connected transport.
| Item | Current value |
|---|---|
| Component version | 0.1.0 |
| Harp protocol version | 1.13.0 |
| Framework | ESP-IDF >= 6.0 |
| Language | C++ with C-compatible application callbacks |
| USB dependency | espressif/esp_tinyusb >= 2.0.0 on ESP32-S2/S3 |
| Application register start | 36 |
This is an early component release. Review known limitations before deploying it in unattended experiments.
- Harp core register map and message dispatch.
- C-style application callbacks through
HarpCApp. - USB CDC or high-speed UART host communication.
- Wi-Fi station mode and an outbound, reconnecting TCP client.
- Separate receive buffers for serial and TCP traffic.
- NVS persistence for writable core and network registers marked non-volatile.
- Harp clock receiver, repeater, and generator modes.
- FreeRTOS-based operation with application and protocol work assignable to different cores.
- Hardware-derived device identity from the ESP32 base MAC, with an application override.
- Optional non-blocking Bluetooth Classic SPP logging for the original ESP32.
| Path | Purpose |
|---|---|
include/ |
Public component headers |
src/ |
Core, synchronization, networking, NVS, and transport implementations |
examples/esp32/ |
UART example for the original ESP32 |
examples/esp32s3/ |
native USB example with synchronization generation |
examples/esp32-bt-log/ |
UART Harp transport plus Bluetooth SPP diagnostics |
docs/ |
Architecture, register, integration, networking, and timing documentation |
Reference the repository root from main/idf_component.yml:
dependencies:
harp_core:
git: https://github.com/barbaLab/harp.core.esp32.gitFor local development, use a relative path instead of a machine-specific absolute path:
dependencies:
harp_core:
path: ../../harp.core.esp32The repository itself is the component root; do not set the dependency path to src.
Select the host backend with idf.py menuconfig under Harp Core transport. Native USB is the default on ESP32-S2/S3; UART is the default on other targets. UART defaults to port 0, TX GPIO 1, RX GPIO 3, and 921600 baud.
An application supplies a register table and the callbacks declared by HarpCApp. A typical startup sequence is:
- initialize application hardware and reset its register values;
- construct and configure the
HarpCoresingleton; - optionally configure synchronization and identity;
- call
init(); - call
run()frequently from a dedicated task.
run() polls synchronization state, updates the core state and heartbeat, processes TCP input, then processes USB or UART input. See Integrating an application for the callback contract and a task template.
flowchart TD
H["Host USB or UART"] --> C["HarpCore dispatcher"]
T["Outbound TCP connection"] --> C
C --> R["Core register handlers"]
C --> A["Application callbacks"]
R --> S["Reply to request source"]
A --> S
E["Heartbeat or app event"] --> B["Broadcast to connected transports"]
The TCP endpoint is configured by Harp registers 32–35. The device acts as a TCP client: it connects to the configured host rather than listening for incoming connections. TCP is raw Harp framing without encryption or authentication; use it only on a trusted network or behind an appropriate secure tunnel. Ideally, for both security and perfomance/congestion reasons, a behaviour setup using harp-TCP devices should have its own private network.
For detailed register specification check docs/core-network-register-extension.md.
The synchronization module supports receiver, repeater, and generator roles. A Harp clock frame is six UART bytes at 100 kbit/s: two sync bytes followed by a little-endian seconds counter. RMT and GPIO timing are used to estimate the second boundary and esp_timer supplies the local microsecond time base. Hardware timestamp output remains available to application code.
Pin selection, electrical compatibility, and clock role are board responsibilities. See Synchronization.
Application registers begin at address 36. Addresses 32–35 are reserved by this core for networking and must not be reused by applications.
| Example | Target and purpose |
|---|---|
examples/esp32 |
Original ESP32, Harp over UART0, optional receiver synchronization on UART2/GPIO2 |
examples/esp32s3 |
ESP32-S3, Harp over native USB, synchronization on UART1 GPIO18/17, generator enabled by default |
examples/esp32-bt-log |
Original ESP32, Harp over UART and diagnostic logging over Bluetooth SPP |
The example dependency manifests currently contain local development paths. Replace those paths with the Git dependency above or with a path valid in your checkout before building.
- Inbound message checksum and header validation are not yet enforced by the dispatcher. Do not treat malformed-input recovery as production-ready.
- NVS persistence currently covers core and network registers, not application registers.
DFUreset requests currently perform a normal ESP restart; no firmware-update transport is entered.- Native USB is available only on chips with USB OTG support. The original ESP32 uses UART.
- Network credentials are masked on Harp reads and removed from the live register buffer after application, but ordinary NVS storage is not encrypted unless the containing project enables NVS encryption.