main: lots changed, I lost track

This commit is contained in:
2026-03-09 10:31:37 +01:00
parent 4e5f053c18
commit 25a6122d53

View File

@@ -7,8 +7,6 @@
)] )]
use core::{num::{self, Wrapping}, ptr::addr_of_mut};
use alloc::{string::String, sync::Arc}; use alloc::{string::String, sync::Arc};
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_time::{Duration, Instant, Timer, WithTimeout}; use embassy_time::{Duration, Instant, Timer, WithTimeout};
@@ -16,7 +14,7 @@ use embassy_time::{Duration, Instant, Timer, WithTimeout};
use enum_map::EnumMap; use enum_map::EnumMap;
use esp_hal::{gpio::{Output, OutputConfig, Pin}, time::Rate}; use esp_hal::{gpio::{Output, OutputConfig, Pin}, time::Rate};
use esp_hal::{ use esp_hal::{
clock::CpuClock, system::{AppCoreGuard, CpuControl, Stack}, timer::{systimer::SystemTimer, timg::{TimerGroup, Wdt}} clock::CpuClock, timer::{systimer::SystemTimer, timg::{TimerGroup, Wdt}}
}; };
use embassy_sync::{ use embassy_sync::{
@@ -28,13 +26,10 @@ use renderbug_bike::{events::{Prediction, SensorSource, SensorState}, graphics::
use renderbug_bike::events::Measurement; use renderbug_bike::events::Measurement;
use static_cell::StaticCell; use static_cell::StaticCell;
use esp_backtrace as _; use esp_backtrace as _;
use esp_rtos::embassy::{Executor, InterruptExecutor}; use esp_hal::spi::master::any::Degrade;
use esp_hal::interrupt::software::SoftwareInterruptControl;
use renderbug_embassy::tasks::{ use renderbug_bike::tasks::ui::{Ui, ui_main};
motion::motion_task, use esp_hal::dma::DmaChannelConvert;
ui::{Ui, ui_main}
};
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pubsub::DynSubscriber}; use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pubsub::DynSubscriber};
use embassy_sync::channel::Channel; use embassy_sync::channel::Channel;
@@ -48,14 +43,25 @@ esp_bootloader_esp_idf::esp_app_desc!();
#[cfg(feature="radio")] #[cfg(feature="radio")]
static WIFI_INIT: StaticCell<esp_radio::Controller<'static>> = StaticCell::new(); static WIFI_INIT: StaticCell<esp_radio::Controller<'static>> = StaticCell::new();
rtos_trace::global_trace!(Tracer);
#[esp_rtos::main] #[esp_rtos::main]
async fn main(spawner: Spawner) { async fn main(spawner: Spawner) {
esp_alloc::heap_allocator!(size: 128 * 1024); // If we aren't using the second CPU, we can use the bootloader space for the heap instead
if cfg!(not(feature="dual-core")) {
esp_alloc::heap_allocator!(#[esp_hal::ram(reclaimed)] size: 73744);
esp_alloc::heap_allocator!(size: 32 * 1024);
} else {
esp_alloc::heap_allocator!(size: 100000);
}
RenderbugLogger::init_logger(); RenderbugLogger::init_logger();
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
let peripherals = esp_hal::init(config); let peripherals = esp_hal::init(config);
info!("Boot memory stats: {}", esp_alloc::HEAP.stats());
let sys_timer = SystemTimer::new(peripherals.SYSTIMER); let sys_timer = SystemTimer::new(peripherals.SYSTIMER);
esp_rtos::start(sys_timer.alarm0); esp_rtos::start(sys_timer.alarm0);
info!("Embassy initialized!"); info!("Embassy initialized!");
@@ -102,15 +108,15 @@ async fn main(spawner: Spawner) {
let i2c = I2c::new(peripherals.I2C1, Config::default()).unwrap().with_scl(scl).with_sda(sda).into_async(); let i2c = I2c::new(peripherals.I2C1, Config::default()).unwrap().with_scl(scl).with_sda(sda).into_async();
let i2c_bus = I2C_BUS.init(Mutex::new(i2c)); let i2c_bus = I2C_BUS.init(Mutex::new(i2c));
#[cfg(feature="mpu")] #[cfg(feature="mpu")]
spawner.must_spawn(renderbug_embassy::tasks::mpu::mpu_task(motion_bus.dyn_sender(), I2cDevice::new(i2c_bus))); spawner.must_spawn(renderbug_bike::tasks::mpu::mpu_task(motion_bus.dyn_sender(), I2cDevice::new(i2c_bus)));
#[cfg(feature="gps")] #[cfg(feature="gps")]
spawner.must_spawn(renderbug_embassy::tasks::gps::gps_task(motion_bus.dyn_sender(), I2cDevice::new(i2c_bus))); spawner.must_spawn(renderbug_bike::tasks::gps::gps_task(motion_bus.dyn_sender(), I2cDevice::new(i2c_bus)));
} }
#[cfg(feature="oled")] #[cfg(feature="oled")]
{ {
use esp_hal::i2c::master::{Config, I2c}; use esp_hal::i2c::master::{Config, I2c};
use renderbug_embassy::graphics::ssd1306::SsdOutput; use renderbug_bike::graphics::ssd1306::SsdOutput;
let rst = Output::new(peripherals.GPIO21, esp_hal::gpio::Level::Low, OutputConfig::default()); let rst = Output::new(peripherals.GPIO21, esp_hal::gpio::Level::Low, OutputConfig::default());
let i2c = I2c::new( let i2c = I2c::new(
@@ -118,7 +124,7 @@ async fn main(spawner: Spawner) {
Config::default().with_frequency(Rate::from_khz(400)) Config::default().with_frequency(Rate::from_khz(400))
).unwrap().with_scl(peripherals.GPIO18).with_sda(peripherals.GPIO17).into_async(); ).unwrap().with_scl(peripherals.GPIO18).with_sda(peripherals.GPIO17).into_async();
let output = SsdOutput::new(i2c, rst, oled_controls).await; let output = SsdOutput::new(i2c, rst, oled_controls).await;
spawner.must_spawn(renderbug_embassy::tasks::oled_render::oled_render(output, oled_surfaces, oled_uniforms)); spawner.must_spawn(renderbug_bike::tasks::oled_render::oled_render(output, oled_surfaces, oled_uniforms));
} }
let mut storage = renderbug_bike::storage::SharedFlash::new(esp_storage::FlashStorage::new()); let mut storage = renderbug_bike::storage::SharedFlash::new(esp_storage::FlashStorage::new());
@@ -179,13 +185,13 @@ async fn main(spawner: Spawner) {
#[cfg(not(feature="demo"))] #[cfg(not(feature="demo"))]
{ {
info!("Launching motion engine"); info!("Launching motion engine");
spawner.must_spawn(motion_task(motion_bus.dyn_receiver(), predictions.dyn_publisher().unwrap())); spawner.must_spawn(renderbug_bike::tasks::motion::motion_task(motion_bus.dyn_receiver(), predictions.dyn_publisher().unwrap(), recording_bus.dyn_publisher().unwrap()));
} }
#[cfg(feature="demo")] #[cfg(feature="demo")]
{ {
warn!("Launching with demo sequencer"); warn!("Launching with demo sequencer");
spawner.must_spawn(renderbug_embassy::tasks::demo::demo_task(predictions.dyn_publisher().unwrap())); spawner.must_spawn(renderbug_bike::tasks::demo::demo_task(predictions.dyn_publisher().unwrap()));
} }
info!("Launching Safety UI"); info!("Launching Safety UI");
@@ -224,22 +230,31 @@ async fn main(spawner: Spawner) {
info!("Launching core 2 watchdog"); info!("Launching core 2 watchdog");
let timer1 = TimerGroup::new(peripherals.TIMG1); let timer1 = TimerGroup::new(peripherals.TIMG1);
let mut ui_wdt = timer1.wdt; let mut ui_wdt = timer1.wdt;
ui_wdt.set_timeout(esp_hal::timer::timg::MwdtStage::Stage0, esp_hal::time::Duration::from_secs(10)); ui_wdt.set_timeout(esp_hal::timer::timg::MwdtStage::Stage0, esp_hal::time::Duration::from_secs(60));
#[cfg(feature="dual-core")]
ui_wdt.enable(); ui_wdt.enable();
spawner.must_spawn(wdt_task(ui_wdt)); spawner.must_spawn(wdt_task(ui_wdt));
} }
spawner.must_spawn(print_sensor_status(predictions.dyn_subscriber().unwrap())); spawner.must_spawn(print_sensor_status(predictions.dyn_subscriber().unwrap()));
info!("System is ready in {}ms", Instant::now().as_millis()); info!("Ready to rock and roll in {}ms", Instant::now().as_millis());
}; };
#[allow(static_mut_refs)]
#[cfg(feature="dual-core")] #[cfg(feature="dual-core")]
{ {
static mut CORE2_STACK: Stack<16384> = Stack::new(); use core::mem::MaybeUninit;
use esp_hal::interrupt::software::SoftwareInterruptControl;
use esp_hal::system::Stack;
use esp_rtos::embassy::Executor;
// We can be sneaky and stick the stack for the second core into the bootloader ram
#[esp_hal::ram(reclaimed)]
static mut CORE2_STACK: MaybeUninit<Stack<73744>> = MaybeUninit::uninit();
let swi = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT); let swi = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
esp_rtos::start_second_core(peripherals.CPU_CTRL, swi.software_interrupt0, swi.software_interrupt1, unsafe { &mut *addr_of_mut!(CORE2_STACK) }, || { // SAFETY: The internal implementation of Stack is itself MaybeUninit
esp_rtos::start_second_core(peripherals.CPU_CTRL, swi.software_interrupt0, swi.software_interrupt1, unsafe { CORE2_STACK.assume_init_mut() }, || {
info!("Second CPU core started"); info!("Second CPU core started");
static CORE2_EXEC: StaticCell<Executor> = StaticCell::new(); static CORE2_EXEC: StaticCell<Executor> = StaticCell::new();
let exec = CORE2_EXEC.init_with(|| { Executor::new() }); let exec = CORE2_EXEC.init_with(|| { Executor::new() });
@@ -250,7 +265,10 @@ async fn main(spawner: Spawner) {
#[cfg(not(feature="dual-core"))] #[cfg(not(feature="dual-core"))]
core2_main(spawner); core2_main(spawner);
info!("Ready to rock and roll"); loop {
//info!("Memory stats: {}", esp_alloc::HEAP.stats());
Timer::after_secs(1).await;
}
} }
#[embassy_executor::task] #[embassy_executor::task]
@@ -304,7 +322,7 @@ async fn print_sensor_readings(mut events: DynSubscriber<'static, Measurement>)
async fn print_sensor_status(mut events: DynSubscriber<'static, Prediction>) { async fn print_sensor_status(mut events: DynSubscriber<'static, Prediction>) {
info!("telemetry ready"); info!("telemetry ready");
let mut num_events = Wrapping(0usize); let mut sensor_states: EnumMap<SensorSource, SensorState> = EnumMap::default();
loop { loop {
let next = events.next_message_pure().with_timeout(Duration::from_secs(5)).await; let next = events.next_message_pure().with_timeout(Duration::from_secs(5)).await;
match next { match next {