Updating to ESP eco-system per Oct 23 2025

This commit is contained in:
2025-10-23 09:26:10 +02:00
parent 974dd6f515
commit 5278dde5a1
8 changed files with 797 additions and 591 deletions

17
.cargo/config.toml Normal file
View File

@@ -0,0 +1,17 @@
[target.riscv32imc-unknown-none-elf]
runner = "espflash flash --monitor --chip esp32c3"
[env]
[build]
rustflags = [
# Required to obtain backtraces (e.g. when using the "esp-backtrace" crate.)
# NOTE: May negatively impact performance of produced code
"-C", "force-frame-pointers",
]
target = "riscv32imc-unknown-none-elf"
[unstable]
build-std = ["core"]

1163
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,38 +1,35 @@
[package]
name = "wallas-esp32c3"
version = "0.1.0"
edition = "2021"
version = "0.1.1"
edition = "2024"
[dependencies]
esp-backtrace = { version = "0.15.0", features = [
esp-backtrace = { version = "0.18.0", features = [
"esp32c3",
"exception-handler",
"panic-handler",
"println",
]}
esp-hal = { version = "0.23.1", features = [
esp-hal = { version = "1.0.0-rc.1", features = [
"esp32c3",
"unstable",
] }
esp-println = { version = "0.13.0", features = ["esp32c3", "log"] }
log = { version = "0.4.21" }
esp-alloc = { version = "0.6.0" }
embedded-io = "0.6.1"
esp-println = { version = "0.16.0", features = ["esp32c3", "log-04"] }
log = { version = "0.4.28" }
esp-alloc = "0.9.0"
esp-rtos = { version = "0.1.1", features = ["esp-radio", "embassy", "log-04", "esp32c3"] }
embedded-io = "0.7.1"
embedded-io-async = "0.7.0"
embassy-net = { version = "0.7.1", features = [ "tcp", "udp", "dhcpv4", "dns", "medium-ethernet"] }
embedded-io-async = "0.6.1"
embassy-net = { version = "0.6.0", features = [ "tcp", "udp", "dhcpv4", "dns", "medium-ethernet"] }
esp-wifi = { version = "0.12.0", default-features=false, features = [
esp-radio = { version = "0.16.0", default-features=false, features = [
"esp32c3",
"utils",
"wifi",
"esp-alloc",
"log",
] }
embassy-sync = "0.6.1"
rand_core = "0.9.0"
embassy-sync = "0.7.2"
rand_core = "0.9.3"
nom = { version = "8", default-features = false, features = [ "alloc" ] }
heapless = { version = "0.8.0", default-features = false }
heapless = { version = "0.9.1", default-features = false }
smoltcp = { version = "0.12.0", default-features = false, features = [
"medium-ethernet",
"proto-dhcpv4",
@@ -43,22 +40,19 @@ smoltcp = { version = "0.12.0", default-features = false, features = [
"socket-tcp",
"socket-udp",
] }
embassy-executor = { version = "0.7.0", features = [
"task-arena-size-163840"
] }
embassy-time = { version = "0.4.0", features = ["generic-queue-8"] }
esp-hal-embassy = { version = "0.6.0", features = ["esp32c3"] }
static_cell = { version = "2.1.0", features = ["nightly"] }
critical-section = "1.2.0"
embassy-executor = "0.9.1"
embassy-time = { version = "0.5.0", features = ["generic-queue-8"] }
static_cell = { version = "2.1.1" }
# critical-section = "1.2.0"
maud = { git = "https://github.com/jakobdalsgaard/maud.git", features = ["alloc", "picoserve"] }
picoserve = { version = "0.14.1", default-features = false, features = [
picoserve = { version = "0.16.0", default-features = false, features = [
"alloc",
"embassy",
"log",
] }
sntpc = { version = "0.5.1", default-features = false, features = [ "embassy-socket" ] }
chrono = { version = "0.4.39", default-features = false, features = [ "alloc" ] }
serde = { version = "1.0.217", default-features = false }
sntpc = { version = "0.6.1", default-features = false, features = [ "embassy-socket" ] }
chrono = { version = "0.4.42", default-features = false, features = [ "alloc" ] }
serde = { version = "1.0.228", default-features = false }
include_file_compress = "0.1.3"
[profile.dev]
@@ -74,3 +68,6 @@ incremental = false
lto = 'fat'
opt-level = 's'
overflow-checks = false
[profile.dev.package.esp-wifi]
opt-level = 3

0
set-env.sh Normal file → Executable file
View File

View File

@@ -21,7 +21,8 @@ const APP_JS_FILENAME: &str = concat!("/app-", env!("CARGO_PKG_VERSION_SAFE"), "
static PICO_CONFIG : picoserve::Config<Duration> = picoserve::Config::new(
picoserve::Timeouts {
start_read_request: Some(Duration::from_secs(5)),
start_read_request: Some(Duration::from_secs(1)),
persistent_start_read_request: Some(Duration::from_secs(1)),
read_request: Some(Duration::from_secs(1)),
write: Some(Duration::from_secs(1)),
}).keep_connection_alive();
@@ -118,15 +119,15 @@ fn page(heading: &str, content: Markup) -> Markup {
"RISC-V is a registered trademark of RISC-V International · Wallas is a registered trademark of Wallas-Marin Oy · Espressif is a registered trademark of Espressif Systems"
}
dialog #message .dialog-center {};
dialog #"set-target" .dialog-center {
dialog #set-target .dialog-center {
span ."cancel-x" { "🗙" };
form {
div #"temperature-form" {
div #temperature-form {
input #target type="range" min="5" max="25" name="target";
br;
label #"target-label" for="target" { "Target temperature in °C" };
label #target-label for="target" { "Target temperature in °C" };
br;
button #"set-target" { "Set" };
button #set-target { "Set" };
};
};
};
@@ -231,10 +232,10 @@ fn index() -> impl IntoResponse {
div .opaque { p .intro { "Beta version of ESP32C3 based Wifi extension to the Wallas 361062 Control Panel for the DT/GB Heaters" } }
div .opaque { p #graph { "Waiting for data ..." } }
div .opaque { p #latest { "Waiting for latest reading ..." } }
button #"button-start" .button { "Start heater" }
button #"button-stop" .button { "Stop heater" }
button #"button-ventilate" .button { "Start ventilator" }
button #"button-target" .button { "Set target temperature" }
button #button-start .button { "Start heater" }
button #button-stop .button { "Stop heater" }
button #button-ventilate .button { "Start ventilator" }
button #button-target .button { "Set target temperature" }
})
}

View File

@@ -8,14 +8,11 @@ extern crate alloc;
use heapless::String;
use esp_hal::rng::Rng;
use esp_hal::timer::timg::TimerGroup;
use esp_hal::clock::CpuClock;
/**
* Embassy includes
*/
use esp_hal_embassy::init as initialize_embassy;
use esp_hal_embassy::main;
use embassy_executor::Spawner;
/**
@@ -76,8 +73,9 @@ const SNTP_SOCKETS: usize = 1;
const DNS_SOCKETS: usize = 1;
const MAX_CONCURRENT_SOCKETS: usize = HTTPD_SOCKETS + DHCP_SOCKETS + DNS_SOCKETS + SNTP_SOCKETS;
// esp_bootloader_esp_idf::esp_app_desc!();
#[main]
#[esp_rtos::main]
async fn main(spawner: Spawner) {
info!("booting firmware version {}", VERSION);
@@ -92,28 +90,20 @@ async fn main(spawner: Spawner) {
async fn main_fallible(
spawner: Spawner,
) -> Result<(), Error> {
let peripherals = esp_hal::init({
let mut config = esp_hal::Config::default();
config.cpu_clock = CpuClock::max();
config
});
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
let peripherals = esp_hal::init(config);
esp_alloc::heap_allocator!(HEAP_MEMORY_SIZE);
esp_alloc::heap_allocator!(size: HEAP_MEMORY_SIZE);
esp_println::logger::init_logger_from_env();
// let systimer = SystemTimer::new(peripherals.SYSTIMER).split::<Target>();
let tmg1 = TimerGroup::new(peripherals.TIMG1);
initialize_embassy(tmg1.timer0);
let rng = Rng::new();
let rng = Rng::new(peripherals.RNG);
let ssid = String::<32>::try_from(WIFI_SSID).map_err(|()| Error::ParseCredentials)?;
let ssid = String::<32>::try_from(WIFI_SSID).map_err(|_| Error::ParseCredentials)?;
let password =
String::<64>::try_from(WIFI_PASSWORD).map_err(|()| Error::ParseCredentials)?;
String::<64>::try_from(WIFI_PASSWORD).map_err(|_| Error::ParseCredentials)?;
let tmg0 = TimerGroup::new(peripherals.TIMG0);
let stack = connect_to_wifi(spawner, tmg0, rng, peripherals.WIFI, peripherals.RADIO_CLK, (ssid, password)).await.unwrap();
let stack = connect_to_wifi(spawner, peripherals.TIMG1, peripherals.SW_INTERRUPT, peripherals.WIFI, rng, (ssid, password)).await.unwrap();
let _ = httpd_spawn(spawner, HTTPD_SOCKETS, stack);

View File

@@ -40,9 +40,9 @@ type DomainCommandChannel = PubSubChannel<CriticalSectionRawMutex, DomainCommand
pub static DOMAIN_COMMAND_CHANNEL: DomainCommandChannel = DomainCommandChannel::new();
pub fn serial_spawn(spawner: embassy_executor::Spawner, peri_uart: AnyUart) {
pub fn serial_spawn(spawner: embassy_executor::Spawner, peri_uart: AnyUart<'static>) {
// Initialize and configure UART0
let config = Config::default().with_rx_fifo_full_threshold(BUFFER_SIZE as u16);
let config = Config::default();
// removed rx_pin, tx_pin
let my_uart = Uart::new(peri_uart, config).unwrap().into_async();
// Split UART0 to create seperate Tx and Rx handles

View File

@@ -1,36 +1,27 @@
// Copyright Claudio Mattera 2024.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//! Functions and task for WiFi connection
use alloc::string::ToString;
use log::debug;
use log::error;
use log::info;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_executor::Spawner;
use embassy_net::new as new_network_stack;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::signal::Signal;
use esp_wifi::init as initialize_wifi;
use esp_wifi::wifi::new_with_mode as new_wifi_with_mode;
use esp_wifi::wifi::wifi_state;
use esp_wifi::wifi::ClientConfiguration;
use esp_wifi::wifi::Configuration;
use esp_wifi::wifi::WifiController;
use esp_wifi::wifi::WifiDevice;
use esp_wifi::wifi::WifiError as EspWifiError;
use esp_wifi::wifi::WifiEvent;
use esp_wifi::wifi::WifiStaDevice;
use esp_wifi::wifi::WifiState;
use esp_wifi::EspWifiController;
use esp_wifi::InitializationError as WifiInitializationError;
#[cfg(target_arch = "riscv32")]
use esp_hal::interrupt::software::SoftwareInterruptControl;
use esp_radio::{
Controller,
wifi::{
ClientConfig,
ModeConfig,
WifiController,
WifiDevice,
WifiEvent,
WifiStaState,
WifiError,
},
};
use embassy_net::Config;
use embassy_net::DhcpConfig;
use embassy_net::Runner;
@@ -40,11 +31,10 @@ use embassy_net::StackResources;
use embassy_time::Duration;
use embassy_time::Timer;
use esp_hal::peripherals::RADIO_CLK;
use esp_hal::peripherals::TIMG0;
use esp_hal::peripherals::WIFI;
use esp_hal::peripherals::{WIFI, SW_INTERRUPT};
use esp_hal::rng::Rng;
use esp_hal::timer::timg::TimerGroup;
use esp_hal::timer::timg::TimerGroupInstance;
// use esp_hal::Blocking;
use heapless::String;
@@ -62,34 +52,46 @@ static STACK_COUNT : usize = super::MAX_CONCURRENT_SOCKETS;
static STACK_RESOURCES: StaticCell<StackResources<STACK_COUNT>> = StaticCell::new();
/// Static cell for WiFi controller
static WIFI_CONTROLLER: StaticCell<EspWifiController<'static>> = StaticCell::new();
static WIFI_CONTROLLER: StaticCell<Controller<'static>> = StaticCell::new();
/// Signal to request to stop WiFi
pub static STOP_WIFI_SIGNAL: Signal<CriticalSectionRawMutex, ()> = Signal::new();
/// Connect to WiFi
pub async fn connect(
pub async fn connect<T>(
spawner: Spawner,
timg0: TimerGroup<TIMG0>,
timer1: T,
interrupt: SW_INTERRUPT<'static>,
wifi: WIFI<'static>,
rng: Rng,
wifi: WIFI,
radio_clock_control: RADIO_CLK,
(ssid, password): (String<32>, String<64>),
) -> Result<Stack<'static>, Error> {
) -> Result<Stack<'static>, WifiError>
where
T: TimerGroupInstance + 'static,
{
let mut rng_wrapper = RngWrapper::from(rng);
let seed = rng_wrapper.next_u64();
debug!("Use random seed 0x{seed:016x}");
let wifi_controller = initialize_wifi(timg0.timer0, rng, radio_clock_control)?;
let wifi_controller: &'static mut _ = WIFI_CONTROLLER.init(wifi_controller);
let (wifi_interface, controller) = new_wifi_with_mode(wifi_controller, wifi, WifiStaDevice)?;
let timg0 = TimerGroup::new(timer1);
#[cfg(target_arch = "riscv32")]
let sw_int = SoftwareInterruptControl::new(interrupt);
esp_rtos::start(
timg0.timer0,
#[cfg(target_arch = "riscv32")]
sw_int.software_interrupt0,
);
let controller = WIFI_CONTROLLER.init(esp_radio::init().unwrap());
let (controller, interfaces) = esp_radio::wifi::new(controller, wifi, Default::default()).unwrap();
let wifi_interface = interfaces.sta;
let config = Config::dhcpv4(DhcpConfig::default());
debug!("Initialize network stack");
let stack_resources: &'static mut _ = STACK_RESOURCES.init(StackResources::new());
let (stack, runner) = new_network_stack(wifi_interface, config, stack_resources, seed);
let (stack, runner) = embassy_net::new(wifi_interface, config, stack_resources, seed);
spawner.must_spawn(connection(controller, ssid, password));
spawner.must_spawn(net_task(runner));
@@ -116,7 +118,7 @@ pub async fn connect(
/// Task for ongoing network processing
#[embassy_executor::task]
async fn net_task(mut runner: Runner<'static, WifiDevice<'static, WifiStaDevice>>) {
async fn net_task(mut runner: Runner<'static, WifiDevice<'static>>) {
runner.run().await;
}
@@ -135,23 +137,23 @@ async fn connection_fallible(
mut controller: WifiController<'static>,
ssid: String<32>,
password: String<64>,
) -> Result<(), Error> {
) -> Result<(), WifiError> {
debug!("Start connection");
debug!("Device capabilities: {:?}", controller.capabilities());
loop {
if wifi_state() == WifiState::StaConnected {
if esp_radio::wifi::sta_state() == WifiStaState::Connected {
// wait until we're no longer connected
controller.wait_for_event(WifiEvent::StaDisconnected).await;
Timer::after(Duration::from_millis(5000)).await;
}
if !matches!(controller.is_started(), Ok(true)) {
let client_config = Configuration::Client(ClientConfiguration {
ssid: ssid.clone(),
password: password.clone(),
..Default::default()
});
controller.set_configuration(&client_config)?;
let client_config = ModeConfig::Client(
ClientConfig::default()
.with_ssid(ssid.clone().to_string())
.with_password(password.clone().to_string()),
);
controller.set_config(&client_config)?;
debug!("Starting WiFi controller");
controller.start_async().await?;
debug!("WiFi controller started");
@@ -180,6 +182,7 @@ async fn connection_fallible(
Ok(())
}
/*
/// Error within WiFi connection
#[derive(Debug)]
pub enum Error {
@@ -201,3 +204,4 @@ impl From<EspWifiError> for Error {
Self::Wifi(error)
}
}
*/