mirror of
https://github.com/esphome/esphome.git
synced 2026-05-24 01:37:15 +08:00
[nrf52][zephyr] prepare for native builds (#16193)
Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com> Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
This commit is contained in:
@@ -9,6 +9,7 @@ import subprocess
|
||||
from esphome import pins
|
||||
import esphome.codegen as cg
|
||||
from esphome.components.zephyr import (
|
||||
add_extra_script,
|
||||
copy_files as zephyr_copy_files,
|
||||
zephyr_add_overlay,
|
||||
zephyr_add_pm_static,
|
||||
@@ -21,6 +22,7 @@ from esphome.components.zephyr import (
|
||||
from esphome.components.zephyr.const import (
|
||||
BOOTLOADER_MCUBOOT,
|
||||
CONF_CDC_ACM,
|
||||
KEY_BOARD,
|
||||
KEY_BOOTLOADER,
|
||||
KEY_ZEPHYR,
|
||||
CdcAcm,
|
||||
@@ -36,6 +38,7 @@ from esphome.const import (
|
||||
CONF_OTA,
|
||||
CONF_RESET_PIN,
|
||||
CONF_SAFE_MODE,
|
||||
CONF_TOOLCHAIN,
|
||||
CONF_VERSION,
|
||||
CONF_VOLTAGE,
|
||||
KEY_CORE,
|
||||
@@ -44,10 +47,12 @@ from esphome.const import (
|
||||
KEY_TARGET_PLATFORM,
|
||||
PLATFORM_NRF52,
|
||||
ThreadModel,
|
||||
Toolchain,
|
||||
)
|
||||
from esphome.core import CORE, CoroPriority, EsphomeError, coroutine_with_priority
|
||||
from esphome.core.config import BOARD_MAX_LENGTH
|
||||
import esphome.final_validate as fv
|
||||
from esphome.helpers import write_file_if_changed
|
||||
from esphome.storage_json import StorageJSON
|
||||
from esphome.types import ConfigType
|
||||
|
||||
@@ -67,8 +72,35 @@ AUTO_LOAD = ["zephyr", "preferences"]
|
||||
IS_TARGET_PLATFORM = True
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
FAKE_BOARD_MANIFEST = """
|
||||
{
|
||||
"frameworks": [
|
||||
"zephyr"
|
||||
],
|
||||
"name": "esphome nrf52",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"speed": 115200
|
||||
},
|
||||
"url": "https://esphome.io/",
|
||||
"vendor": "esphome",
|
||||
"build": {
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_fwid": "0x00B6"
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def set_core_data(config: ConfigType) -> ConfigType:
|
||||
# Resolve toolchain: CLI (already on CORE.toolchain) > YAML > default.
|
||||
if CORE.toolchain is None:
|
||||
CORE.toolchain = config.get(CONF_TOOLCHAIN, Toolchain.PLATFORMIO)
|
||||
zephyr_set_core_data(config)
|
||||
CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = PLATFORM_NRF52
|
||||
CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = KEY_ZEPHYR
|
||||
@@ -80,10 +112,18 @@ def set_core_data(config: ConfigType) -> ConfigType:
|
||||
|
||||
|
||||
def set_framework(config: ConfigType) -> ConfigType:
|
||||
if CONF_VERSION not in config[CONF_FRAMEWORK]:
|
||||
default_version = "2.6.1-b" if CORE.using_toolchain_platformio else "2.9.2"
|
||||
config = {
|
||||
**config,
|
||||
CONF_FRAMEWORK: {**config[CONF_FRAMEWORK], CONF_VERSION: default_version},
|
||||
}
|
||||
framework_ver = cv.Version.parse(
|
||||
cv.version_number(config[CONF_FRAMEWORK][CONF_VERSION])
|
||||
)
|
||||
CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] = framework_ver
|
||||
if not CORE.using_toolchain_platformio:
|
||||
return config
|
||||
if framework_ver < cv.Version(2, 9, 2):
|
||||
return cv.require_framework_version(
|
||||
nrf52_zephyr=cv.Version(2, 6, 1, "a"),
|
||||
@@ -182,7 +222,7 @@ CONFIG_SCHEMA = cv.All(
|
||||
default={},
|
||||
): cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_VERSION, default="2.6.1-b"): cv.string_strict,
|
||||
cv.Optional(CONF_VERSION): cv.string_strict,
|
||||
cv.Optional(CONF_ADVANCED, default={}): cv.Schema(
|
||||
{
|
||||
cv.Optional(
|
||||
@@ -238,40 +278,51 @@ FINAL_VALIDATE_SCHEMA = _final_validate
|
||||
@coroutine_with_priority(CoroPriority.PLATFORM)
|
||||
async def to_code(config: ConfigType) -> None:
|
||||
"""Convert the configuration to code."""
|
||||
cg.add_platformio_option("board", config[CONF_BOARD])
|
||||
cg.add_build_flag("-DUSE_NRF52")
|
||||
cg.add_define("ESPHOME_BOARD", config[CONF_BOARD])
|
||||
cg.add_define("ESPHOME_VARIANT", "NRF52")
|
||||
# nRF52 processors are single-core
|
||||
cg.add_define(ThreadModel.SINGLE)
|
||||
cg.add_platformio_option(CONF_FRAMEWORK, CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK])
|
||||
cg.add_platformio_option(
|
||||
"platform",
|
||||
"https://github.com/tomaszduda23/platform-nordicnrf52/archive/refs/tags/v10.3.0-5.zip",
|
||||
)
|
||||
cg.add_platformio_option(
|
||||
"platform_packages",
|
||||
[
|
||||
f"platformio/framework-zephyr@https://github.com/tomaszduda23/framework-sdk-nrf/archive/refs/tags/v{CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]}.zip",
|
||||
],
|
||||
)
|
||||
if CORE.using_toolchain_platformio:
|
||||
cg.add_platformio_option("board", config[CONF_BOARD])
|
||||
cg.add_platformio_option(
|
||||
CONF_FRAMEWORK, CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK]
|
||||
)
|
||||
cg.add_platformio_option(
|
||||
"platform",
|
||||
"https://github.com/tomaszduda23/platform-nordicnrf52/archive/refs/tags/v10.3.0-5.zip",
|
||||
)
|
||||
cg.add_platformio_option(
|
||||
"platform_packages",
|
||||
[
|
||||
f"platformio/framework-zephyr@https://github.com/tomaszduda23/framework-sdk-nrf/archive/refs/tags/v{CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]}.zip",
|
||||
],
|
||||
)
|
||||
if config[KEY_BOOTLOADER] != BOOTLOADER_MCUBOOT:
|
||||
# make sure that firmware.zip is created
|
||||
# for Adafruit_nRF52_Bootloader
|
||||
cg.add_platformio_option("board_upload.protocol", "nrfutil")
|
||||
cg.add_platformio_option("board_upload.use_1200bps_touch", "true")
|
||||
cg.add_platformio_option("board_upload.require_upload_port", "true")
|
||||
cg.add_platformio_option("board_upload.wait_for_upload_port", "true")
|
||||
|
||||
add_extra_script(
|
||||
"pre",
|
||||
"pre_build.py",
|
||||
Path(__file__).parent / "pre_build.py.script",
|
||||
)
|
||||
# build is done by west so bypass board checking in platformio
|
||||
cg.add_platformio_option("boards_dir", CORE.relative_build_path("boards"))
|
||||
|
||||
if config[KEY_BOOTLOADER] == BOOTLOADER_MCUBOOT:
|
||||
cg.add_define("USE_BOOTLOADER_MCUBOOT")
|
||||
else:
|
||||
if "_sd" in config[KEY_BOOTLOADER]:
|
||||
bootloader = config[KEY_BOOTLOADER].split("_")
|
||||
sd_id = bootloader[2][2:]
|
||||
cg.add_define("USE_SOFTDEVICE_ID", int(sd_id))
|
||||
if (len(bootloader)) > 3:
|
||||
sd_version = bootloader[3][1:]
|
||||
cg.add_define("USE_SOFTDEVICE_VERSION", int(sd_version))
|
||||
# make sure that firmware.zip is created
|
||||
# for Adafruit_nRF52_Bootloader
|
||||
cg.add_platformio_option("board_upload.protocol", "nrfutil")
|
||||
cg.add_platformio_option("board_upload.use_1200bps_touch", "true")
|
||||
cg.add_platformio_option("board_upload.require_upload_port", "true")
|
||||
cg.add_platformio_option("board_upload.wait_for_upload_port", "true")
|
||||
elif "_sd" in config[KEY_BOOTLOADER]:
|
||||
bootloader = config[KEY_BOOTLOADER].split("_")
|
||||
sd_id = bootloader[2][2:]
|
||||
cg.add_define("USE_SOFTDEVICE_ID", int(sd_id))
|
||||
if (len(bootloader)) > 3:
|
||||
sd_version = bootloader[3][1:]
|
||||
cg.add_define("USE_SOFTDEVICE_VERSION", int(sd_version))
|
||||
|
||||
zephyr_setup_preferences()
|
||||
zephyr_to_code(config)
|
||||
@@ -341,6 +392,16 @@ async def _dfu_to_code(dfu_config):
|
||||
|
||||
def copy_files() -> None:
|
||||
"""Copy files to the build directory."""
|
||||
|
||||
if CORE.using_toolchain_platformio and (
|
||||
zephyr_data()[KEY_BOOTLOADER] == BOOTLOADER_MCUBOOT
|
||||
or zephyr_data()[KEY_BOARD] == "xiao_ble"
|
||||
):
|
||||
write_file_if_changed(
|
||||
CORE.relative_build_path(f"boards/{zephyr_data()[KEY_BOARD]}.json"),
|
||||
FAKE_BOARD_MANIFEST,
|
||||
)
|
||||
|
||||
zephyr_copy_files()
|
||||
|
||||
|
||||
@@ -415,6 +476,8 @@ def upload_program(config: ConfigType, args, host: str) -> bool:
|
||||
if zephyr_data()[KEY_BOOTLOADER] == BOOTLOADER_MCUBOOT:
|
||||
mcumgr_device = host
|
||||
else:
|
||||
if not CORE.using_toolchain_platformio:
|
||||
raise EsphomeError("Not implemented yet")
|
||||
result = _upload_using_platformio(config, host, ["-t", "upload"])
|
||||
if result != 0:
|
||||
raise EsphomeError(f"Upload failed with result: {result}")
|
||||
|
||||
@@ -25,6 +25,14 @@ BOARDS_ZEPHYR = {
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V6,
|
||||
]
|
||||
},
|
||||
"adafruit_itsybitsy": {
|
||||
KEY_BOOTLOADER: [
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V6,
|
||||
BOOTLOADER_ADAFRUIT,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD132,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V7,
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
# https://github.com/ffenix113/zigbee_home/blob/17bb7b9e9d375e756da9e38913f53303937fb66a/types/board/known_boards.go
|
||||
|
||||
@@ -10,9 +10,7 @@ from esphome.helpers import copy_file_if_changed, write_file_if_changed
|
||||
from esphome.types import ConfigType
|
||||
|
||||
from .const import (
|
||||
BOOTLOADER_MCUBOOT,
|
||||
CONF_CDC_ACM,
|
||||
KEY_BOARD,
|
||||
KEY_BOOTLOADER,
|
||||
KEY_EXTRA_BUILD_FILES,
|
||||
KEY_KCONFIG,
|
||||
@@ -50,8 +48,8 @@ class Section:
|
||||
class ZephyrData(TypedDict):
|
||||
board: str
|
||||
bootloader: str
|
||||
prj_conf: dict[str, tuple[PrjConfValueType, bool]]
|
||||
overlay: str
|
||||
prj_conf: dict[str, dict[str, tuple[PrjConfValueType, bool]]]
|
||||
overlay: dict[str, str]
|
||||
extra_build_files: dict[str, Path]
|
||||
pm_static: list[Section]
|
||||
user: dict[str, list[str]]
|
||||
@@ -63,7 +61,9 @@ def zephyr_set_core_data(config: ConfigType) -> None:
|
||||
board=config[CONF_BOARD],
|
||||
bootloader=config[KEY_BOOTLOADER],
|
||||
prj_conf={},
|
||||
overlay="",
|
||||
overlay={
|
||||
"": "",
|
||||
}, # set empty to make sure that overlay is cleared after config change
|
||||
extra_build_files={},
|
||||
pm_static=[],
|
||||
user={},
|
||||
@@ -76,12 +76,14 @@ def zephyr_data() -> ZephyrData:
|
||||
|
||||
|
||||
def zephyr_add_prj_conf(
|
||||
name: str, value: PrjConfValueType, required: bool = True
|
||||
name: str, value: PrjConfValueType, required: bool = True, image: str = ""
|
||||
) -> None:
|
||||
"""Set an zephyr prj conf value."""
|
||||
if not name.startswith("CONFIG_"):
|
||||
name = "CONFIG_" + name
|
||||
prj_conf = zephyr_data()[KEY_PRJ_CONF]
|
||||
if image not in zephyr_data()[KEY_PRJ_CONF]:
|
||||
zephyr_data()[KEY_PRJ_CONF][image] = {}
|
||||
prj_conf = zephyr_data()[KEY_PRJ_CONF][image]
|
||||
if name not in prj_conf:
|
||||
prj_conf[name] = (value, required)
|
||||
return
|
||||
@@ -94,8 +96,11 @@ def zephyr_add_prj_conf(
|
||||
prj_conf[name] = (value, required)
|
||||
|
||||
|
||||
def zephyr_add_overlay(content):
|
||||
zephyr_data()[KEY_OVERLAY] += textwrap.dedent(content)
|
||||
def zephyr_add_overlay(content: str, image: str = "") -> None:
|
||||
data = zephyr_data()
|
||||
if image not in data[KEY_OVERLAY]:
|
||||
data[KEY_OVERLAY][image] = ""
|
||||
data[KEY_OVERLAY][image] += textwrap.dedent(content)
|
||||
|
||||
|
||||
def add_extra_build_file(filename: str, path: Path) -> bool:
|
||||
@@ -118,8 +123,6 @@ def zephyr_to_code(config: ConfigType) -> None:
|
||||
cg.add_build_flag("-DUSE_ZEPHYR")
|
||||
cg.add_define("USE_NATIVE_64BIT_TIME")
|
||||
cg.set_cpp_standard("gnu++20")
|
||||
# build is done by west so bypass board checking in platformio
|
||||
cg.add_platformio_option("boards_dir", CORE.relative_build_path("boards"))
|
||||
# c++ support
|
||||
zephyr_add_prj_conf("NEWLIB_LIBC", True)
|
||||
zephyr_add_prj_conf("FPU", True)
|
||||
@@ -132,18 +135,12 @@ def zephyr_to_code(config: ConfigType) -> None:
|
||||
# <err> os: Illegal load of EXC_RETURN into PC
|
||||
zephyr_add_prj_conf("MAIN_STACK_SIZE", 2048)
|
||||
|
||||
add_extra_script(
|
||||
"pre",
|
||||
"pre_build.py",
|
||||
Path(__file__).parent / "pre_build.py.script",
|
||||
)
|
||||
|
||||
CORE.add_job(_cdc_acm_to_code, config)
|
||||
|
||||
|
||||
@coroutine_with_priority(CoroPriority.FINAL)
|
||||
async def _cdc_acm_to_code(config: ConfigType) -> None:
|
||||
if "CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT" in zephyr_data()[KEY_PRJ_CONF]:
|
||||
if "CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT" in zephyr_data()[KEY_PRJ_CONF][""]:
|
||||
var = cg.new_Pvariable(config[CONF_CDC_ACM])
|
||||
await cg.register_component(var, {})
|
||||
|
||||
@@ -219,55 +216,28 @@ def copy_files():
|
||||
"""
|
||||
)
|
||||
|
||||
want_opts = zephyr_data()[KEY_PRJ_CONF]
|
||||
|
||||
prj_conf = (
|
||||
"\n".join(
|
||||
f"{name}={_format_prj_conf_val(value[0])}"
|
||||
for name, value in sorted(want_opts.items())
|
||||
for image, want_opts in zephyr_data()[KEY_PRJ_CONF].items():
|
||||
prj_conf = (
|
||||
"\n".join(
|
||||
f"{name}={_format_prj_conf_val(value[0])}"
|
||||
for name, value in sorted(want_opts.items())
|
||||
)
|
||||
+ "\n"
|
||||
)
|
||||
+ "\n"
|
||||
)
|
||||
|
||||
write_file_if_changed(CORE.relative_build_path("zephyr/prj.conf"), prj_conf)
|
||||
if image:
|
||||
path = CORE.relative_build_path(f"sysbuild/{image}.conf")
|
||||
else:
|
||||
path = CORE.relative_build_path("zephyr/prj.conf")
|
||||
|
||||
write_file_if_changed(
|
||||
CORE.relative_build_path("zephyr/app.overlay"),
|
||||
zephyr_data()[KEY_OVERLAY],
|
||||
)
|
||||
write_file_if_changed(CORE.relative_build_path(path), prj_conf)
|
||||
|
||||
if (
|
||||
zephyr_data()[KEY_BOOTLOADER] == BOOTLOADER_MCUBOOT
|
||||
or zephyr_data()[KEY_BOARD] == "xiao_ble"
|
||||
):
|
||||
fake_board_manifest = """
|
||||
{
|
||||
"frameworks": [
|
||||
"zephyr"
|
||||
],
|
||||
"name": "esphome nrf52",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"speed": 115200
|
||||
},
|
||||
"url": "https://esphome.io/",
|
||||
"vendor": "esphome",
|
||||
"build": {
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_fwid": "0x00B6"
|
||||
}
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
write_file_if_changed(
|
||||
CORE.relative_build_path(f"boards/{zephyr_data()[KEY_BOARD]}.json"),
|
||||
fake_board_manifest,
|
||||
)
|
||||
for image, content in zephyr_data()[KEY_OVERLAY].items():
|
||||
if image:
|
||||
path = CORE.relative_build_path(f"sysbuild/{image}.overlay")
|
||||
else:
|
||||
path = CORE.relative_build_path("zephyr/app.overlay")
|
||||
write_file_if_changed(path, content)
|
||||
|
||||
for filename, path in zephyr_data()[KEY_EXTRA_BUILD_FILES].items():
|
||||
copy_file_if_changed(
|
||||
|
||||
Reference in New Issue
Block a user