Compare commits
1 Commits
v0.2.1
...
273bf2f946
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
273bf2f946 |
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user