1 Commits

Author SHA1 Message Date
Priec
273bf2f946 dual core setup 2026-01-18 11:20:20 +01:00
5 changed files with 62 additions and 27 deletions

View File

@@ -6,10 +6,13 @@
clippy::mem_forget,
reason = "mem::forget is generally not safe to do with esp_hal types"
)]
// TODO WARNING core 1 should be logic, core 0 wifi, its flipped now
use embassy_executor::Spawner;
use embassy_futures::select::{select3, Either3};
use embassy_net::{Runner, StackResources};
use embassy_sync::signal::Signal;
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_time::{Duration, Timer};
use projekt_final::bus::I2cInner;
@@ -20,6 +23,7 @@ use esp_hal::{
clock::CpuClock,
i2c::master::{Config as I2cConfig, I2c},
rng::Rng,
system::{CpuControl, Stack},
timer::timg::TimerGroup,
};
use esp_wifi::{
@@ -43,6 +47,9 @@ extern crate alloc;
use alloc::format;
static I2C_BUS: StaticCell<RefCell<I2cInner>> = StaticCell::new();
static APP_CORE_STACK: StaticCell<Stack<8192>> = StaticCell::new();
static EXECUTOR_CORE1: StaticCell<esp_hal_embassy::Executor> = StaticCell::new();
static NETWORK_READY: Signal<CriticalSectionRawMutex, ()> = Signal::new();
macro_rules! mk_static {
($t:ty,$val:expr) => {{
@@ -97,21 +104,25 @@ async fn main(spawner: Spawner) -> ! {
let timg1 = TimerGroup::new(peripherals.TIMG1);
esp_hal_embassy::init(timg1.timer0);
let net_config = embassy_net::Config::dhcpv4(Default::default());
let seed = (rng.random() as u64) << 32 | rng.random() as u64;
let (stack, runner) = embassy_net::new(
wifi_interface,
net_config,
mk_static!(StackResources<3>, StackResources::<3>::new()),
seed,
);
// Start core 1 for WiFi and MQTT (network stack created there)
let mut cpu_control = CpuControl::new(peripherals.CPU_CTRL);
let _guard = cpu_control.start_app_core(
APP_CORE_STACK.init(Stack::new()),
move || {
let executor = EXECUTOR_CORE1.init(esp_hal_embassy::Executor::new());
executor.run(|spawner| {
spawner.spawn(core1_network_task(spawner, controller, wifi_interface, seed)).ok();
});
}
).unwrap();
spawner.spawn(connection_task(controller)).expect("spawn connection_task");
spawner.spawn(net_task(runner)).expect("spawn net_task");
wait_for_network(stack).await;
// Wait for network to be ready (signaled from core 1)
NETWORK_READY.wait().await;
info!("Network ready, starting core 0 tasks");
spawner.spawn(mqtt_task(stack)).expect("spawn mqtt_task");
// Core 0: display and MPU tasks
spawner.spawn(display::task::display_task(display_i2c)).expect("spawn display_task");
spawner.spawn(mpu::task::mpu_task(mpu_i2c)).expect("spawn mpu_task");
@@ -156,7 +167,27 @@ async fn main(spawner: Spawner) -> ! {
}
}
async fn wait_for_network(stack: embassy_net::Stack<'static>) {
// Runs on core 1 - creates and owns the network stack
#[embassy_executor::task]
async fn core1_network_task(
spawner: Spawner,
controller: WifiController<'static>,
wifi_interface: WifiDevice<'static>,
seed: u64,
) {
spawner.spawn(connection_task(controller)).ok();
let net_config = embassy_net::Config::dhcpv4(Default::default());
let (stack, runner) = embassy_net::new(
wifi_interface,
net_config,
mk_static!(StackResources<3>, StackResources::<3>::new()),
seed,
);
spawner.spawn(net_task(runner)).ok();
// Wait for network
loop {
if stack.is_link_up() { break; }
Timer::after(Duration::from_millis(500)).await;
@@ -168,6 +199,12 @@ async fn wait_for_network(stack: embassy_net::Stack<'static>) {
}
Timer::after(Duration::from_millis(500)).await;
}
// Signal core 0 that network is ready
NETWORK_READY.signal(());
// Start MQTT on this core (it needs the stack)
spawner.spawn(mqtt_task(stack)).ok();
}
async fn handle_mqtt_message(msg: IncomingMsg) {

View File

@@ -7,17 +7,16 @@ use embedded_hal_bus::i2c::RefCellDevice;
use esp_hal::i2c::master::I2c;
use esp_hal::Async;
/// The underlying I2C peripheral type for esp-hal 1.0.0-rc.0
/// The underlying I2C peripheral type
pub type I2cInner = I2c<'static, Async>;
/// We use RefCell to share the bus on a single core.
/// It's zero-overhead and safe because Embassy tasks don't preempt each other.
/// RefCell to share the bus on a single core.
pub type SharedI2c = RefCell<I2cInner>;
/// A handle to a shared I2C device.
pub type I2cDevice = RefCellDevice<'static, I2cInner>;
/// Create a new I2C device handle from the shared bus.
/// New I2C device handle from the shared bus.
pub fn new_device(bus: &'static SharedI2c) -> I2cDevice {
RefCellDevice::new(bus)
}

View File

@@ -6,7 +6,7 @@
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::channel::{Channel, Receiver, TrySendError};
use heapless::String as HString;
use heapless::String;
use crate::contracts::{DisplayCommand, ImuReading};
@@ -58,14 +58,14 @@ pub async fn show_imu(reading: ImuReading) {
/// Set the status line.
pub async fn set_status(text: &str) {
let mut s = HString::<32>::new();
let mut s = String::<32>::new();
let _ = s.push_str(&text[..text.len().min(32)]);
send(DisplayCommand::SetStatus(s)).await;
}
/// Show an error message.
pub async fn show_error(text: &str) {
let mut s = HString::<64>::new();
let mut s = String::<64>::new();
let _ = s.push_str(&text[..text.len().min(64)]);
send(DisplayCommand::ShowError(s)).await;
}

View File

@@ -6,7 +6,7 @@ use log::{error, info};
use alloc::boxed::Box;
use alloc::format;
use heapless::String as HString;
use heapless::String;
use mousefood::{EmbeddedBackend, EmbeddedBackendConfig};
use ratatui::{
layout::{Constraint, Direction, Layout},
@@ -27,9 +27,9 @@ const REFRESH_INTERVAL_MS: u64 = 100;
/// Internal state for what to render.
struct DisplayState {
status: HString<32>,
status: String<32>,
last_imu: Option<ImuReading>,
last_error: Option<HString<64>>,
last_error: Option<String<64>>,
mqtt_connected: bool,
mqtt_msg_count: u32,
}
@@ -37,7 +37,7 @@ struct DisplayState {
impl Default for DisplayState {
fn default() -> Self {
Self {
status: HString::new(),
status: String::new(),
last_imu: None,
last_error: None,
mqtt_connected: false,
@@ -66,7 +66,7 @@ impl DisplayState {
DisplayCommand::Clear => {
self.last_imu = None;
self.last_error = None;
self.status = HString::new();
self.status = String::new();
}
}
}

View File

@@ -1,6 +1,5 @@
// src/i2c/com.rs
use embassy_executor::task;
use embassy_time::{Duration, Timer};
use esp_hal::{
i2c::master::{Config, I2c},
@@ -9,7 +8,7 @@ use esp_hal::{
use ssd1306::mode::BufferedGraphicsMode;
use log::info;
#[task]
#[embassy_executor::task]
pub async fn display_task() {
use mousefood::{EmbeddedBackend, EmbeddedBackendConfig};
use ratatui::{
@@ -73,7 +72,7 @@ pub async fn display_task() {
}
}
#[task]
#[embassy_executor::task]
pub async fn i2c_check() {
let peripherals = unsafe { Peripherals::steal() };
let mut i2c = I2c::new(peripherals.I2C0, Config::default())