diff --git a/esphome/components/nrf52/__init__.py b/esphome/components/nrf52/__init__.py index 5d92a4fa80..d2ed3b15e9 100644 --- a/esphome/components/nrf52/__init__.py +++ b/esphome/components/nrf52/__init__.py @@ -141,6 +141,22 @@ CONF_UICR_ERASE = "uicr_erase" VOLTAGE_LEVELS = [1.8, 2.1, 2.4, 2.7, 3.0, 3.3] +_DFU_SCHEMA = cv.Schema( + { + cv.GenerateID(): cv.declare_id(DeviceFirmwareUpdate), + cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema, + } +) + + +def _dfu_schema(value: bool | ConfigType) -> ConfigType: + if isinstance(value, bool): + if not value: + raise cv.Invalid("Use 'dfu: true' or specify a configuration dict") + return _DFU_SCHEMA({}) + return _DFU_SCHEMA(value) + + CONFIG_SCHEMA = cv.All( _detect_bootloader, set_core_data, @@ -150,12 +166,7 @@ CONFIG_SCHEMA = cv.All( cv.string_strict, cv.ByteLength(max=BOARD_MAX_LENGTH) ), cv.Optional(KEY_BOOTLOADER): cv.one_of(*BOOTLOADERS, lower=True), - cv.Optional(CONF_DFU): cv.Schema( - { - cv.GenerateID(): cv.declare_id(DeviceFirmwareUpdate), - cv.Required(CONF_RESET_PIN): pins.gpio_output_pin_schema, - } - ), + cv.Optional(CONF_DFU): _dfu_schema, cv.Optional(CONF_DCDC, default=True): cv.boolean, cv.Optional(CONF_REG0): cv.Schema( { @@ -321,8 +332,9 @@ async def to_code(config: ConfigType) -> None: async def _dfu_to_code(dfu_config): cg.add_define("USE_NRF52_DFU") var = cg.new_Pvariable(dfu_config[CONF_ID]) - pin = await cg.gpio_pin_expression(dfu_config[CONF_RESET_PIN]) - cg.add(var.set_reset_pin(pin)) + if CONF_RESET_PIN in dfu_config: + pin = await cg.gpio_pin_expression(dfu_config[CONF_RESET_PIN]) + cg.add(var.set_reset_pin(pin)) zephyr_add_prj_conf("CDC_ACM_DTE_RATE_CALLBACK_SUPPORT", True) await cg.register_component(var, dfu_config) diff --git a/esphome/components/nrf52/dfu.cpp b/esphome/components/nrf52/dfu.cpp index c2017248d2..24dee99726 100644 --- a/esphome/components/nrf52/dfu.cpp +++ b/esphome/components/nrf52/dfu.cpp @@ -2,24 +2,34 @@ #ifdef USE_NRF52_DFU +#include "esphome/core/application.h" #include "esphome/core/log.h" #include "esphome/components/zephyr/cdc_acm.h" -namespace esphome { -namespace nrf52 { +#include + +namespace esphome::nrf52 { static const char *const TAG = "dfu"; static const uint32_t DFU_DBL_RESET_MAGIC = 0x5A1AD5; // SALADS +static const uint8_t DFU_MAGIC_UF2_RESET = 0x57; // Adafruit nRF52 bootloader UF2 magic void DeviceFirmwareUpdate::setup() { - this->reset_pin_->setup(); + if (this->reset_pin_ != nullptr) { + this->reset_pin_->setup(); + } #if defined(CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT) zephyr::global_cdc_acm->add_on_rate_callback([this](const device *, uint32_t rate) { if (rate == 1200) { volatile uint32_t *dbl_reset_mem = (volatile uint32_t *) 0x20007F7C; (*dbl_reset_mem) = DFU_DBL_RESET_MAGIC; - this->reset_pin_->digital_write(true); + if (this->reset_pin_ != nullptr) { + this->reset_pin_->digital_write(true); + } else { + NRF_POWER->GPREGRET = DFU_MAGIC_UF2_RESET; + App.reboot(); + } } }); #endif @@ -27,10 +37,13 @@ void DeviceFirmwareUpdate::setup() { void DeviceFirmwareUpdate::dump_config() { ESP_LOGCONFIG(TAG, "DFU:"); - LOG_PIN(" RESET Pin: ", this->reset_pin_); + if (this->reset_pin_ != nullptr) { + LOG_PIN(" RESET Pin: ", this->reset_pin_); + } else { + ESP_LOGCONFIG(TAG, " Method: GPREGRET"); + } } -} // namespace nrf52 -} // namespace esphome +} // namespace esphome::nrf52 #endif diff --git a/esphome/components/nrf52/dfu.h b/esphome/components/nrf52/dfu.h index 71060e43c1..82c7d9f54e 100644 --- a/esphome/components/nrf52/dfu.h +++ b/esphome/components/nrf52/dfu.h @@ -5,8 +5,7 @@ #include "esphome/core/component.h" #include "esphome/core/gpio.h" -namespace esphome { -namespace nrf52 { +namespace esphome::nrf52 { class DeviceFirmwareUpdate : public Component { public: void setup() override; @@ -14,10 +13,9 @@ class DeviceFirmwareUpdate : public Component { void dump_config() override; protected: - GPIOPin *reset_pin_; + GPIOPin *reset_pin_{nullptr}; }; -} // namespace nrf52 -} // namespace esphome +} // namespace esphome::nrf52 #endif diff --git a/tests/components/nrf52/test-dfu-pin.nrf52-xiao-ble.yaml b/tests/components/nrf52/test-dfu-pin.nrf52-xiao-ble.yaml new file mode 100644 index 0000000000..d53c692001 --- /dev/null +++ b/tests/components/nrf52/test-dfu-pin.nrf52-xiao-ble.yaml @@ -0,0 +1,9 @@ +nrf52: + dfu: + reset_pin: + number: 14 + inverted: true + mode: + output: true + reg0: + voltage: 1.8V diff --git a/tests/components/nrf52/test.nrf52-xiao-ble.yaml b/tests/components/nrf52/test.nrf52-xiao-ble.yaml index d53c692001..de4c0c6e00 100644 --- a/tests/components/nrf52/test.nrf52-xiao-ble.yaml +++ b/tests/components/nrf52/test.nrf52-xiao-ble.yaml @@ -1,9 +1,4 @@ nrf52: - dfu: - reset_pin: - number: 14 - inverted: true - mode: - output: true + dfu: true reg0: voltage: 1.8V