improved hardware init

This commit is contained in:
Djeeberjr 2025-10-27 15:15:01 +01:00
parent 16ea1db55f
commit d63e9e964d
5 changed files with 116 additions and 105 deletions

1
Cargo.lock generated
View File

@ -1156,6 +1156,7 @@ dependencies = [
"smart-leds", "smart-leds",
"smoltcp", "smoltcp",
"static_cell", "static_cell",
"thiserror",
] ]
[[package]] [[package]]

View File

@ -50,6 +50,7 @@ smart-leds = "0.4.0"
embedded-sdmmc = "0.8.0" embedded-sdmmc = "0.8.0"
embedded-hal-bus = "0.3.0" embedded-hal-bus = "0.3.0"
thiserror = { version = "2.0.17", default-features = false }
[profile.dev] [profile.dev]
# Rust debug is too slow. # Rust debug is too slow.

View File

@ -1,4 +1,5 @@
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use esp_hal::gpio::{AnyPin, Output};
use esp_hal::peripherals; use esp_hal::peripherals;
use esp_hal_smartled::SmartLedsAdapterAsync; use esp_hal_smartled::SmartLedsAdapterAsync;
use log::debug; use log::debug;
@ -26,10 +27,9 @@ const LED_LEVEL: u8 = 255;
#[embassy_executor::task] #[embassy_executor::task]
pub async fn feedback_task( pub async fn feedback_task(
mut led: SmartLedsAdapterAsync<'static, { hardware::LED_BUFFER_SIZE }>, mut led: SmartLedsAdapterAsync<'static, { hardware::LED_BUFFER_SIZE }>,
buzzer: peripherals::GPIO21<'static>, mut buzzer: Output<'static>,
) { ) {
debug!("Starting feedback task"); debug!("Starting feedback task");
let mut buzzer = init::hardware::setup_buzzer(buzzer);
loop { loop {
let feedback_state = FEEDBACK_STATE.wait().await; let feedback_state = FEEDBACK_STATE.wait().await;
match feedback_state { match feedback_state {

View File

@ -1,14 +1,12 @@
use core::cell::RefCell;
use critical_section::Mutex;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_net::Stack; use embassy_net::Stack;
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use esp_hal::Blocking; use esp_hal::Blocking;
use esp_hal::delay::Delay; use esp_hal::delay::Delay;
use esp_hal::gpio::Input; use esp_hal::gpio::{AnyPin};
use esp_hal::i2c::master::Config; use esp_hal::i2c::master::Config;
use esp_hal::peripherals::{ use esp_hal::peripherals::{
GPIO0, GPIO1, GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23, I2C0, RMT, SPI2, GPIO1, GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23, I2C0, RMT, SPI2,
UART1, UART1,
}; };
use esp_hal::rmt::Rmt; use esp_hal::rmt::Rmt;
@ -21,12 +19,12 @@ use esp_hal::{
clock::CpuClock, clock::CpuClock,
gpio::{Output, OutputConfig}, gpio::{Output, OutputConfig},
i2c::master::I2c, i2c::master::I2c,
timer::systimer::SystemTimer,
uart::Uart, uart::Uart,
}; };
use esp_hal_smartled::{SmartLedsAdapterAsync, buffer_size_async}; use esp_hal_smartled::{SmartLedsAdapterAsync, buffer_size_async};
use esp_println::logger::init_logger; use esp_println::logger::init_logger;
use log::{debug, error}; use log::{debug, error};
use thiserror::Error;
use crate::init::network; use crate::init::network;
use crate::init::sd_card::{SDCardPersistence, setup_sdcard}; use crate::init::sd_card::{SDCardPersistence, setup_sdcard};
@ -52,8 +50,6 @@ use crate::init::wifi;
pub const NUM_LEDS: usize = 1; pub const NUM_LEDS: usize = 1;
pub const LED_BUFFER_SIZE: usize = buffer_size_async(NUM_LEDS); pub const LED_BUFFER_SIZE: usize = buffer_size_async(NUM_LEDS);
static SD_DET: Mutex<RefCell<Option<Input>>> = Mutex::new(RefCell::new(None));
#[panic_handler] #[panic_handler]
fn panic(info: &core::panic::PanicInfo) -> ! { fn panic(info: &core::panic::PanicInfo) -> ! {
let delay = Delay::new(); let delay = Delay::new();
@ -64,109 +60,116 @@ fn panic(info: &core::panic::PanicInfo) -> ! {
esp_bootloader_esp_idf::esp_app_desc!(); esp_bootloader_esp_idf::esp_app_desc!();
pub async fn hardware_init( #[derive(Error, Debug)]
spawner: Spawner, pub enum HardwareInitError {
) -> ( #[error("Failed to etup UART")]
Uart<'static, Async>, Uart(#[from] esp_hal::uart::ConfigError),
Stack<'static>,
I2c<'static, Async>,
GPIO21<'static>,
GPIO0<'static>,
SmartLedsAdapterAsync<'static, LED_BUFFER_SIZE>,
SDCardPersistence,
) {
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
let peripherals = esp_hal::init(config);
esp_alloc::heap_allocator!(#[unsafe(link_section = ".dram2_uninit")] size: 65536); #[error("Failed to setup I2C")]
I2C(#[from] esp_hal::i2c::master::ConfigError),
let timg0 = TimerGroup::new(peripherals.TIMG0); #[error("Failed to setup SPI")]
let sw_interrupt = Spi(#[from] esp_hal::spi::master::ConfigError),
esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
esp_rtos::start(timg0.timer0, sw_interrupt.software_interrupt0);
init_logger(log::LevelFilter::Debug); #[error("Failed to setuo LED")]
Led(#[from] esp_hal::rmt::Error),
}
let rng = esp_hal::rng::Rng::new(); pub struct AppHardware {
let network_seed = (rng.random() as u64) << 32 | rng.random() as u64; pub uart: Uart<'static, Async>,
pub network_stack: Stack<'static>,
pub i2c: I2c<'static, Async>,
pub buzzer: Output<'static>,
pub sd_present: AnyPin<'static>,
pub led: SmartLedsAdapterAsync<'static, LED_BUFFER_SIZE>,
pub sdcard: SDCardPersistence,
}
wifi::set_antenna_mode(peripherals.GPIO3, peripherals.GPIO14).await; impl AppHardware {
let interfaces = wifi::setup_wifi(peripherals.WIFI, spawner); pub async fn init(spawner: Spawner) -> Result<Self, HardwareInitError> {
let stack = network::setup_network(network_seed, interfaces.ap, spawner); let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
let peripherals = esp_hal::init(config);
Timer::after(Duration::from_millis(1)).await; esp_alloc::heap_allocator!(#[unsafe(link_section = ".dram2_uninit")] size: 65536);
let uart_device = setup_uart(peripherals.UART1, peripherals.GPIO16, peripherals.GPIO17); let timg0 = TimerGroup::new(peripherals.TIMG0);
let sw_interrupt =
esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
esp_rtos::start(timg0.timer0, sw_interrupt.software_interrupt0);
let i2c_device = setup_i2c(peripherals.I2C0, peripherals.GPIO22, peripherals.GPIO23); init_logger(log::LevelFilter::Debug);
let sd_det_gpio = peripherals.GPIO0; let rng = esp_hal::rng::Rng::new();
let network_seed = (rng.random() as u64) << 32 | rng.random() as u64;
let spi_bus = setup_spi( wifi::set_antenna_mode(peripherals.GPIO3, peripherals.GPIO14).await;
peripherals.SPI2, let interfaces = wifi::setup_wifi(peripherals.WIFI, spawner);
peripherals.GPIO19, let network_stack = network::setup_network(network_seed, interfaces.ap, spawner);
peripherals.GPIO20,
peripherals.GPIO18,
);
let sd_cs_pin = Output::new( Timer::after(Duration::from_millis(1)).await;
peripherals.GPIO2,
esp_hal::gpio::Level::High,
OutputConfig::default(),
);
let vol_mgr = setup_sdcard(spi_bus, sd_cs_pin); let uart_device = setup_uart(peripherals.UART1, peripherals.GPIO16, peripherals.GPIO17)?;
let buzzer_gpio = peripherals.GPIO21; let i2c_device = setup_i2c(peripherals.I2C0, peripherals.GPIO22, peripherals.GPIO23)?;
let led = setup_led(peripherals.RMT, peripherals.GPIO1); let sd_det_gpio = peripherals.GPIO0;
Timer::after(Duration::from_millis(500)).await; let spi_bus = setup_spi(
peripherals.SPI2,
peripherals.GPIO19,
peripherals.GPIO20,
peripherals.GPIO18,
)?;
debug!("hardware init done"); let sd_cs_pin = Output::new(
peripherals.GPIO2,
esp_hal::gpio::Level::High,
OutputConfig::default(),
);
( let vol_mgr = setup_sdcard(spi_bus, sd_cs_pin);
uart_device,
stack, let buzzer_gpio = peripherals.GPIO21;
i2c_device, let buzzer = setup_buzzer(buzzer_gpio);
buzzer_gpio,
sd_det_gpio, let led = setup_led(peripherals.RMT, peripherals.GPIO1)?;
led,
vol_mgr, Timer::after(Duration::from_millis(500)).await;
)
debug!("hardware init done");
Ok(Self {
uart: uart_device,
network_stack,
i2c: i2c_device,
buzzer,
sd_present: sd_det_gpio.into(),
led,
sdcard: vol_mgr,
})
}
} }
fn setup_uart( fn setup_uart(
uart1: UART1<'static>, uart1: UART1<'static>,
uart_tx: GPIO16<'static>, uart_tx: GPIO16<'static>,
uart_rx: GPIO17<'static>, uart_rx: GPIO17<'static>,
) -> Uart<'static, Async> { ) -> Result<Uart<'static, Async>, esp_hal::uart::ConfigError> {
let uard_device = Uart::new(uart1, esp_hal::uart::Config::default().with_baudrate(9600)); let uart_device = Uart::new(uart1, esp_hal::uart::Config::default().with_baudrate(9600))?;
Ok(uart_device.with_rx(uart_rx).with_tx(uart_tx).into_async())
match uard_device {
Ok(block) => block.with_rx(uart_rx).with_tx(uart_tx).into_async(),
Err(e) => {
error!("Failed to initialize UART: {e}");
panic!(); //TODO panic!
}
}
} }
fn setup_i2c( fn setup_i2c(
i2c0: I2C0<'static>, i2c0: I2C0<'static>,
sda: GPIO22<'static>, sda: GPIO22<'static>,
scl: GPIO23<'static>, scl: GPIO23<'static>,
) -> I2c<'static, Async> { ) -> Result<I2c<'static, Async>, esp_hal::i2c::master::ConfigError> {
debug!("init I2C"); debug!("init I2C");
let config = Config::default().with_frequency(Rate::from_khz(400)); let config = Config::default().with_frequency(Rate::from_khz(400));
let i2c = match I2c::new(i2c0, config) {
Ok(i2c) => i2c.with_sda(sda).with_scl(scl).into_async(), let i2c = I2c::new(i2c0, config)?;
Err(e) => {
error!("Failed to initialize I2C: {:?}", e); Ok(i2c.with_sda(sda).with_scl(scl).into_async())
panic!(); //TODO panic!
}
};
i2c
} }
fn setup_spi( fn setup_spi(
@ -174,35 +177,34 @@ fn setup_spi(
sck: GPIO19<'static>, sck: GPIO19<'static>,
miso: GPIO20<'static>, miso: GPIO20<'static>,
mosi: GPIO18<'static>, mosi: GPIO18<'static>,
) -> Spi<'static, Blocking> { ) -> Result<Spi<'static, Blocking>, esp_hal::spi::master::ConfigError> {
let spi = match Spi::new(spi2, Spi_config::default()) { let spi = Spi::new(spi2, Spi_config::default())?;
Ok(spi) => spi.with_sck(sck).with_miso(miso).with_mosi(mosi), Ok(spi.with_sck(sck).with_miso(miso).with_mosi(mosi))
Err(e) => panic!("Failed to initialize SPI: {:?}", e),
};
spi
} }
pub fn setup_buzzer(buzzer_gpio: GPIO21<'static>) -> Output<'static> { pub fn setup_buzzer(buzzer_gpio: GPIO21<'static>) -> Output<'static> {
let config = esp_hal::gpio::OutputConfig::default() let config = esp_hal::gpio::OutputConfig::default()
.with_drive_strength(esp_hal::gpio::DriveStrength::_40mA); .with_drive_strength(esp_hal::gpio::DriveStrength::_40mA);
let buzzer = Output::new(buzzer_gpio, esp_hal::gpio::Level::Low, config);
buzzer Output::new(buzzer_gpio, esp_hal::gpio::Level::Low, config)
} }
fn setup_led<'a>( fn setup_led<'a>(
rmt: RMT<'a>, rmt: RMT<'a>,
led_gpio: GPIO1<'a>, led_gpio: GPIO1<'a>,
) -> esp_hal_smartled::SmartLedsAdapterAsync<'a, LED_BUFFER_SIZE> { ) -> Result<esp_hal_smartled::SmartLedsAdapterAsync<'a, LED_BUFFER_SIZE>, esp_hal::rmt::Error> {
let rmt: Rmt<'_, esp_hal::Async> = { let rmt: Rmt<'_, esp_hal::Async> = {
let frequency: Rate = Rate::from_mhz(80); let frequency: Rate = Rate::from_mhz(80);
Rmt::new(rmt, frequency) Rmt::new(rmt, frequency)
} }?
.expect("Failed to initialize RMT")
.into_async(); .into_async();
let rmt_channel = rmt.channel0; let rmt_channel = rmt.channel0;
let rmt_buffer = [esp_hal::rmt::PulseCode::default(); LED_BUFFER_SIZE]; let rmt_buffer = [esp_hal::rmt::PulseCode::default(); LED_BUFFER_SIZE];
SmartLedsAdapterAsync::new(rmt_channel, led_gpio, rmt_buffer) Ok(SmartLedsAdapterAsync::new(
rmt_channel,
led_gpio,
rmt_buffer,
))
} }

View File

@ -17,7 +17,7 @@ use embassy_sync::{
signal::Signal, signal::Signal,
}; };
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use esp_hal::gpio::Input; use esp_hal::gpio::{AnyPin, Input};
use esp_hal::{gpio::InputConfig, peripherals}; use esp_hal::{gpio::InputConfig, peripherals};
use log::{debug, info}; use log::{debug, info};
use static_cell::StaticCell; use static_cell::StaticCell;
@ -25,7 +25,7 @@ use static_cell::StaticCell;
extern crate alloc; extern crate alloc;
use crate::{ use crate::{
init::sd_card::SDCardPersistence, init::{hardware::AppHardware, sd_card::SDCardPersistence},
store::{IDStore, day::Day, tally_id::TallyID}, store::{IDStore, day::Day, tally_id::TallyID},
webserver::start_webserver, webserver::start_webserver,
}; };
@ -47,36 +47,43 @@ static CHAN: StaticCell<TallyChannel> = StaticCell::new();
#[esp_rtos::main] #[esp_rtos::main]
async fn main(spawner: Spawner) -> ! { async fn main(spawner: Spawner) -> ! {
let (uart_device, stack, i2c, buzzer_gpio, sd_det_gpio, led, persistence_layer) = let app_hardware = AppHardware::init(spawner).await.unwrap();
init::hardware::hardware_init(spawner).await;
info!("Starting up..."); info!("Starting up...");
let mut rtc = drivers::rtc::RTCClock::new(i2c).await; let mut rtc = drivers::rtc::RTCClock::new(app_hardware.i2c).await;
let store: UsedStore = IDStore::new_from_storage(persistence_layer).await; let store: UsedStore = IDStore::new_from_storage(app_hardware.sdcard).await;
let shared_store = Rc::new(Mutex::new(store)); let shared_store = Rc::new(Mutex::new(store));
let chan: &'static mut TallyChannel = CHAN.init(PubSubChannel::new()); let chan: &'static mut TallyChannel = CHAN.init(PubSubChannel::new());
let publisher: TallyPublisher = chan.publisher().unwrap(); let publisher: TallyPublisher = chan.publisher().unwrap();
let mut sub: TallySubscriber = chan.subscriber().unwrap(); let mut sub: TallySubscriber = chan.subscriber().unwrap();
wait_for_stack_up(stack).await; wait_for_stack_up(app_hardware.network_stack).await;
start_webserver(spawner, stack, shared_store.clone(), chan); start_webserver(
spawner,
app_hardware.network_stack,
shared_store.clone(),
chan,
);
/****************************** Spawning tasks ***********************************/ /****************************** Spawning tasks ***********************************/
debug!("spawing NFC reader task..."); debug!("spawing NFC reader task...");
spawner.must_spawn(drivers::nfc_reader::rfid_reader_task( spawner.must_spawn(drivers::nfc_reader::rfid_reader_task(
uart_device, app_hardware.uart,
publisher, publisher,
)); ));
debug!("spawing feedback task.."); debug!("spawing feedback task..");
spawner.must_spawn(feedback::feedback_task(led, buzzer_gpio)); spawner.must_spawn(feedback::feedback_task(
app_hardware.led,
app_hardware.buzzer,
));
debug!("spawn sd detect task"); debug!("spawn sd detect task");
spawner.must_spawn(sd_detect_task(sd_det_gpio)); spawner.must_spawn(sd_detect_task(app_hardware.sd_present));
/******************************************************************************/ /******************************************************************************/
debug!("everything spawned"); debug!("everything spawned");
@ -101,7 +108,7 @@ async fn main(spawner: Spawner) -> ! {
} }
#[embassy_executor::task] #[embassy_executor::task]
async fn sd_detect_task(sd_det_gpio: peripherals::GPIO0<'static>) { async fn sd_detect_task(sd_det_gpio: AnyPin<'static>) {
let mut sd_det = Input::new(sd_det_gpio, InputConfig::default()); let mut sd_det = Input::new(sd_det_gpio, InputConfig::default());
sd_det.wait_for(esp_hal::gpio::Event::AnyEdge).await; sd_det.wait_for(esp_hal::gpio::Event::AnyEdge).await;