[libretiny] Regenerate boards, enable Cortex-M4 atomics, and consolidate platform code

This commit is contained in:
J. Nick Koston
2026-01-13 09:07:04 -10:00
parent 3d40979c96
commit a45cbc6595
13 changed files with 1919 additions and 1729 deletions
+1
View File
@@ -27,6 +27,7 @@
- [ ] RP2040
- [ ] BK72xx
- [ ] RTL87xx
- [ ] LN882x
- [ ] nRF52840
## Example entry for `config.yaml`:
+1
View File
@@ -27,6 +27,7 @@ COMPONENT_DATA = LibreTinyComponent(
board_pins=BK72XX_BOARD_PINS,
pin_validation=None,
usage_validation=None,
supports_atomics=False,
)
File diff suppressed because it is too large Load Diff
+18 -5
View File
@@ -35,6 +35,7 @@ from .const import (
FAMILY_BK7231N,
FAMILY_COMPONENT,
FAMILY_FRIENDLY,
FAMILY_RTL8710B,
KEY_BOARD,
KEY_COMPONENT,
KEY_COMPONENT_DATA,
@@ -278,11 +279,23 @@ async def component_to_code(config):
cg.add_build_flag(f"-DUSE_LIBRETINY_VARIANT_{config[CONF_FAMILY]}")
cg.add_define("ESPHOME_BOARD", config[CONF_BOARD])
cg.add_define("ESPHOME_VARIANT", FAMILY_FRIENDLY[config[CONF_FAMILY]])
# LibreTiny uses MULTI_NO_ATOMICS because platforms like BK7231N (ARM968E-S) lack
# exclusive load/store (no LDREX/STREX). std::atomic RMW operations require libatomic,
# which is not linked to save flash (4-8KB). Even if linked, libatomic would use locks
# (ATOMIC_INT_LOCK_FREE=1), so explicit FreeRTOS mutexes are simpler and equivalent.
cg.add_define(ThreadModel.MULTI_NO_ATOMICS)
# Set threading model based on chip architecture
component: LibreTinyComponent = CORE.data[KEY_LIBRETINY][KEY_COMPONENT_DATA]
if component.supports_atomics:
# RTL87xx (Cortex-M4) and LN882x (Cortex-M4F) have LDREX/STREX
cg.add_define(ThreadModel.MULTI_ATOMICS)
else:
# BK72xx uses ARM968E-S (ARMv5TE) which lacks LDREX/STREX.
# std::atomic RMW operations would require libatomic (not linked to save
# 4-8KB flash). Even if linked, it would use locks, so explicit FreeRTOS
# mutexes are simpler and equivalent.
cg.add_define(ThreadModel.MULTI_NO_ATOMICS)
# RTL8710B needs FreeRTOS 8.2.3+ for xTaskNotifyGive/ulTaskNotifyTake
# required by AsyncTCP 3.4.3+ (https://github.com/esphome/esphome/issues/10220)
# RTL8720C (ambz2) requires FreeRTOS 10.x so this only applies to RTL8710B
if config[CONF_FAMILY] == FAMILY_RTL8710B:
cg.add_platformio_option("custom_versions.freertos", "8.2.3")
# force using arduino framework
cg.add_platformio_option("framework", "arduino")
+1
View File
@@ -11,6 +11,7 @@ class LibreTinyComponent:
board_pins: dict[str, dict[str, int]]
pin_validation: Callable[[int], int]
usage_validation: Callable[[dict], dict]
supports_atomics: bool = False # True for Cortex-M4(F) with LDREX/STREX
CONF_LIBRETINY = "libretiny"
@@ -33,6 +33,7 @@ from esphome.core import CORE
CODEOWNERS = ["@kuba2k2"]
AUTO_LOAD = ["libretiny"]
IS_TARGET_PLATFORM = True
COMPONENT_DATA = LibreTinyComponent(
name=COMPONENT_{COMPONENT},
@@ -40,6 +41,7 @@ COMPONENT_DATA = LibreTinyComponent(
board_pins={COMPONENT}_BOARD_PINS,
pin_validation={PIN_VALIDATION},
usage_validation={USAGE_VALIDATION},
supports_atomics={SUPPORTS_ATOMICS},
)
@@ -97,6 +99,14 @@ COMPONENT_MAP = {
"ln882x": "lightning-ln882x",
}
# Components with Cortex-M4(F) have LDREX/STREX for native atomic support.
# BK72xx uses ARM968E-S (ARMv5TE) which lacks these instructions.
COMPONENT_SUPPORTS_ATOMICS = {
"rtl87xx": True, # Cortex-M4
"ln882x": True, # Cortex-M4F
"bk72xx": False, # ARM968E-S
}
def subst(code: str, key: str, value: str) -> str:
return code.replace(f"{{{key}}}", value)
@@ -147,6 +157,7 @@ def write_component_code(
PIN_SCHEMA=PIN_SCHEMA_BASE,
PIN_VALIDATION="None",
USAGE_VALIDATION="None",
SUPPORTS_ATOMICS=str(COMPONENT_SUPPORTS_ATOMICS.get(component, False)),
)
# parse gpio.py file to find custom validators
+2 -1
View File
@@ -17,7 +17,7 @@ from esphome.core import CORE
from .boards import LN882X_BOARD_PINS, LN882X_BOARDS
CODEOWNERS = ["@lamauny"]
CODEOWNERS = ["@kuba2k2"]
AUTO_LOAD = ["libretiny"]
IS_TARGET_PLATFORM = True
@@ -27,6 +27,7 @@ COMPONENT_DATA = LibreTinyComponent(
board_pins=LN882X_BOARD_PINS,
pin_validation=None,
usage_validation=None,
supports_atomics=True,
)
+194 -123
View File
@@ -4,6 +4,14 @@
from esphome.components.libretiny.const import FAMILY_LN882H
LN882X_BOARDS = {
"generic-ln882hki": {
"name": "Generic - LN882HKI",
"family": FAMILY_LN882H,
},
"wb02a": {
"name": "WB02A Wi-Fi/BLE Module",
"family": FAMILY_LN882H,
},
"wl2s": {
"name": "WL2S Wi-Fi/BLE Module",
"family": FAMILY_LN882H,
@@ -12,13 +20,195 @@ LN882X_BOARDS = {
"name": "LN-02 Wi-Fi/BLE Module",
"family": FAMILY_LN882H,
},
"generic-ln882hki": {
"name": "Generic - LN882HKI",
"family": FAMILY_LN882H,
},
}
LN882X_BOARD_PINS = {
"generic-ln882hki": {
"WIRE0_SCL_0": 0,
"WIRE0_SCL_1": 1,
"WIRE0_SCL_2": 2,
"WIRE0_SCL_3": 3,
"WIRE0_SCL_4": 4,
"WIRE0_SCL_5": 5,
"WIRE0_SCL_6": 6,
"WIRE0_SCL_7": 7,
"WIRE0_SCL_8": 8,
"WIRE0_SCL_9": 9,
"WIRE0_SCL_10": 10,
"WIRE0_SCL_11": 11,
"WIRE0_SCL_12": 12,
"WIRE0_SCL_13": 19,
"WIRE0_SCL_14": 20,
"WIRE0_SCL_15": 21,
"WIRE0_SCL_16": 22,
"WIRE0_SCL_17": 23,
"WIRE0_SCL_18": 24,
"WIRE0_SCL_19": 25,
"WIRE0_SDA_0": 0,
"WIRE0_SDA_1": 1,
"WIRE0_SDA_2": 2,
"WIRE0_SDA_3": 3,
"WIRE0_SDA_4": 4,
"WIRE0_SDA_5": 5,
"WIRE0_SDA_6": 6,
"WIRE0_SDA_7": 7,
"WIRE0_SDA_8": 8,
"WIRE0_SDA_9": 9,
"WIRE0_SDA_10": 10,
"WIRE0_SDA_11": 11,
"WIRE0_SDA_12": 12,
"WIRE0_SDA_13": 19,
"WIRE0_SDA_14": 20,
"WIRE0_SDA_15": 21,
"WIRE0_SDA_16": 22,
"WIRE0_SDA_17": 23,
"WIRE0_SDA_18": 24,
"WIRE0_SDA_19": 25,
"SERIAL0_RX": 3,
"SERIAL0_TX": 2,
"SERIAL1_RX": 24,
"SERIAL1_TX": 25,
"ADC2": 0,
"ADC3": 1,
"ADC4": 4,
"ADC5": 19,
"ADC6": 20,
"ADC7": 21,
"PA00": 0,
"PA0": 0,
"PA01": 1,
"PA1": 1,
"PA02": 2,
"PA2": 2,
"PA03": 3,
"PA3": 3,
"PA04": 4,
"PA4": 4,
"PA05": 5,
"PA5": 5,
"PA06": 6,
"PA6": 6,
"PA07": 7,
"PA7": 7,
"PA08": 8,
"PA8": 8,
"PA09": 9,
"PA9": 9,
"PA10": 10,
"PA11": 11,
"PA12": 12,
"PB03": 19,
"PB3": 19,
"PB04": 20,
"PB4": 20,
"PB05": 21,
"PB5": 21,
"PB06": 22,
"PB6": 22,
"PB07": 23,
"PB7": 23,
"PB08": 24,
"PB8": 24,
"PB09": 25,
"PB9": 25,
"RX0": 3,
"RX1": 24,
"TX0": 2,
"TX1": 25,
"D0": 0,
"D1": 1,
"D2": 2,
"D3": 3,
"D4": 4,
"D5": 5,
"D6": 6,
"D7": 7,
"D8": 8,
"D9": 9,
"D10": 10,
"D11": 11,
"D12": 12,
"D13": 19,
"D14": 20,
"D15": 21,
"D16": 22,
"D17": 23,
"D18": 24,
"D19": 25,
"A2": 0,
"A3": 1,
"A4": 4,
"A5": 19,
"A6": 20,
"A7": 21,
},
"wb02a": {
"WIRE0_SCL_0": 7,
"WIRE0_SCL_1": 5,
"WIRE0_SCL_2": 3,
"WIRE0_SCL_3": 10,
"WIRE0_SCL_4": 2,
"WIRE0_SCL_5": 1,
"WIRE0_SCL_6": 4,
"WIRE0_SCL_7": 5,
"WIRE0_SCL_8": 9,
"WIRE0_SCL_9": 24,
"WIRE0_SCL_10": 25,
"WIRE0_SDA_0": 7,
"WIRE0_SDA_1": 5,
"WIRE0_SDA_2": 3,
"WIRE0_SDA_3": 10,
"WIRE0_SDA_4": 2,
"WIRE0_SDA_5": 1,
"WIRE0_SDA_6": 4,
"WIRE0_SDA_7": 5,
"WIRE0_SDA_8": 9,
"WIRE0_SDA_9": 24,
"WIRE0_SDA_10": 25,
"SERIAL0_RX": 3,
"SERIAL0_TX": 2,
"SERIAL1_RX": 24,
"SERIAL1_TX": 25,
"ADC3": 1,
"ADC4": 4,
"PA01": 1,
"PA1": 1,
"PA02": 2,
"PA2": 2,
"PA03": 3,
"PA3": 3,
"PA04": 4,
"PA4": 4,
"PA05": 5,
"PA5": 5,
"PA07": 7,
"PA7": 7,
"PA09": 9,
"PA9": 9,
"PA10": 10,
"PB08": 24,
"PB8": 24,
"PB09": 25,
"PB9": 25,
"RX0": 3,
"RX1": 24,
"SCL0": 25,
"SDA0": 25,
"TX0": 2,
"TX1": 25,
"D0": 7,
"D1": 5,
"D2": 3,
"D3": 10,
"D4": 2,
"D5": 1,
"D6": 4,
"D7": 9,
"D8": 24,
"D9": 25,
"A0": 1,
"A1": 4,
},
"wl2s": {
"WIRE0_SCL_0": 7,
"WIRE0_SCL_1": 12,
@@ -161,125 +351,6 @@ LN882X_BOARD_PINS = {
"A1": 1,
"A2": 0,
},
"generic-ln882hki": {
"WIRE0_SCL_0": 0,
"WIRE0_SCL_1": 1,
"WIRE0_SCL_2": 2,
"WIRE0_SCL_3": 3,
"WIRE0_SCL_4": 4,
"WIRE0_SCL_5": 5,
"WIRE0_SCL_6": 6,
"WIRE0_SCL_7": 7,
"WIRE0_SCL_8": 8,
"WIRE0_SCL_9": 9,
"WIRE0_SCL_10": 10,
"WIRE0_SCL_11": 11,
"WIRE0_SCL_12": 12,
"WIRE0_SCL_13": 19,
"WIRE0_SCL_14": 20,
"WIRE0_SCL_15": 21,
"WIRE0_SCL_16": 22,
"WIRE0_SCL_17": 23,
"WIRE0_SCL_18": 24,
"WIRE0_SCL_19": 25,
"WIRE0_SDA_0": 0,
"WIRE0_SDA_1": 1,
"WIRE0_SDA_2": 2,
"WIRE0_SDA_3": 3,
"WIRE0_SDA_4": 4,
"WIRE0_SDA_5": 5,
"WIRE0_SDA_6": 6,
"WIRE0_SDA_7": 7,
"WIRE0_SDA_8": 8,
"WIRE0_SDA_9": 9,
"WIRE0_SDA_10": 10,
"WIRE0_SDA_11": 11,
"WIRE0_SDA_12": 12,
"WIRE0_SDA_13": 19,
"WIRE0_SDA_14": 20,
"WIRE0_SDA_15": 21,
"WIRE0_SDA_16": 22,
"WIRE0_SDA_17": 23,
"WIRE0_SDA_18": 24,
"WIRE0_SDA_19": 25,
"SERIAL0_RX": 3,
"SERIAL0_TX": 2,
"SERIAL1_RX": 24,
"SERIAL1_TX": 25,
"ADC2": 0,
"ADC3": 1,
"ADC4": 4,
"ADC5": 19,
"ADC6": 20,
"ADC7": 21,
"PA00": 0,
"PA0": 0,
"PA01": 1,
"PA1": 1,
"PA02": 2,
"PA2": 2,
"PA03": 3,
"PA3": 3,
"PA04": 4,
"PA4": 4,
"PA05": 5,
"PA5": 5,
"PA06": 6,
"PA6": 6,
"PA07": 7,
"PA7": 7,
"PA08": 8,
"PA8": 8,
"PA09": 9,
"PA9": 9,
"PA10": 10,
"PA11": 11,
"PA12": 12,
"PB03": 19,
"PB3": 19,
"PB04": 20,
"PB4": 20,
"PB05": 21,
"PB5": 21,
"PB06": 22,
"PB6": 22,
"PB07": 23,
"PB7": 23,
"PB08": 24,
"PB8": 24,
"PB09": 25,
"PB9": 25,
"RX0": 3,
"RX1": 24,
"TX0": 2,
"TX1": 25,
"D0": 0,
"D1": 1,
"D2": 2,
"D3": 3,
"D4": 4,
"D5": 5,
"D6": 6,
"D7": 7,
"D8": 8,
"D9": 9,
"D10": 10,
"D11": 11,
"D12": 12,
"D13": 19,
"D14": 20,
"D15": 21,
"D16": 22,
"D17": 23,
"D18": 24,
"D19": 25,
"A2": 0,
"A3": 1,
"A4": 4,
"A5": 19,
"A6": 20,
"A7": 21,
},
}
BOARDS = LN882X_BOARDS
+1 -9
View File
@@ -6,13 +6,10 @@
# in schema.py file in this directory.
from esphome import pins
import esphome.codegen as cg
from esphome.components import libretiny
from esphome.components.libretiny.const import (
COMPONENT_RTL87XX,
FAMILY_RTL8710B,
KEY_COMPONENT_DATA,
KEY_FAMILY,
KEY_LIBRETINY,
LibreTinyComponent,
)
@@ -24,13 +21,13 @@ CODEOWNERS = ["@kuba2k2"]
AUTO_LOAD = ["libretiny"]
IS_TARGET_PLATFORM = True
COMPONENT_DATA = LibreTinyComponent(
name=COMPONENT_RTL87XX,
boards=RTL87XX_BOARDS,
board_pins=RTL87XX_BOARD_PINS,
pin_validation=None,
usage_validation=None,
supports_atomics=True,
)
@@ -48,11 +45,6 @@ CONFIG_SCHEMA.prepend_extra(_set_core_data)
async def to_code(config):
# Use FreeRTOS 8.2.3+ for xTaskNotifyGive/ulTaskNotifyTake required by AsyncTCP 3.4.3+
# https://github.com/esphome/esphome/issues/10220
# Only for RTL8710B (ambz) - RTL8720C (ambz2) requires FreeRTOS 10.x
if CORE.data[KEY_LIBRETINY][KEY_FAMILY] == FAMILY_RTL8710B:
cg.add_platformio_option("custom_versions.freertos", "8.2.3")
return await libretiny.component_to_code(config)
File diff suppressed because it is too large Load Diff
+3 -2
View File
@@ -612,8 +612,9 @@ uint64_t Scheduler::millis_64_(uint32_t now) {
// THREAD SAFETY NOTE:
// This function has three implementations, based on the precompiler flags
// - ESPHOME_THREAD_SINGLE - Runs on single-threaded platforms (ESP8266, RP2040, etc.)
// - ESPHOME_THREAD_MULTI_NO_ATOMICS - Runs on multi-threaded platforms without atomics (LibreTiny)
// - ESPHOME_THREAD_MULTI_ATOMICS - Runs on multi-threaded platforms with atomics (ESP32, HOST, etc.)
// - ESPHOME_THREAD_MULTI_NO_ATOMICS - Runs on multi-threaded platforms without atomics (LibreTiny BK72xx)
// - ESPHOME_THREAD_MULTI_ATOMICS - Runs on multi-threaded platforms with atomics (ESP32, HOST, LibreTiny
// RTL87xx/LN882x, etc.)
//
// Make sure all changes are synchronized if you edit this function.
//
@@ -0,0 +1,13 @@
logger:
level: VERBOSE
esphome:
on_boot:
- lambda: |-
int x = 100;
x = clamp(x, 50, 90);
assert(x == 90);
x = clamp_at_least(x, 95);
assert(x == 95);
x = clamp_at_most(x, 40);
assert(x == 40);
@@ -0,0 +1,13 @@
logger:
level: VERBOSE
esphome:
on_boot:
- lambda: |-
int x = 100;
x = clamp(x, 50, 90);
assert(x == 90);
x = clamp_at_least(x, 95);
assert(x == 95);
x = clamp_at_most(x, 40);
assert(x == 40);