diff --git a/docs/adr/0009-wifi-companion-boards.md b/docs/adr/0009-wifi-companion-boards.md index 0641f46..648b337 100644 --- a/docs/adr/0009-wifi-companion-boards.md +++ b/docs/adr/0009-wifi-companion-boards.md @@ -12,8 +12,9 @@ declare it (Heltec V3 and Wireless Tracker at 140/130 contacts, both C6 boards a also gets bounded WiFi buffers and a measured 72 KB heap (Kconfig, `HEAP_MEM_POOL_IGNORE_MIN`). Tracker V2, C3 and the classic ESP32 boards do not fit WiFi + BLE (DRAM). Upstream's `set/get wifi.ssid|pwd|enabled`, `set wifi.clear`, `get wifi.status|ip`; applied on reboot; TCP port -`CONFIG_ZEPHCORE_TCP_PORT` (5000, as upstream). The Zephyr ESP32 WiFi stack needs patches `0017`/`0018` and -hal_espressif `0001` to survive traffic bursts (§13). +`CONFIG_ZEPHCORE_TCP_PORT` (5000, as upstream). The Zephyr ESP32 WiFi stack needed patches `0017`/`0018` and +hal_espressif `0001` to survive traffic bursts; since the 2026-09-26 Zephyr bump only `0017` remains (the other +two fixes are upstream, `67151dfaf73` and hal_espressif `af97fb02df`) (§13). ## Decision @@ -21,4 +22,4 @@ WiFi + BLE on every board that can hold both; fewer contacts on the no-PSRAM one ## Consequences -Watch patches `0017`/`0018` and hal_espressif `0001` on every west update. +Watch patch `0017` on every west update: upstream's RX path still blocks for 100 ms. diff --git a/zephcore/adapters/ble/ble_gatt_layout.cpp b/zephcore/adapters/ble/ble_gatt_layout.cpp index a02f770..d3f6127 100644 --- a/zephcore/adapters/ble/ble_gatt_layout.cpp +++ b/zephcore/adapters/ble/ble_gatt_layout.cpp @@ -39,12 +39,26 @@ static const struct bt_gatt_attr *gatt_sc_value_attr; static struct bt_gatt_indicate_params gatt_sc_ind_params; static uint16_t gatt_sc_ind_range[2]; +/* Persisted key, so formatted here rather than with bt_addr_le_to_str(): that + * is a display format and changed upstream ("AA:..:FF (public)" became + * "P:AA:..:FF"), which orphaned every stored key and sent every bonded phone a + * needless Service Changed. This keeps the original format byte for byte. */ static void gatt_peer_settings_key(char *key, size_t key_len, const bt_addr_le_t *addr) { - char addr_str[BT_ADDR_LE_STR_LEN]; + static const char *const type_str[] = { "public", "random", "public-id", "random-id" }; + char type_hex[5]; + const char *type; - bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); - snprintk(key, key_len, "ble/gatt_peer/%s", addr_str); + if (addr->type < ARRAY_SIZE(type_str)) { + type = type_str[addr->type]; + } else { + snprintk(type_hex, sizeof(type_hex), "0x%02x", addr->type); + type = type_hex; + } + + snprintk(key, key_len, "ble/gatt_peer/%02X:%02X:%02X:%02X:%02X:%02X (%s)", + addr->a.val[5], addr->a.val[4], addr->a.val[3], + addr->a.val[2], addr->a.val[1], addr->a.val[0], type); } static int gatt_peer_layout_load(const bt_addr_le_t *addr, uint8_t *ver_out) diff --git a/zephcore/patches/modules/hal_espressif/0001-heap-adapter-psram-realloc.patch b/zephcore/patches/modules/hal_espressif/0001-heap-adapter-psram-realloc.patch deleted file mode 100644 index f304b6c..0000000 --- a/zephcore/patches/modules/hal_espressif/0001-heap-adapter-psram-realloc.patch +++ /dev/null @@ -1,41 +0,0 @@ -Backport of hal_espressif af97fb02df (upstream main, 2026-09-23): -"zephyr: port: fix realloc in the psram heap adapters". - -With the Wi-Fi or BT heap in PSRAM, os_wpa_realloc_func() and -esp_bt_realloc_func() freed the old block and returned a new, uninitialized -one: wpabuf_resize() lost the buffer contents, and on allocation failure the -old block was already freed while the caller still owned it. - -ZephCore: drop this patch at the first west update whose hal_espressif pin -contains af97fb02df (Zephyr main still pins 064142dfcd, 2026-09-18). - -diff --git a/zephyr/port/include/esp_heap_adapter.h b/zephyr/port/include/esp_heap_adapter.h -index be7e293da5..5015e50d52 100644 ---- a/zephyr/port/include/esp_heap_adapter.h -+++ b/zephyr/port/include/esp_heap_adapter.h -@@ -62,10 +62,10 @@ static inline void* os_wpa_malloc_func(size_t _size) - - static inline void* os_wpa_realloc_func(void *_ptr, size_t _size) - { -- if (_ptr) { -- esp_wifi_free_func(_ptr); -+ if (esp_ptr_in_dram(_ptr)) { -+ return k_realloc(_ptr, _size); - } -- return os_wpa_malloc_func(_size); -+ return shared_multi_heap_realloc(SMH_REG_ATTR_EXTERNAL, _ptr, _size); - } - - static inline void* os_wpa_calloc_func(size_t _nmemb, size_t _size) -@@ -121,10 +121,7 @@ static inline void* esp_bt_calloc_func(size_t _nmemb, size_t _size) - - static inline void* esp_bt_realloc_func(void *_ptr, size_t _size) - { -- if (_ptr) { -- shared_multi_heap_free(_ptr); -- } -- return esp_bt_malloc_func(_size); -+ return shared_multi_heap_realloc(SMH_REG_ATTR_EXTERNAL, _ptr, _size); - } - - static inline void esp_bt_free_func(void *_mem) diff --git a/zephcore/patches/zephyr/0001-lora-lr11xx-lr20xx-build.patch b/zephcore/patches/zephyr/0001-lora-lr11xx-lr20xx-build.patch index 3d5065e..b7f19b9 100644 --- a/zephcore/patches/zephyr/0001-lora-lr11xx-lr20xx-build.patch +++ b/zephcore/patches/zephyr/0001-lora-lr11xx-lr20xx-build.patch @@ -14,6 +14,14 @@ zephcore_apply_patches() reset these two files, and 0003 re-supplied the lines 0001 and 0002 had just added. Now that each file has exactly one owner, both patches apply first time. + +Also adds DT_HAS_SEMTECH_LR1110_ENABLED / DT_HAS_SEMTECH_LR2021_ENABLED to the +LORA_MODULE_BACKEND_NATIVE dependency. Upstream 1263266b615 (2026-09-23) made +that backend depend on the radios its in-tree drivers cover (SX1261/2, STM32WL, +LR1121); zephcore_common.conf selects it on every board, so on an LR1110- or +LR2021-only board the choice silently fell through to loramac-node (a Kconfig +warning, no build error). Our two drivers are native-backend drivers. + diff --git a/drivers/lora/CMakeLists.txt b/drivers/lora/CMakeLists.txt index fecfe8ea8bb..0fbeadcc404 100644 --- a/drivers/lora/CMakeLists.txt @@ -32,7 +40,7 @@ index fecfe8ea8bb..0fbeadcc404 100644 add_subdirectory_ifdef(CONFIG_LORA_MODULE_BACKEND_LORAMAC_NODE loramac-node) add_subdirectory_ifdef(CONFIG_LORA_MODULE_BACKEND_LORA_BASICS_MODEM lora-basics-modem) diff --git a/drivers/lora/Kconfig b/drivers/lora/Kconfig -index e31c08c1371..d53979fabd1 100644 +index 67346bc1142..eff530d806a 100644 --- a/drivers/lora/Kconfig +++ b/drivers/lora/Kconfig @@ -5,6 +5,7 @@ @@ -43,7 +51,19 @@ index e31c08c1371..d53979fabd1 100644 menuconfig LORA bool "LoRa drivers" -@@ -79,6 +80,8 @@ config LORA_INIT_PRIORITY +@@ -36,8 +37,10 @@ config LORA_MODULE_BACKEND_LORA_BASICS_MODEM + + config LORA_MODULE_BACKEND_NATIVE + bool "Native Zephyr backend" ++ # ZephCore patch: lr11xx/ and lr20xx/ are native-backend drivers too. + depends on DT_HAS_SEMTECH_SX1261_ENABLED || DT_HAS_SEMTECH_SX1262_ENABLED \ +- || DT_HAS_ST_STM32WL_SUBGHZ_RADIO_ENABLED || DT_HAS_SEMTECH_LR1121_ENABLED ++ || DT_HAS_ST_STM32WL_SUBGHZ_RADIO_ENABLED || DT_HAS_SEMTECH_LR1121_ENABLED \ ++ || DT_HAS_SEMTECH_LR1110_ENABLED || DT_HAS_SEMTECH_LR2021_ENABLED + help + Use Zephyr's built-in LoRa drivers without external modules. + Currently supports SX1261/SX1262, the STM32WL sub-GHz radio and LR1121. +@@ -81,6 +84,8 @@ config LORA_INIT_PRIORITY rsource "Kconfig.sx12xx" rsource "Kconfig.rylrxxx" diff --git a/zephcore/patches/zephyr/0018-shared-multi-heap-lock.patch b/zephcore/patches/zephyr/0018-shared-multi-heap-lock.patch deleted file mode 100644 index 53ebd79..0000000 --- a/zephcore/patches/zephyr/0018-shared-multi-heap-lock.patch +++ /dev/null @@ -1,108 +0,0 @@ -shared_multi_heap: lock the pool. - -sys_heap is not internally synchronized and shared_multi_heap added no lock, -although it is a system-wide pool for drivers and applications. On ESP32 with -CONFIG_ESP_WIFI_HEAP_SPIRAM (every PSRAM Wi-Fi companion) the Wi-Fi adapter -(hal_espressif esp_heap_adapter.h) allocates and frees from it on several -threads at once; under Wi-Fi traffic that corrupted the heap ("heap -corruption (free list linkage)" / "double free?") and panicked the Wi-Fi -task. A spinlock around every pool operation, as k_heap does around the same -allocator. - -Found and bench-verified 2026-09-24 on a XIAO ESP32-S3 companion -(devdocs/lld/08-connectivity.md, "Wi-Fi flood wedge"). Not fixed on Zephyr -main as of 15723416fdd (2026-09-24). - -diff --git a/lib/heap/shared_multi_heap.c b/lib/heap/shared_multi_heap.c -index c6a4fe50d58..6af29745d5c 100644 ---- a/lib/heap/shared_multi_heap.c -+++ b/lib/heap/shared_multi_heap.c -@@ -13,6 +13,18 @@ - - static struct sys_multi_heap shared_multi_heap; - -+/* -+ * ZephCore: sys_heap is not internally synchronized ("All locking must be -+ * provided by the user", sys_heap.h), and neither was this pool, although it -+ * is a system-wide service shared by drivers and applications. On ESP32 with -+ * CONFIG_ESP_WIFI_HEAP_SPIRAM the Wi-Fi adapter allocates and frees from here -+ * on several threads at once (the Wi-Fi task, its event thread and every -+ * transmitting thread); under traffic that corrupted the heap ("double -+ * free?" / "free list linkage") and panicked the Wi-Fi task. A spinlock, as -+ * k_heap uses around the same allocator. -+ */ -+static struct k_spinlock smh_lock; -+ - static struct { - struct sys_heap heap_pool[MAX_MULTI_HEAPS]; - unsigned int heap_cnt; -@@ -66,6 +78,8 @@ int shared_multi_heap_add(struct shared_multi_heap_region *region, void *user_da - return -ENOMEM; - } - -+ k_spinlock_key_t key = k_spin_lock(&smh_lock); -+ - slot = smh_data[attr].heap_cnt; - h = &smh_data[attr].heap_pool[slot]; - -@@ -74,12 +88,17 @@ int shared_multi_heap_add(struct shared_multi_heap_region *region, void *user_da - - smh_data[attr].heap_cnt++; - -+ k_spin_unlock(&smh_lock, key); -+ - return 0; - } - - void shared_multi_heap_free(void *block) - { -+ k_spinlock_key_t key = k_spin_lock(&smh_lock); -+ - sys_multi_heap_free(&shared_multi_heap, block); -+ k_spin_unlock(&smh_lock, key); - } - - void *shared_multi_heap_alloc(enum shared_multi_heap_attr attr, size_t bytes) -@@ -88,7 +107,11 @@ void *shared_multi_heap_alloc(enum shared_multi_heap_attr attr, size_t bytes) - return NULL; - } - -- return sys_multi_heap_alloc(&shared_multi_heap, (void *)(long) attr, bytes); -+ k_spinlock_key_t key = k_spin_lock(&smh_lock); -+ void *block = sys_multi_heap_alloc(&shared_multi_heap, (void *)(long) attr, bytes); -+ -+ k_spin_unlock(&smh_lock, key); -+ return block; - } - - void *shared_multi_heap_realloc(enum shared_multi_heap_attr attr, void *ptr, size_t bytes) -@@ -97,8 +120,12 @@ void *shared_multi_heap_realloc(enum shared_multi_heap_attr attr, void *ptr, siz - return NULL; - } - -- return sys_multi_heap_aligned_realloc(&shared_multi_heap, (void *)(long) attr, -- ptr, 0, bytes); -+ k_spinlock_key_t key = k_spin_lock(&smh_lock); -+ void *block = sys_multi_heap_aligned_realloc(&shared_multi_heap, (void *)(long) attr, -+ ptr, 0, bytes); -+ -+ k_spin_unlock(&smh_lock, key); -+ return block; - } - - void *shared_multi_heap_aligned_alloc(enum shared_multi_heap_attr attr, -@@ -108,8 +135,12 @@ void *shared_multi_heap_aligned_alloc(enum shared_multi_heap_attr attr, - return NULL; - } - -- return sys_multi_heap_aligned_alloc(&shared_multi_heap, (void *)(long) attr, -- align, bytes); -+ k_spinlock_key_t key = k_spin_lock(&smh_lock); -+ void *block = sys_multi_heap_aligned_alloc(&shared_multi_heap, (void *)(long) attr, -+ align, bytes); -+ -+ k_spin_unlock(&smh_lock, key); -+ return block; - } - - int shared_multi_heap_pool_init(void) diff --git a/zephcore/west.yml b/zephcore/west.yml index 7ecb57e..a2b839c 100644 --- a/zephcore/west.yml +++ b/zephcore/west.yml @@ -6,7 +6,7 @@ manifest: projects: - name: zephyr remote: zephyrproject-rtos - revision: 7d713288b4baab1cffecadf16f258d9a3885d713 + revision: 3e7672a71bd954ca46c38c99d8d8f68a0fb23090 import: true self: