mirror of
https://github.com/esphome/esphome.git
synced 2025-09-26 15:12:21 +01:00
245 lines
7.9 KiB
Python
245 lines
7.9 KiB
Python
import os
|
|
import esphome.codegen as cg
|
|
import esphome.config_validation as cv
|
|
from esphome.const import (
|
|
CONF_BOARD,
|
|
KEY_CORE,
|
|
KEY_TARGET_FRAMEWORK,
|
|
KEY_TARGET_PLATFORM,
|
|
PLATFORM_NRF52,
|
|
CONF_TYPE,
|
|
CONF_FRAMEWORK,
|
|
CONF_VARIANT,
|
|
)
|
|
from esphome.core import CORE, coroutine_with_priority
|
|
from esphome.helpers import (
|
|
write_file_if_changed,
|
|
copy_file_if_changed,
|
|
)
|
|
from typing import Union
|
|
|
|
# force import gpio to register pin schema
|
|
from .gpio import nrf52_pin_to_code # noqa
|
|
|
|
KEY_NRF52 = "nrf52"
|
|
|
|
|
|
def set_core_data(config):
|
|
CORE.data[KEY_NRF52] = {}
|
|
CORE.data[KEY_NRF52][KEY_PRJ_CONF_OPTIONS] = {}
|
|
CORE.data[KEY_NRF52][KEY_ZEPHYR_OVERLAY] = ""
|
|
CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = PLATFORM_NRF52
|
|
CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = config[CONF_FRAMEWORK][CONF_TYPE]
|
|
return config
|
|
|
|
|
|
# https://github.com/platformio/platform-nordicnrf52/releases
|
|
NORDICNRF52_PLATFORM_VERSION = cv.Version(10, 3, 0)
|
|
|
|
|
|
def _platform_check_versions(value):
|
|
value = value.copy()
|
|
value[CONF_PLATFORM_VERSION] = value.get(
|
|
CONF_PLATFORM_VERSION,
|
|
_parse_platform_version(str(NORDICNRF52_PLATFORM_VERSION)),
|
|
)
|
|
return value
|
|
|
|
|
|
def _parse_platform_version(value):
|
|
try:
|
|
# if platform version is a valid version constraint, prefix the default package
|
|
cv.platformio_version_constraint(value)
|
|
return f"platformio/nordicnrf52@{value}"
|
|
except cv.Invalid:
|
|
return value
|
|
|
|
|
|
CONF_PLATFORM_VERSION = "platform_version"
|
|
|
|
PLATFORM_FRAMEWORK_SCHEMA = cv.All(
|
|
cv.Schema(
|
|
{
|
|
cv.Optional(CONF_PLATFORM_VERSION): _parse_platform_version,
|
|
}
|
|
),
|
|
_platform_check_versions,
|
|
)
|
|
|
|
ZEPHYR_VARIANT_GENERIC = "generic"
|
|
ZEPHYR_VARIANT_NRF_SDK = "nrf-sdk"
|
|
ZEPHYR_VARIANTS = [
|
|
ZEPHYR_VARIANT_GENERIC,
|
|
ZEPHYR_VARIANT_NRF_SDK,
|
|
]
|
|
|
|
FRAMEWORK_VARIANTS = [
|
|
"zephyr",
|
|
"arduino",
|
|
]
|
|
|
|
FRAMEWORK_SCHEMA = cv.All(
|
|
cv.Schema(
|
|
{
|
|
cv.Required(CONF_TYPE): cv.one_of(*FRAMEWORK_VARIANTS, lower=True),
|
|
cv.Optional(CONF_VARIANT): cv.one_of(*ZEPHYR_VARIANTS, lower=True),
|
|
}
|
|
),
|
|
_platform_check_versions,
|
|
)
|
|
|
|
|
|
CONFIG_SCHEMA = cv.All(
|
|
cv.Schema(
|
|
{
|
|
cv.Required(CONF_BOARD): cv.string_strict,
|
|
cv.Optional(CONF_FRAMEWORK, default={}): FRAMEWORK_SCHEMA,
|
|
}
|
|
),
|
|
set_core_data,
|
|
)
|
|
|
|
nrf52_ns = cg.esphome_ns.namespace("nrf52")
|
|
|
|
|
|
PrjConfValueType = Union[bool, str, int]
|
|
KEY_PRJ_CONF_OPTIONS = "prj_conf_options"
|
|
KEY_ZEPHYR_OVERLAY = "zephyr_overlay"
|
|
|
|
|
|
def add_zephyr_prj_conf_option(name: str, value: PrjConfValueType):
|
|
"""Set an zephyr prj conf value."""
|
|
if not CORE.using_zephyr:
|
|
raise ValueError("Not an zephyr project")
|
|
if name in CORE.data[KEY_NRF52][KEY_PRJ_CONF_OPTIONS]:
|
|
old_value = CORE.data[KEY_NRF52][KEY_PRJ_CONF_OPTIONS][name]
|
|
if old_value != value:
|
|
raise ValueError(
|
|
f"{name} alread set with value {old_value}, new value {value}"
|
|
)
|
|
CORE.data[KEY_NRF52][KEY_PRJ_CONF_OPTIONS][name] = value
|
|
|
|
|
|
def add_zephyr_overlay(content):
|
|
if not CORE.using_zephyr:
|
|
raise ValueError("Not an zephyr project")
|
|
CORE.data[KEY_NRF52][KEY_ZEPHYR_OVERLAY] += content
|
|
|
|
|
|
@coroutine_with_priority(1000)
|
|
async def to_code(config):
|
|
cg.add(nrf52_ns.setup_preferences())
|
|
if config[CONF_BOARD] == "nrf52840":
|
|
if CORE.using_zephyr:
|
|
# this board works with https://github.com/adafruit/Adafruit_nRF52_Bootloader
|
|
config[CONF_BOARD] = "adafruit_itsybitsy_nrf52840"
|
|
elif CORE.using_arduino:
|
|
# it has most generic GPIO mapping
|
|
# TODO does it matter if custom board is defined?
|
|
config[CONF_BOARD] = "nrf52840_dk_adafruit"
|
|
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")
|
|
conf = config[CONF_FRAMEWORK]
|
|
cg.add_platformio_option(CONF_FRAMEWORK, conf[CONF_TYPE])
|
|
cg.add_platformio_option("platform", conf[CONF_PLATFORM_VERSION])
|
|
|
|
# make sure that firmware.zip is created
|
|
# for Adafruit_nRF52_Bootloader
|
|
# TODO add bootloader type to config
|
|
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")
|
|
cg.add_platformio_option("extra_scripts", [f"pre:build_{conf[CONF_TYPE]}.py"])
|
|
if CORE.using_arduino:
|
|
cg.add_build_flag("-DUSE_ARDUINO")
|
|
# watchdog
|
|
cg.add_build_flag("-DNRFX_WDT_ENABLED=1")
|
|
cg.add_build_flag("-DNRFX_WDT0_ENABLED=1")
|
|
cg.add_build_flag("-DNRFX_WDT_CONFIG_NO_IRQ=1")
|
|
# prevent setting up GPIO PINs
|
|
cg.add_platformio_option("board_build.variant", "nrf52840")
|
|
cg.add_platformio_option(
|
|
"board_build.variants_dir", os.path.dirname(os.path.realpath(__file__))
|
|
)
|
|
cg.add_library("https://github.com/NordicSemiconductor/nrfx#v2.1.0", None, None)
|
|
elif CORE.using_zephyr:
|
|
cg.add_build_flag("-DUSE_ZEPHYR")
|
|
if conf[CONF_VARIANT] == ZEPHYR_VARIANT_GENERIC:
|
|
cg.add_platformio_option(
|
|
"platform_packages",
|
|
[
|
|
"platformio/framework-zephyr@^2.30500.231204",
|
|
# "platformio/toolchain-gccarmnoneeabi@^1.120301.0"
|
|
],
|
|
)
|
|
elif conf[CONF_VARIANT] == ZEPHYR_VARIANT_NRF_SDK:
|
|
cg.add_platformio_option(
|
|
"platform_packages",
|
|
[
|
|
"platformio/framework-zephyr@https://github.com/tomaszduda23/framework-sdk-nrf",
|
|
"platformio/toolchain-gccarmnoneeabi@https://github.com/tomaszduda23/toolchain-sdk-ng",
|
|
],
|
|
)
|
|
else:
|
|
raise NotImplementedError
|
|
# c++ support
|
|
add_zephyr_prj_conf_option("CONFIG_NEWLIB_LIBC", False)
|
|
add_zephyr_prj_conf_option("CONFIG_NEWLIB_LIBC_NANO", True)
|
|
add_zephyr_prj_conf_option("CONFIG_NEWLIB_LIBC_FLOAT_PRINTF", True)
|
|
add_zephyr_prj_conf_option("CONFIG_CPLUSPLUS", True)
|
|
add_zephyr_prj_conf_option("CONFIG_LIB_CPLUSPLUS", True)
|
|
# watchdog
|
|
add_zephyr_prj_conf_option("CONFIG_WATCHDOG", True)
|
|
add_zephyr_prj_conf_option("CONFIG_WDT_DISABLE_AT_BOOT", False)
|
|
# TODO debug only
|
|
add_zephyr_prj_conf_option("CONFIG_DEBUG_THREAD_INFO", True)
|
|
|
|
else:
|
|
raise NotImplementedError
|
|
# add_zephyr_prj_conf_option("CONFIG_USE_SEGGER_RTT", True)
|
|
# add_zephyr_prj_conf_option("CONFIG_RTT_CONSOLE", True)
|
|
# add_zephyr_prj_conf_option("CONFIG_UART_CONSOLE", False)
|
|
|
|
|
|
def _format_prj_conf_val(value: PrjConfValueType) -> str:
|
|
if isinstance(value, bool):
|
|
return "y" if value else "n"
|
|
if isinstance(value, int):
|
|
return str(value)
|
|
if isinstance(value, str):
|
|
return f'"{value}"'
|
|
raise ValueError
|
|
|
|
|
|
# Called by writer.py
|
|
def copy_files():
|
|
if CORE.using_zephyr:
|
|
want_opts = CORE.data[KEY_NRF52][KEY_PRJ_CONF_OPTIONS]
|
|
contents = (
|
|
"\n".join(
|
|
f"{name}={_format_prj_conf_val(value)}"
|
|
for name, value in sorted(want_opts.items())
|
|
)
|
|
+ "\n"
|
|
)
|
|
|
|
write_file_if_changed(CORE.relative_build_path("zephyr/prj.conf"), contents)
|
|
write_file_if_changed(
|
|
CORE.relative_build_path("zephyr/app.overlay"),
|
|
CORE.data[KEY_NRF52][KEY_ZEPHYR_OVERLAY],
|
|
)
|
|
|
|
dir = os.path.dirname(__file__)
|
|
build_zephyr_file = os.path.join(
|
|
dir, f"build_{CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK]}.py.script"
|
|
)
|
|
copy_file_if_changed(
|
|
build_zephyr_file,
|
|
CORE.relative_build_path(
|
|
f"build_{CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK]}.py"
|
|
),
|
|
)
|