mirror of
https://github.com/esphome/esphome.git
synced 2026-08-31 18:16:03 +00:00
[nrf52][zephyr] support for multi on rate callbacks (#14557)
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user