[nrf52][zephyr] support for multi on rate callbacks (#14557)

This commit is contained in:
tomaszduda23
2026-03-07 11:18:21 -05:00
committed by GitHub
parent cbebb81196
commit 0e106d843c
7 changed files with 87 additions and 31 deletions
+3
View File
@@ -20,8 +20,10 @@ from esphome.components.zephyr import (
)
from esphome.components.zephyr.const import (
BOOTLOADER_MCUBOOT,
CONF_CDC_ACM,
KEY_BOOTLOADER,
KEY_ZEPHYR,
CdcAcm,
)
import esphome.config_validation as cv
from esphome.const import (
@@ -159,6 +161,7 @@ CONFIG_SCHEMA = cv.All(
cv.Required(CONF_VERSION): cv.string_strict,
}
),
cv.GenerateID(CONF_CDC_ACM): cv.declare_id(CdcAcm),
}
),
set_framework,
+10 -25
View File
@@ -2,42 +2,27 @@
#ifdef USE_NRF52_DFU
#include <zephyr/device.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/drivers/uart/cdc_acm.h>
#include "esphome/core/log.h"
#include "esphome/components/zephyr/cdc_acm.h"
namespace esphome {
namespace nrf52 {
static const char *const TAG = "dfu";
volatile bool goto_dfu = false; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
static const uint32_t DFU_DBL_RESET_MAGIC = 0x5A1AD5; // SALADS
#define DEVICE_AND_COMMA(node_id) DEVICE_DT_GET(node_id),
static void cdc_dte_rate_callback(const struct device * /*unused*/, uint32_t rate) {
if (rate == 1200) {
goto_dfu = true;
}
}
void DeviceFirmwareUpdate::setup() {
this->reset_pin_->setup();
const struct device *cdc_dev[] = {DT_FOREACH_STATUS_OKAY(zephyr_cdc_acm_uart, DEVICE_AND_COMMA)};
for (auto &idx : cdc_dev) {
cdc_acm_dte_rate_callback_set(idx, cdc_dte_rate_callback);
}
}
void DeviceFirmwareUpdate::loop() {
if (goto_dfu) {
goto_dfu = false;
volatile uint32_t *dbl_reset_mem = (volatile uint32_t *) 0x20007F7C;
(*dbl_reset_mem) = DFU_DBL_RESET_MAGIC;
this->reset_pin_->digital_write(true);
}
#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);
}
});
#endif
}
void DeviceFirmwareUpdate::dump_config() {
-1
View File
@@ -10,7 +10,6 @@ namespace nrf52 {
class DeviceFirmwareUpdate : public Component {
public:
void setup() override;
void loop() override;
void set_reset_pin(GPIOPin *reset) { this->reset_pin_ = reset; }
void dump_config() override;
+15 -5
View File
@@ -5,11 +5,13 @@ from typing import TypedDict
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome.const import CONF_BOARD, KEY_CORE, KEY_FRAMEWORK_VERSION
from esphome.core import CORE
from esphome.core import CORE, CoroPriority, coroutine_with_priority
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,
@@ -54,7 +56,7 @@ class ZephyrData(TypedDict):
user: dict[str, list[str]]
def zephyr_set_core_data(config):
def zephyr_set_core_data(config: ConfigType) -> None:
CORE.data[KEY_ZEPHYR] = ZephyrData(
board=config[CONF_BOARD],
bootloader=config[KEY_BOOTLOADER],
@@ -64,7 +66,6 @@ def zephyr_set_core_data(config):
pm_static=[],
user={},
)
return config
def zephyr_data() -> ZephyrData:
@@ -110,7 +111,7 @@ def add_extra_script(stage: str, filename: str, path: Path) -> None:
cg.add_platformio_option("extra_scripts", [key])
def zephyr_to_code(config):
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")
@@ -132,6 +133,15 @@ def zephyr_to_code(config):
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]:
var = cg.new_Pvariable(config[CONF_CDC_ACM])
await cg.register_component(var, {})
def zephyr_setup_preferences():
cg.add(zephyr_ns.setup_preferences())
@@ -151,7 +161,7 @@ def _format_prj_conf_val(value: PrjConfValueType) -> str:
raise ValueError
def zephyr_add_cdc_acm(config, id):
def zephyr_add_cdc_acm(config: ConfigType, id: int) -> None:
framework_ver: cv.Version = CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION]
if CORE.is_nrf52 and framework_ver >= cv.Version(3, 2, 0):
zephyr_add_prj_conf("CONFIG_USB_DEVICE_STACK_NEXT", False)
+30
View File
@@ -0,0 +1,30 @@
#if defined(CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT)
#include "cdc_acm.h"
#include <zephyr/drivers/uart.h>
#include <zephyr/drivers/uart/cdc_acm.h>
#define DEVICE_AND_COMMA(node_id) DEVICE_DT_GET(node_id),
namespace esphome::zephyr {
CdcAcm::CdcAcm() { global_cdc_acm = this; }
void CdcAcm::setup() {
#if DT_HAS_COMPAT_STATUS_OKAY(zephyr_cdc_acm_uart)
const struct device *cdc_dev[] = {DT_FOREACH_STATUS_OKAY(zephyr_cdc_acm_uart, DEVICE_AND_COMMA)};
for (auto &idx : cdc_dev) {
// only one global callback can be registered
cdc_acm_dte_rate_callback_set(idx, CdcAcm::cdc_dte_rate_callback_);
}
#endif // DT_HAS_COMPAT_STATUS_OKAY(zephyr_cdc_acm_uart)
}
void CdcAcm::cdc_dte_rate_callback_(const struct device *device, uint32_t rate) {
global_cdc_acm->defer([device, rate]() { global_cdc_acm->rate_callbacks_.call(device, rate); });
}
CdcAcm *global_cdc_acm; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
} // namespace esphome::zephyr
#endif
+27
View File
@@ -0,0 +1,27 @@
#pragma once
#if defined(CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT)
#include "esphome/core/component.h"
#include "esphome/core/helpers.h"
#include <zephyr/device.h>
namespace esphome::zephyr {
class CdcAcm : public Component {
public:
CdcAcm();
void setup() override;
void add_on_rate_callback(std::function<void(const device *, uint32_t)> &&callback) {
this->rate_callbacks_.add(std::move(callback));
}
protected:
static void cdc_dte_rate_callback_(const device *device, uint32_t rate);
CallbackManager<void(const device *, uint32_t)> rate_callbacks_;
};
extern CdcAcm *global_cdc_acm; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
} // namespace esphome::zephyr
#endif
+2
View File
@@ -14,3 +14,5 @@ KEY_BOARD: Final = "board"
KEY_USER: Final = "user"
zephyr_ns = cg.esphome_ns.namespace("zephyr")
CdcAcm = zephyr_ns.class_("CdcAcm", cg.Component)
CONF_CDC_ACM = "cdc_acm"