mirror of
https://github.com/esphome/esphome.git
synced 2026-10-19 20:49:35 +00:00
[nrf52] Add the Makerdiary nRF52840 MDK USB Dongle
This commit is contained in:
@@ -71,6 +71,7 @@ from esphome.types import ConfigType
|
||||
from .boards import BOARDS_ZEPHYR, BOOTLOADER_CONFIG, SELF_RESET_PINS
|
||||
from .const import (
|
||||
BOOTLOADER_ADAFRUIT,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_NOSD,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD132,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V6,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V7,
|
||||
@@ -200,6 +201,7 @@ def set_framework(config: ConfigType) -> ConfigType:
|
||||
# DFU bootloader with Nordic's nrfutil; mcuboot uses mcumgr instead
|
||||
SERIAL_DFU_BOOTLOADERS = (
|
||||
BOOTLOADER_ADAFRUIT,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_NOSD,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD132,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V6,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V7,
|
||||
@@ -1149,12 +1151,14 @@ def run_compile(args, config: ConfigType) -> bool:
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD132: ("0x0051", "0x009D"),
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V6: ("0x0052", "0x00B6"),
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V7: ("0x0052", "0x00CA,0x0100,0x0123"),
|
||||
BOOTLOADER_ADAFRUIT_NRF52_NOSD: ("0x0052", "0x00"), # no SoftDevice to require
|
||||
}
|
||||
# UF2 family IDs — nRF52832 vs nRF52840 per SoftDevice variant
|
||||
_UF2_FAMILY_IDS = {
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD132: "0x7EAED30A",
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V6: "0xADA52840",
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V7: "0xADA52840",
|
||||
BOOTLOADER_ADAFRUIT_NRF52_NOSD: "0xADA52840",
|
||||
}
|
||||
|
||||
# SDK < 2.9.2 places artifacts directly in build_dir/zephyr/.
|
||||
|
||||
@@ -3,6 +3,7 @@ from esphome.components.zephyr.const import KEY_BOOTLOADER
|
||||
|
||||
from .const import (
|
||||
BOOTLOADER_ADAFRUIT,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_NOSD,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD132,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V6,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V7,
|
||||
@@ -36,6 +37,16 @@ BOARDS_ZEPHYR = {
|
||||
},
|
||||
# Nordic nRF52840 Dongle (PCA10059): factory Open DFU bootloader at 0xE0000, kept in place
|
||||
"nrf52840dongle": {KEY_BOOTLOADER: [BOOTLOADER_NRF]},
|
||||
# Makerdiary nRF52840 MDK USB Dongle: its UF2 bootloader is an Adafruit fork without a
|
||||
# SoftDevice; Adafruit's own builds for the board carry one
|
||||
"nrf52840_mdk_usb_dongle": {
|
||||
KEY_BOOTLOADER: [
|
||||
BOOTLOADER_ADAFRUIT_NRF52_NOSD,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V7,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V6,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD132,
|
||||
]
|
||||
},
|
||||
}
|
||||
|
||||
# Boards with a GPIO wired to their RESET pin: driving it low is a pin reset, which the factory
|
||||
@@ -72,4 +83,9 @@ BOOTLOADER_CONFIG = {
|
||||
BOOTLOADER_NRF: [
|
||||
Section("open_bootloader", 0xE0000, 0x20000, "flash_primary"),
|
||||
],
|
||||
# Same MBR page and application start as above; the bootloader, its settings and the MBR
|
||||
# parameters fill the last 48 KB
|
||||
BOOTLOADER_ADAFRUIT_NRF52_NOSD: [
|
||||
Section("Adafruit_nRF52_Bootloader", 0xF4000, 0xC000, "flash_primary"),
|
||||
],
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ BOOTLOADER_ADAFRUIT = "adafruit"
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD132 = "adafruit_nrf52_sd132"
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V6 = "adafruit_nrf52_sd140_v6"
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V7 = "adafruit_nrf52_sd140_v7"
|
||||
BOOTLOADER_ADAFRUIT_NRF52_NOSD = "adafruit_nrf52_nosd"
|
||||
BOOTLOADER_NRF = "nrf"
|
||||
|
||||
EXTRA_ADC = [
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
nrf52:
|
||||
dcdc: False
|
||||
dfu: true # the 1200 bps touch reboots into the UF2 bootloader
|
||||
@@ -0,0 +1,15 @@
|
||||
esphome:
|
||||
name: componenttestnrf52
|
||||
friendly_name: $component_name
|
||||
|
||||
nrf52:
|
||||
board: nrf52840_mdk_usb_dongle
|
||||
|
||||
logger:
|
||||
level: VERY_VERBOSE
|
||||
|
||||
packages:
|
||||
component_under_test: !include
|
||||
file: $component_test_file
|
||||
vars:
|
||||
component_test_file: $component_test_file
|
||||
@@ -7,7 +7,10 @@ from unittest.mock import Mock, patch
|
||||
import pytest
|
||||
|
||||
from esphome.components import nrf52
|
||||
from esphome.components.nrf52.const import BOOTLOADER_ADAFRUIT_NRF52_SD140_V7
|
||||
from esphome.components.nrf52.const import (
|
||||
BOOTLOADER_ADAFRUIT_NRF52_NOSD,
|
||||
BOOTLOADER_ADAFRUIT_NRF52_SD140_V7,
|
||||
)
|
||||
from esphome.components.zephyr.const import KEY_BOARD, KEY_BOOTLOADER
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import KEY_CORE, KEY_FRAMEWORK_VERSION, Toolchain
|
||||
@@ -138,3 +141,24 @@ def test_sd140_v7_dfu_accepts_all_s140_7_softdevices(
|
||||
cmd = next(c.args[0] for c in run_cmd.call_args_list if "genpkg" in c.args[0])
|
||||
sd_req = cmd[cmd.index("--sd-req") + 1].split(",")
|
||||
assert sd_req == ["0x00CA", "0x0100", "0x0123"]
|
||||
|
||||
|
||||
def test_softdevice_free_adafruit_layout_requires_no_softdevice(
|
||||
build_dir: Path, run_cmd: Mock
|
||||
) -> None:
|
||||
"""The Makerdiary MDK USB Dongle's bootloader takes an nRF52840 UF2 and a package that
|
||||
does not ask for a SoftDevice."""
|
||||
with patch.object(
|
||||
nrf52,
|
||||
"zephyr_data",
|
||||
return_value={
|
||||
KEY_BOARD: "board",
|
||||
KEY_BOOTLOADER: BOOTLOADER_ADAFRUIT_NRF52_NOSD,
|
||||
},
|
||||
):
|
||||
_build(build_dir, cv.Version(3, 4, 0), ["zephyr/zephyr/zephyr.hex"], run_cmd)
|
||||
uf2 = next(c.args[0] for c in run_cmd.call_args_list if "-f" in c.args[0])
|
||||
assert uf2[uf2.index("-f") + 1] == "0xADA52840"
|
||||
genpkg = next(c.args[0] for c in run_cmd.call_args_list if "genpkg" in c.args[0])
|
||||
assert genpkg[genpkg.index("--dev-type") + 1] == "0x0052"
|
||||
assert genpkg[genpkg.index("--sd-req") + 1] == "0x00"
|
||||
|
||||
@@ -11,7 +11,10 @@ from esphome.components.nrf52 import (
|
||||
set_core_data,
|
||||
)
|
||||
from esphome.components.nrf52.boards import BOOTLOADER_CONFIG
|
||||
from esphome.components.nrf52.const import BOOTLOADER_NRF
|
||||
from esphome.components.nrf52.const import (
|
||||
BOOTLOADER_ADAFRUIT_NRF52_NOSD,
|
||||
BOOTLOADER_NRF,
|
||||
)
|
||||
from esphome.components.zephyr.const import KEY_PM_STATIC, KEY_ZEPHYR
|
||||
from esphome.components.zephyr_mcumgr.ota import _validate_bootloader
|
||||
from esphome.config import path_context
|
||||
@@ -37,12 +40,20 @@ def test_dongle_rejects_foreign_bootloader() -> None:
|
||||
_detect_bootloader({"board": "nrf52840dongle", "bootloader": "mcuboot"})
|
||||
|
||||
|
||||
def _dongle_core_data() -> None:
|
||||
def test_mdk_usb_dongle_defaults_to_the_softdevice_free_adafruit_layout() -> None:
|
||||
"""Makerdiary's UF2 bootloader is an Adafruit fork that ships without a SoftDevice."""
|
||||
config = _detect_bootloader({"board": "nrf52840_mdk_usb_dongle"})
|
||||
assert config["bootloader"] == BOOTLOADER_ADAFRUIT_NRF52_NOSD
|
||||
|
||||
|
||||
def _dongle_core_data(
|
||||
board: str = "nrf52840dongle", bootloader: str = BOOTLOADER_NRF
|
||||
) -> None:
|
||||
CORE.data[KEY_CORE] = {}
|
||||
CORE.testing_mode = (
|
||||
False # the real flash, not the larger one faked for grouped tests
|
||||
)
|
||||
set_core_data({"board": "nrf52840dongle", "bootloader": BOOTLOADER_NRF})
|
||||
set_core_data({"board": board, "bootloader": bootloader})
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -64,6 +75,16 @@ def test_nrf_bootloader_reserves_factory_region() -> None:
|
||||
assert registered["open_bootloader"].end_address == 0x100000
|
||||
|
||||
|
||||
def test_adafruit_nosd_reserves_only_the_bootloader() -> None:
|
||||
"""Without a SoftDevice the app follows the MBR page at 0x1000, as with the Open DFU
|
||||
bootloader; the Adafruit bootloader keeps its usual place at the top of the flash."""
|
||||
_dongle_core_data("nrf52840_mdk_usb_dongle", BOOTLOADER_ADAFRUIT_NRF52_NOSD)
|
||||
registered = {s.name: s for s in CORE.data[KEY_ZEPHYR][KEY_PM_STATIC]}
|
||||
assert set(registered) == {"Adafruit_nRF52_Bootloader"}
|
||||
assert registered["Adafruit_nRF52_Bootloader"].address == 0xF4000
|
||||
assert registered["Adafruit_nRF52_Bootloader"].end_address == 0x100000
|
||||
|
||||
|
||||
def test_nrf_bootloader_rejects_mcumgr_ota() -> None:
|
||||
"""OTA with mcumgr places its slot against a SoftDevice, which this layout has none of."""
|
||||
_dongle_core_data()
|
||||
|
||||
Reference in New Issue
Block a user