2.1. Build and Run
This document contains instructions on building the images for ESP Thread Border Router and CLI device and forming a Thread network with the devices.
2.1.1. Set up the Repositories
Clone the esp-idf and the esp-thread-br repository.
The current esp-thread-br master branch is compatible with the ESP-IDF commit e6aeb3d.
Refer to the specific tags for each stable release at esp-thread-br releases.
git clone --recursive https://github.com/espressif/esp-idf.git
cd esp-idf
git checkout e6aeb3d36d2fcaf578e4e53308191a8e262dc822
git submodule update --init --depth 1
./install.sh
. ./export.sh
cd ..
git clone --recursive https://github.com/espressif/esp-thread-br.git
If you are new to ESP-IDF, please follow the ESP-IDF getting started guide to set up the IDF development environment and get familiar with the IDF development tools.
2.1.2. Build the RCP Image
Build the esp-idf/examples/openthread/ot_rcp
example. The firmware doesn’t need to be explicitly flashed to a device. It will be included in the Border Router firmware and flashed to the ESP32-H2 chip upon first boot.
cd $IDF_PATH/examples/openthread/ot_rcp
Select the ESP32-H2 as the RCP.
idf.py set-target esp32h2
The default communication interface on the ESP Thread Border Router board is UART0 with 460800 baudrate, which can be configured in esp_ot_config.h.
idf.py menuconfig
idf.py build
2.1.3. Configure ESP Thread Border Router
Go to the basic_thread_border_router
example folder.
cd esp-thread-br/examples/basic_thread_border_router
The default configuration works as is on ESP Thread Border Router board, the default SoC target is ESP32-S3.
To run the example on other SoCs, please configure the SoC target using command:
idf.py set-target <chip_name>
For any other customized settings, you can configure the project in menuconfig.
idf.py menuconfig
Note
LWIP_IPV6_NUM_ADDRESSES configuration is fixed in the border router library, it was changed from 8 to 12 since IDF v5.3.1 release. Please update this configuration based on the following table:
IDF Versions
LWIP_IPV6_NUM_ADDRESSES
v5.1.4 and earlier
8
v5.2.2 and earlier
8
v5.3.0
8
v5.3.1 and later
12
2.1.3.1. Wi-Fi based Thread Border Router
By default, it is configured as Wi-Fi based Thread Border Router.
The auto start mode is disabled by default, if you want the device connects to the configured Wi-Fi and form Thread network automatically, and then act as the border router, you need to enable the menuconfig ESP Thread Border Router Example -> Enable the automatic start mode in Thread Border
.
When automatic start mode is enabled, the Thread dataset, Wi-Fi SSID and password must be set in menuconfig. The corresponding options are Component config -> OpenThread -> Thread Operational Dataset
, Example Connection Configuration -> WiFi SSID
and Example Connection Configuration -> WiFi Password
.
Note that in this mode, the device will first attempt to use the Wi-Fi SSID and password stored in NVS. If no Wi-Fi information is stored, it will then use the EXAMPLE_WIFI_SSID and EXAMPLE_WIFI_PASSWORD from menuconfig.
Note
The following configuration options are all optional, jump to 2.1.4. Build and Run the Thread Border Router if you don’t need any customized settings.
2.1.3.2. Ethernet based Thread Border Router
The border router can also be configured to connect to an Ethernet network. In this case, the daughter board ESP Thread Border Router/Zigbee Gateway Sub-Ethernet
is required to extend the Ethernet interface.
The following options need to be set:
Enable
EXAMPLE_CONNECT_ETHERNET
Disable
EXAMPLE_CONNECT_WIFI
The configurations of EXAMPLE_CONNECT_ETHERNET
as following:
Parameter
Value
Note
Type
W5500 Module
Mandatory
Stack Size
2048
Customized
SPI Host
SPI2
Mandatory
SPI SCLK
GPIO21
Mandatory
SPI MOSI
GPIO45
Mandatory
SPI MISO
GPIO38
Mandatory
SPI CS
GPIO41
Mandatory
SPI Interrupt
GPIO39
Mandatory
SPI SPEED
36 MHz
Customized
PHY Reset
GPIO40
Mandatory
PHY Address
1
Mandatory
The configuration result would look like this.
Espressif IoT Development Framework Configuration
[ ] connect using WiFi interface
[*] connect using Ethernet interface
(2048) emac_rx task stack size
Ethernet Type (W5500 Module) --->
(2) SPI Host Number
(21) SPI SCLK GPIO number
(45) SPI MOSI GPIO number
(38) SPI MISO GPIO number
(41) SPI CS GPIO number
(36) SPI clock speed (MHz)
(39) Interrupt GPIO number
(40) PHY Reset GPIO number
(1) PHY Address
[*] Obtain IPv6 address
Preferred IPv6 Type (Local Link Address) --->
2.1.3.3. Thread Network Parameters
The Thread network parameters could be pre-configured with OPENTHREAD_NETWORK_xx
options.
2.1.3.4. Communication Interface
The default communication interface between host SoC and RCP is UART.
In order to use the SPI interface instead, the OPENTHREAD_RCP_SPI
and OPENTHREAD_RADIO_SPINEL_SPI
options should be enabled in ot_rcp
and basic_thread_border_router
example configurations, respectively. And set corresponding GPIO numbers in esp_ot_config.h.
2.1.3.5. RF External Coexistence
The SDK incorporates an external coexistence feature that improves transmission performance when there is RF signal interference between Wi-Fi (ESP32-S3) and 802.15.4 (ESP32-H2).
Please refer to external_coexistence_design_en.pdf for the external coexistence design. In addition to the 3-wire mode (use request signal, grant signal and priority signal), a 4th wire tx signal is used to indicate whether the Wi-Fi SoC is under transmission state or not, it helps to enable the scenario that 802.15.4 could transmit when Wi-Fi is receiving.
Note
The external coexistence feature only helps when Wi-Fi and 802.15.4 operate on close channel frequency, in which case the interference is significant. Otherwise, the feature is unnecessary.
To enable the external coexistence feature, check the EXTERNAL_COEX_ENABLE
option in both basic_thread_border_router
and ot_rcp
examples.
The default pin configurations have been set for ESP Thread Border Router Board. The users can change the configurations through menuconfig ESP Thread Border Router Example → External coexist wire type and pin config
if needed.
2.1.4. Build and Run the Thread Border Router
Build and Flash the example to the host SoC.
idf.py -p ${PORT_TO_BR} flash monitor
The following result will be shown in your terminal:
Wi-Fi Border Router:
I (555) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (719) example_connect: Start example_connect.
I (739) wifi:wifi firmware version: 4d93d42
I (899) wifi:mode : sta (84:f7:03:c0:d1:e8)
I (899) wifi:enable tsf
I (899) example_connect: Connecting to xxxx...
I (899) example_connect: Waiting for IP(s)
I (5719) example_connect: Got IPv6 event: Interface "example_netif_sta" address: fe80:0000:0000:0000:86f7:03ff:fec0:d1e8, type: ESP_IP6_ADDR_IS_LINK_LOCAL
I (5719) esp_netif_handlers: example_netif_sta ip: 192.168.1.102, mask: 255.255.255.0, gw: 192.168.1.1
I (5729) example_connect: Got IPv4 event: Interface "example_netif_sta" address: 192.168.1.102
I (5739) example_common: Connected to example_netif_sta
I (5749) example_common: - IPv4 address: 192.168.1.102,
I (5749) example_common: - IPv6 address: fe80:0000:0000:0000:86f7:03ff:fec0:d1e8, type: ESP_IP6_)
I(5779) OPENTHREAD:[I] Platform------: RCP reset: RESET_POWER_ON
I(5809) OPENTHREAD:[N] Platform------: RCP API Version: 6
I (5919) esp_ot_br: RCP Version in storage: openthread-esp32/8282dca796-e64ba13fa; esp32h2; 2022-10-10 06:01:35 UTC
I (5919) esp_ot_br: Running RCP Version: openthread-esp32/8282dca796-e64ba13fa; esp32h2; 2022-10-10 06:01:35 UTC
I (5929) OPENTHREAD: OpenThread attached to netif
I(5939) OPENTHREAD:[I] SrpServer-----: Selected port 53535
I(5949) OPENTHREAD:[I] NetDataPublshr: Publishing DNS/SRP service unicast (ml-eid, port:53535)
Ethernet Border Router:
I (793) cpu_start: Starting scheduler on PRO CPU.
I (793) cpu_start: Starting scheduler on APP CPU.
I (904) system_api: Base MAC address is not set
I (904) system_api: read default base MAC address from EFUSE
I (924) esp_eth.netif.netif_glue: 70:b8:f6:12:c5:5b
I (924) esp_eth.netif.netif_glue: ethernet attached to netif
I (2524) ethernet_connect: Waiting for IP(s).
I (2524) ethernet_connect: Ethernet Link Up
I (3884) ethernet_connect: Got IPv6 event: Interface "example_netif_eth" address: fe80:0000:0000:0000:72b8:f6ff:fe12:c55b, type: ESP_IP6_ADDR_IS_LINK_LOCAL
I (3884) esp_netif_handlers: example_netif_eth ip: 192.168.8.148, mask: 255.255.255.0, gw: 192.168.8.1
I (3894) ethernet_connect: Got IPv4 event: Interface "example_netif_eth" address: 192.168.8.148
I (3904) example_common: Connected to example_netif_eth
I (3904) example_common: - IPv4 address: 192.168.8.148,
I (3914) example_common: - IPv6 address: fe80:0000:0000:0000:72b8:f6fI(3944) OPENTHREAD:[I] Platform------: RCP reset: RESET_POWER_ON
I(3974) OPENTHREAD:[N] Platform------: RCP API Version: 6
I(4144) OPENTHREAD:[I] Settings------: Read NetworkInfo {rloc:0x4400, extaddr:129f848762f1c578, role:leader, mode:0x0f, version:4, keyseq:0x0, ...
I(4154) OPENTHREAD:[I] Settings------: ... pid:0x18954426, mlecntr:0x7da7, maccntr:0x7d1c, mliid:2874d9fa90dc8093}
I (4194) OPENTHREAD: OpenThread attached to netif
2.1.4.1. Connect the Wi-Fi and Form the Thread Network
If enable OPENTHREAD_BR_AUTO_START
option, just skip this step.
If disable OPENTHREAD_BR_AUTO_START
option, you need to setup the network manually. The following CLI commands can be used to connect Wi-Fi and form a Thread network:
wifi connect -s <ssid> -p <psk>
dataset init new
dataset commit active
ifconfig up
thread start
The BR device will connect to the Wi-Fi and then form a Thread network.
> wifi connect -s mywifi -p espressif
ssid: mywifi
psk: espressif
I (5241) pp: pp rom version: e7ae62f
I (5241) net80211: net80211 rom version: e7ae62f
I (5251) wifi:wifi driver task: 3fcbe1a0, prio:23, stack:6144, core=0
I (5251) wifi:wifi firmware version: 0016c4d
I (5251) wifi:wifi certification version: v7.0
I (5251) wifi:config NVS flash: enabled
I (5251) wifi:config nano formating: enabled
I (5251) wifi:Init data frame dynamic rx buffer num: 32
I (5251) wifi:Init static rx mgmt buffer num: 5
I (5251) wifi:Init management short buffer num: 32
I (5251) wifi:Init dynamic tx buffer num: 32
I (5251) wifi:Init static tx FG buffer num: 2
I (5251) wifi:Init static rx buffer size: 1600
I (5251) wifi:Init static rx buffer num: 10
I (5251) wifi:Init dynamic rx buffer num: 32
I (5251) wifi_init: rx ba win: 6
I (5251) wifi_init: tcpip mbox: 32
I (5251) wifi_init: udp mbox: 6
I (5251) wifi_init: tcp mbox: 6
I (5251) wifi_init: tcp tx win: 5760
I (5251) wifi_init: tcp rx win: 5760
I (5251) wifi_init: tcp mss: 1440
I (5251) wifi_init: WiFi IRAM OP enabled
I (5251) wifi_init: WiFi RX IRAM OP enabled
I (5261) wifi:Set ps type: 0, coexist: 0
I (5261) phy_init: phy_version 640,cd64a1a,Jan 24 2024,17:28:12
I (5351) wifi:mode : null
I (5351) wifi:mode : sta (48:27:e2:14:4d:3c)
I (5351) wifi:enable tsf
I (6571) wifi:new:<11,2>, old:<1,1>, ap:<255,255>, sta:<11,2>, prof:1
I (7051) wifi:state: init -> auth (b0)
I (7051) wifi:state: auth -> assoc (0)
I (7071) wifi:state: assoc -> run (10)
I (7351) wifi:connected with mywifi, aid = 2, channel 11, 40D, bssid = 94:d9:b3:1d:d4:37
I (7351) wifi:security: WPA2-PSK, phy: bgn, rssi: -26
I (7351) wifi:pm start, type: 0
I (7361) wifi:dp: 1, bi: 102400, li: 3, scale listen interval from 307200 us to 307200 us
I (7361) wifi:set rx beacon pti, rx_bcn_pti: 0, bcn_timeout: 25000, mt_pti: 0, mt_time: 10000
I (7411) wifi:<ba-add>idx:0 (ifx:0, 94:d9:b3:1d:d4:37), tid:0, ssn:3, winSize:64
I (7441) wifi:AP's beacon interval = 102400 us, DTIM period = 1
I (8361) esp_netif_handlers: sta ip: 192.168.1.100, mask: 255.255.255.0, gw: 192.168.1.1
I (8501) ot_ext_cli: Got IPv6 event: Interface "sta" address: fe80:0000:0000:0000:4a27:e2ff:fe14:4d3c
I(8501) OPENTHREAD:[N] RoutingManager: No valid /48 BR ULA prefix found in settings, generating new one
I(8511) OPENTHREAD:[N] RoutingManager: BR ULA prefix: fd8f:e9a2:bfcc::/48 (generated)
I(8511) OPENTHREAD:[N] RoutingManager: Local on-link prefix: fdde:ad00:beef:cafe::/64
wifi sta is connected successfully
Done
> dataset init new
Done
> dataset commit active
Done I (12401) OPENTHREAD: NAT64 ready
> ifconfig up
I (15451) OPENTHREAD: Platform UDP bound to port 49153
Done
I (15451) OT_STATE: netif up
> thread start
I(18201) OPENTHREAD:[N] Mle-----------: Role disabled -> detached
Done
> I(18521) OPENTHREAD:[N] Mle-----------: Attach attempt 1, AnyPartition reattaching with Active Dataset
I(25141) OPENTHREAD:[N] RouterTable---: Allocate router id 11
I(25141) OPENTHREAD:[N] Mle-----------: RLOC16 fffe -> 6c00
I(25151) OPENTHREAD:[N] Mle-----------: Role detached -> leader
I(25151) OPENTHREAD:[N] Mle-----------: Partition ID 0x82de096
I (25161) OPENTHREAD: Platform UDP bound to port 49154
2.1.5. Build and Run the Thread CLI Device
Build the esp-idf/examples/openthread/ot_cli
example and flash the firmware to another ESP32-H2 devkit.
cd $IDF_PATH/examples/openthread/ot_cli
idf.py -p ${PORT_TO_ESP32_H2} flash monitor
2.1.6. Attach the CLI Device to the Thread Network
First acquire the Thread network dataset on the Border Router:
dataset active -x
The network data will be printed on the Border Router:
> dataset active -x
0e080000000000010000000300001335060004001fffe00208dead00beef00cafe0708fdfaeb6813db063b0510112233445566778899aabbccddeeff00030f4f70656e5468726561642d34396436010212340410104810e2315100afd6bc9215a6bfac530c0402a0f7f8
Done
Commit the dataset on the CLI device with the acquired dataset:
dataset set active 0e080000000000010000000300001335060004001fffe00208dead00beef00cafe0708fdfaeb6813db063b0510112233445566778899aabbccddeeff00030f4f70656e5468726561642d34396436010212340410104810e2315100afd6bc9215a6bfac530c0402a0f7f8
Set the network data active on the CLI device:
dataset commit active
Set up the network interface on the CLI device:
ifconfig up
Start the thread network on the CLI device:
thread start
The CLI device will become a child or a router in the Thread network:
> dataset set active 0e080000000000010000000300001335060004001fffe00208dead00beef00cafe0708fdfaeb6813db063b0510112233445566778899aabbccddeeff00030f4f70656e5468726561642d34396436010212340410104810e2315100afd6bc9215a6bfac530c0402a0f7f8
Done
> dataset commit active
Done
> ifconfig up
Done
I (1665530) OPENTHREAD: netif up
> thread start
I(1667730) OPENTHREAD:[N] Mle-----------: Role disabled -> detached
Done
> I(1669240) OPENTHREAD:[N] Mle-----------: RLOC16 5800 -> fffe
I(1669590) OPENTHREAD:[N] Mle-----------: Attempt to attach - attempt 1, AnyPartition
I(1670590) OPENTHREAD:[N] Mle-----------: RLOC16 fffe -> 6c01
I(1670590) OPENTHREAD:[N] Mle-----------: Role detached -> child