Thread
On the wireless Core, core_thread puts several boards on one Thread mesh: they find each other, route for each other, and exchange UDP messages, with no phone, hub or gateway in between.
Overview
medium or higher. The C API is Tier 1; Studio has no Thread blocks yet, so a Studio project uses it in C mode.Each board is a full Thread device: it attaches as a child, becomes a router when the mesh needs one, and takes over as leader if the leader disappears. With Thread enabled in config.json it starts on boot, and core_delay_ms() and core_watchdog_feed() keep it running, so an ordinary loop needs no Thread calls at all. A loop that neither waits nor feeds the watchdog calls core_thread_process() itself.
#include "core.h"
#include "core_thread.h"
int main(void) {
core_init(); // Thread starts here
while (1) {
if (core_thread_role() >= CORE_THREAD_CHILD) {
// attached: the mesh is reachable
}
core_delay_ms(10); // keeps Thread running
}
}The network in config.json
The network is fixed at build time. Every board built with the same thread block joins the same mesh:
"thread": {
"enabled": true,
"channel": 15,
"panid": "0x1234",
"network_name": "greenhouse",
"network_key": "<32 hex digits>",
"ext_panid": "<16 hex digits>"
}Every key but enabled is optional. The channel is 11 to 26, the PAN ID 0x0000 to 0xFFFE, the name up to 16 characters; role can only be "ftd" today, and mesh_local_prefix takes an IPv6 /64. Absent keys take the SDK’s development defaults, including a network key everyone knows, so set a key of your own. Studio does that for you: turning Thread on in a Core.ST.W5’s settings generates a key and extended PAN ID for the project, and Copy network / Paste network there put boards from different projects on one mesh.
Sending and receiving
Open a UDP port with a receive callback, then send to one address or to every node. The callback gets one packet: its data and length, and the sender’s address and port. It runs from the SDK’s Thread servicing, never from an interrupt, and the packet is valid only during the call, so copy what you keep:
static void on_rx(const core_thread_udp_packet_t *pkt, void *ctx) {
(void)ctx;
core_led_toggle(); // pkt->data, pkt->len: the payload
core_thread_udp_send(pkt->src, pkt->src_port, "ack", 3); // reply to the sender
}
core_thread_udp_open(1234, on_rx, NULL);
// in the loop, once attached:
core_thread_udp_broadcast(1234, "hello", 5); // every node (ff03::1)For anything the wrapper leaves out (CoAP, SRP, the full diagnostics), core_thread_instance() returns the OpenThread instance for the OpenThread C API.
Limits
This is the first milestone: a development network. There is no commissioning, so anyone holding the config (or its bytes) can join the mesh and read its traffic. Every board is router-capable with its receiver on: no sleepy battery end devices. There is no border router, so the mesh does not reach the internet.
Cross-architecture support
Thread is hardware-verified on the wireless Core; the other ST Cores have no 802.15.4 radio.
See the implementation status for the full matrix.
Known gaps
What the SDK itself lists as missing here, straight from the header:
With "ble_provisioning" any phone that connects can move the node to another Thread network: there is no pairing or authorization yet. The network key cannot be read back. core_thread_prov_allow_write() is the hook for a gate; pairing-protected writes are planned.
Thread is C-only (Tier 1) for now, like BLE: no palette blocks, no twin. The role and UDP callbacks need the host-call ABI to grow first.
Every node built from the same config.json joins the same network with the same network key, unless it is moved at run time (core_thread_set_dataset(), or the open BLE provisioning service); there is no joiner / commissioner yet. Development only.
With BLE in the same image, OpenThread is rebuilt without the commissioner, joiner, CoAP secure (DTLS), SRP and DNS clients, TCP, ping, mesh and link-metrics diagnostics, with 64 message buffers instead of 128, so both stacks fit in RAM with room for an application. A full router (FTD) all the same; Thread-only builds keep ST's complete library.
The device is always a full Thread device with its receiver on; battery end devices that sleep between polls are deferred.
The prebuilt mbedTLS calls the ST HAL for the PKA; the SDK answers those calls with an error, so commissioning, SRP client keys and CoAP secure fail. AES (MAC and MLE security) runs on the AES peripheral.
Present in the OpenThread library and callable through core_thread_instance() and the OpenThread headers, but not wrapped.
From the @studio unsupported notes in core_thread.h — tiles@77fd3f3.
API reference
int core_thread_start(void);void core_thread_process(void);core_thread_role_t core_thread_role(void);void core_thread_on_role_change(core_thread_role_cb cb, void * ctx);int core_thread_udp_open(uint16_t port, core_thread_udp_rx_cb rx_cb, void * ctx);int core_thread_udp_send(const uint8_t addr6[16], uint16_t port, const void * buf, uint16_t len);int core_thread_udp_broadcast(uint16_t port, const void * buf, uint16_t len);uint16_t core_thread_rloc16(void);void core_thread_ext_addr(uint8_t out[8]);uint32_t core_thread_partition_id(void);uint8_t core_thread_neighbor_count(void);int8_t core_thread_parent_rssi(void);int core_thread_last_error(void);void * core_thread_instance(void);int core_thread_get_network(core_thread_dataset_t * out);int core_thread_set_enabled(int on);int core_thread_set_dataset(const core_thread_dataset_t * ds);int core_thread_factory_reset(void);int core_thread_is_provisioned(void);int core_thread_prov_allow_write(void);Generated from core_thread.h — tiles@77fd3f3.

