1
0
mirror of https://github.com/esphome/esphome.git synced 2025-03-13 14:18:14 +00:00
This commit is contained in:
Tomasz Duda 2025-02-24 22:01:37 +01:00
parent 34285e7f7c
commit 5241102215
9 changed files with 0 additions and 490 deletions

View File

@ -1,100 +0,0 @@
import esphome.codegen as cg
from esphome.components.zephyr import zephyr_set_core_data, zephyr_to_code
from esphome.components.zephyr.const import (
BOOTLOADER_MCUBOOT,
KEY_BOOTLOADER,
KEY_ZEPHYR,
)
import esphome.config_validation as cv
from esphome.const import (
CONF_BOARD,
CONF_FRAMEWORK,
CONF_PLATFORM_VERSION,
CONF_TYPE,
KEY_CORE,
KEY_TARGET_FRAMEWORK,
KEY_TARGET_PLATFORM,
PLATFORM_NRF52,
)
from esphome.core import CORE, coroutine_with_priority
from .boards_zephyr import BOARDS_ZEPHYR
from .const import BOOTLOADER_ADAFRUIT
# force import gpio to register pin schema
from .gpio import nrf52_pin_to_code # noqa
AUTO_LOAD = ["zephyr"]
def set_core_data(config):
zephyr_set_core_data(config)
CORE.data[KEY_CORE][KEY_TARGET_PLATFORM] = PLATFORM_NRF52
CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK] = KEY_ZEPHYR
return config
BOOTLOADERS = [
BOOTLOADER_ADAFRUIT,
BOOTLOADER_MCUBOOT,
]
def _detect_bootloader(value):
value = value.copy()
bootloader = None
if (
value[CONF_BOARD] in BOARDS_ZEPHYR
and KEY_BOOTLOADER in BOARDS_ZEPHYR[value[CONF_BOARD]]
):
bootloader = BOARDS_ZEPHYR[value[CONF_BOARD]][KEY_BOOTLOADER]
if KEY_BOOTLOADER not in value:
if bootloader is None:
bootloader = BOOTLOADER_MCUBOOT
value[KEY_BOOTLOADER] = bootloader
elif bootloader is not None and bootloader != value[KEY_BOOTLOADER]:
raise cv.Invalid(
f"{value[CONF_FRAMEWORK][CONF_TYPE]} does not support '{bootloader}' bootloader for {value[CONF_BOARD]}"
)
return value
CONFIG_SCHEMA = cv.All(
cv.Schema(
{
cv.Required(CONF_BOARD): cv.string_strict,
cv.Optional(KEY_BOOTLOADER): cv.one_of(*BOOTLOADERS, lower=True),
}
),
_detect_bootloader,
set_core_data,
)
@coroutine_with_priority(1000)
async def to_code(config):
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 = {CONF_PLATFORM_VERSION: "platformio/nordicnrf52@10.3.0"}
cg.add_platformio_option(CONF_FRAMEWORK, CORE.data[KEY_CORE][KEY_TARGET_FRAMEWORK])
cg.add_platformio_option("platform", conf[CONF_PLATFORM_VERSION])
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",
],
)
if config[KEY_BOOTLOADER] == BOOTLOADER_ADAFRUIT:
# make sure that firmware.zip is created
# for Adafruit_nRF52_Bootloader
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")
zephyr_to_code(conf)

View File

@ -1,7 +0,0 @@
from esphome.components.zephyr.const import KEY_BOOTLOADER
from .const import BOOTLOADER_ADAFRUIT
BOARDS_ZEPHYR = {
"adafruit_itsybitsy_nrf52840": {KEY_BOOTLOADER: BOOTLOADER_ADAFRUIT},
}

View File

@ -1 +0,0 @@
BOOTLOADER_ADAFRUIT = "adafruit"

View File

@ -1,53 +0,0 @@
#ifdef USE_ZEPHYR
#include <zephyr/kernel.h>
#include <zephyr/drivers/watchdog.h>
#include <zephyr/sys/reboot.h>
namespace esphome {
static int wdt_channel_id = -EINVAL;
const device *wdt = nullptr;
void yield() { ::k_yield(); }
uint32_t millis() { return k_ticks_to_ms_floor32(k_uptime_ticks()); }
void delay(uint32_t ms) { ::k_msleep(ms); }
uint32_t micros() { return k_ticks_to_us_floor32(k_uptime_ticks()); }
void arch_init() {
wdt = DEVICE_DT_GET(DT_ALIAS(watchdog0));
if (device_is_ready(wdt)) {
static wdt_timeout_cfg wdt_config{};
wdt_config.flags = WDT_FLAG_RESET_SOC;
wdt_config.window.max = 2000;
wdt_channel_id = wdt_install_timeout(wdt, &wdt_config);
if (wdt_channel_id >= 0) {
wdt_setup(wdt, WDT_OPT_PAUSE_HALTED_BY_DBG | WDT_OPT_PAUSE_IN_SLEEP);
}
}
}
void arch_feed_wdt() {
if (wdt_channel_id >= 0) {
wdt_feed(wdt, wdt_channel_id);
}
}
void arch_restart() { sys_reboot(SYS_REBOOT_COLD); }
} // namespace esphome
void setup();
void loop();
int main() {
setup();
while (1) {
loop();
esphome::yield();
}
return 0;
}
#endif

View File

@ -1,120 +0,0 @@
#ifdef USE_ZEPHYR
#include "gpio.h"
#include "esphome/core/log.h"
#include <zephyr/drivers/gpio.h>
namespace esphome {
namespace zephyr {
static const char *const TAG = "zephyr";
static int flags_to_mode(gpio::Flags flags, bool inverted, bool value) {
int ret = 0;
if (flags & gpio::FLAG_INPUT) {
ret |= GPIO_INPUT;
}
if (flags & gpio::FLAG_OUTPUT) {
ret |= GPIO_OUTPUT;
if (value != inverted) {
ret |= GPIO_OUTPUT_INIT_HIGH;
} else {
ret |= GPIO_OUTPUT_INIT_LOW;
}
}
if (flags & gpio::FLAG_PULLUP) {
ret |= GPIO_PULL_UP;
}
if (flags & gpio::FLAG_PULLDOWN) {
ret |= GPIO_PULL_DOWN;
}
if (flags & gpio::FLAG_OPEN_DRAIN) {
ret |= GPIO_OPEN_DRAIN;
}
return ret;
}
struct ISRPinArg {
uint8_t pin;
bool inverted;
};
ISRInternalGPIOPin ZephyrGPIOPin::to_isr() const {
auto *arg = new ISRPinArg{};
arg->pin = pin_;
arg->inverted = inverted_;
return ISRInternalGPIOPin((void *) arg);
}
void ZephyrGPIOPin::attach_interrupt(void (*func)(void *), void *arg, gpio::InterruptType type) const {
// TODO
}
void ZephyrGPIOPin::setup() {
const struct device *gpio = nullptr;
if (pin_ < 32) {
#define GPIO0 DT_NODELABEL(gpio0)
#if DT_NODE_HAS_STATUS(GPIO0, okay)
gpio = DEVICE_DT_GET(GPIO0);
#else
#error "gpio0 is disabled"
#endif
} else {
#define GPIO1 DT_NODELABEL(gpio1)
#if DT_NODE_HAS_STATUS(GPIO1, okay)
gpio = DEVICE_DT_GET(GPIO1);
#else
#error "gpio1 is disabled"
#endif
}
if (device_is_ready(gpio)) {
gpio_ = gpio;
} else {
ESP_LOGE(TAG, "gpio %u is not ready.", pin_);
return;
}
pin_mode(flags_);
}
void ZephyrGPIOPin::pin_mode(gpio::Flags flags) {
if (nullptr == gpio_) {
return;
}
gpio_pin_configure(gpio_, pin_ % 32, flags_to_mode(flags, inverted_, value_));
}
std::string ZephyrGPIOPin::dump_summary() const {
char buffer[32];
snprintf(buffer, sizeof(buffer), "GPIO%u", pin_);
return buffer;
}
bool ZephyrGPIOPin::digital_read() {
if (nullptr == gpio_) {
return false;
}
return bool(gpio_pin_get(gpio_, pin_ % 32) != inverted_);
}
void ZephyrGPIOPin::digital_write(bool value) {
// make sure that value is not ignored since it can be inverted e.g. on switch side
// that way init state should be correct
value_ = value;
if (nullptr == gpio_) {
return;
}
gpio_pin_set(gpio_, pin_ % 32, value != inverted_ ? 1 : 0);
}
void ZephyrGPIOPin::detach_interrupt() const {
// TODO
}
} // namespace zephyr
bool IRAM_ATTR ISRInternalGPIOPin::digital_read() {
// TODO
return false;
}
} // namespace esphome
#endif

View File

@ -1,37 +0,0 @@
#pragma once
#ifdef USE_ZEPHYR
#include "esphome/core/hal.h"
struct device;
namespace esphome {
namespace zephyr {
class ZephyrGPIOPin : public InternalGPIOPin {
public:
void set_pin(uint8_t pin) { pin_ = pin; }
void set_inverted(bool inverted) { inverted_ = inverted; }
void set_flags(gpio::Flags flags) { flags_ = flags; }
void setup() override;
void pin_mode(gpio::Flags flags) override;
bool digital_read() override;
void digital_write(bool value) override;
std::string dump_summary() const override;
void detach_interrupt() const override;
ISRInternalGPIOPin to_isr() const override;
uint8_t get_pin() const override { return pin_; }
bool is_inverted() const override { return inverted_; }
protected:
void attach_interrupt(void (*func)(void *), void *arg, gpio::InterruptType type) const override;
uint8_t pin_;
bool inverted_;
gpio::Flags flags_;
const device *gpio_ = nullptr;
bool value_ = false;
};
} // namespace zephyr
} // namespace esphome
#endif // USE_ZEPHYR

View File

@ -1,4 +0,0 @@
Import("env")
board_config = env.BoardConfig()
board_config.update("frameworks", ["arduino", "zephyr"])

View File

@ -1,155 +0,0 @@
#ifdef USE_ZEPHYR
#include "esphome/core/preferences.h"
#include "esphome/core/log.h"
#include <zephyr/settings/settings.h>
namespace esphome {
namespace zephyr {
static const char *const TAG = "zephyr.preferences";
#define ESPHOME_SETTINGS_KEY "esphome"
class ZephyrPreferenceBackend : public ESPPreferenceBackend {
public:
ZephyrPreferenceBackend(uint32_t type) { this->type_ = type; }
ZephyrPreferenceBackend(uint32_t type, std::vector<uint8_t> &&data) : data(std::move(data)) { this->type_ = type; }
bool save(const uint8_t *data, size_t len) override {
this->data.resize(len);
std::memcpy(this->data.data(), data, len);
ESP_LOGVV(TAG, "save key: %u, len: %d", type_, len);
return true;
}
bool load(uint8_t *data, size_t len) override {
if (len != this->data.size()) {
ESP_LOGE(TAG, "size of setting key %s changed, from: %u, to: %u", get_key().c_str(), this->data.size(), len);
return false;
}
std::memcpy(data, this->data.data(), len);
ESP_LOGVV(TAG, "load key: %u, len: %d", type_, len);
return true;
}
const uint32_t get_type() const { return type_; }
const std::string get_key() const { return str_sprintf(ESPHOME_SETTINGS_KEY "/%" PRIx32, type_); }
std::vector<uint8_t> data;
protected:
uint32_t type_ = 0;
};
class ZephyrPreferences : public ESPPreferences {
public:
void open() {
int err = settings_subsys_init();
if (err) {
ESP_LOGE(TAG, "Failed to initialize settings subsystem, err: %d", err);
return;
}
static struct settings_handler settings_cb = {
.name = ESPHOME_SETTINGS_KEY,
.h_set = load_setting_,
.h_export = export_settings_,
};
err = settings_register(&settings_cb);
if (err) {
ESP_LOGE(TAG, "setting_register failed, err, %d", err);
return;
}
err = settings_load_subtree(ESPHOME_SETTINGS_KEY);
if (err) {
ESP_LOGE(TAG, "Cannot load settings, err: %d", err);
return;
}
ESP_LOGD(TAG, "Loaded %u settings.", backends_.size());
}
ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash) override {
return make_preference(length, type);
}
ESPPreferenceObject make_preference(size_t length, uint32_t type) override {
for (auto backend : backends_) {
if (backend->get_type() == type) {
return ESPPreferenceObject(backend);
}
}
printf("type %u size %u\n", type, backends_.size());
auto *pref = new ZephyrPreferenceBackend(type);
ESP_LOGD(TAG, "Add new setting %s.", pref->get_key().c_str());
backends_.push_back(pref);
return ESPPreferenceObject(pref);
}
bool sync() override {
ESP_LOGD(TAG, "Save settings");
int err = settings_save();
if (err) {
ESP_LOGE(TAG, "Cannot save settings, err: %d", err);
return false;
}
return true;
}
bool reset() override {
ESP_LOGD(TAG, "Reset settings");
for (auto backend : backends_) {
// save empty delete data
backend->data.clear();
}
sync();
return true;
}
protected:
std::vector<ZephyrPreferenceBackend *> backends_;
static int load_setting_(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg) {
auto type = parse_hex<uint32_t>(name);
if (!type.has_value()) {
std::string full_name(ESPHOME_SETTINGS_KEY);
full_name += "/";
full_name += name;
// Delete unusable keys. Otherwise it will stay in flash forever.
settings_delete(full_name.c_str());
return 1;
}
std::vector<uint8_t> data(len);
int err = read_cb(cb_arg, data.data(), len);
ESP_LOGD(TAG, "load setting, name: %s(%u), len %u, err %u", name, *type, len, err);
auto *pref = new ZephyrPreferenceBackend(*type, std::move(data));
static_cast<ZephyrPreferences *>(global_preferences)->backends_.push_back(pref);
return 0;
}
static int export_settings_(int (*cb)(const char *name, const void *value, size_t val_len)) {
for (auto backend : static_cast<ZephyrPreferences *>(global_preferences)->backends_) {
auto name = backend->get_key();
int err = cb(name.c_str(), backend->data.data(), backend->data.size());
ESP_LOGD(TAG, "save in flash, name %s, len %u, err %d", name.c_str(), backend->data.size(), err);
}
return 0;
}
};
void setup_preferences() {
auto *prefs = new ZephyrPreferences();
global_preferences = prefs;
prefs->open();
}
} // namespace zephyr
ESPPreferences *global_preferences; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
} // namespace esphome
#endif

View File

@ -1,13 +0,0 @@
#pragma once
#ifdef USE_ZEPHYR
namespace esphome {
namespace zephyr {
void setup_preferences();
} // namespace zephyr
} // namespace esphome
#endif