From 38217a1ee50f4b4b3e0113850e3317d77aa97076 Mon Sep 17 00:00:00 2001 From: Jack Hogan Date: Wed, 11 Sep 2024 14:01:42 -0400 Subject: [PATCH] Dumped in so much code --- Cargo.toml | 98 +++++++++++++++++----------- build.rs | 4 +- src/eeprom.rs | 64 +++++++++--------- src/main.rs | 176 +++++++++++++++++++++++++++++++++++++------------- 4 files changed, 231 insertions(+), 111 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 07e2469..5729045 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,45 +1,69 @@ [package] -name = "sign-firmware" +name = "dummy" version = "0.1.0" authors = ["Jack Hogan "] edition = "2021" -resolver = "2" -rust-version = "1.77" - -[[bin]] -name = "sign-firmware" -harness = false # do not use the built in cargo test harness -> resolve rust-analyzer errors - -[profile.release] -opt-level = "s" - -[profile.dev] -debug = true # Symbols are nice and they don't increase the size on Flash -opt-level = "z" - -[features] -default = ["std", "embassy", "esp-idf-svc/native", "nightly"] - -pio = ["esp-idf-svc/pio"] -std = ["alloc", "esp-idf-svc/binstart", "esp-idf-svc/std"] -alloc = ["esp-idf-svc/alloc"] -nightly = ["esp-idf-svc/nightly"] -experimental = ["esp-idf-svc/experimental"] -embassy = [ - "esp-idf-svc/embassy-sync", - "esp-idf-svc/critical-section", - "esp-idf-svc/embassy-time-driver", -] +license = "MIT OR Apache-2.0" [dependencies] -log = { version = "0.4", default-features = false } -esp-idf-svc = { version = "0.49", default-features = false } -palette = "0.7.6" -bincode = { version = "2.0.0-rc.3", features = ["derive"] } -anyhow = "1.0.87" -toml-cfg = "0.2.0" -embassy-time = "0.3.2" +esp-backtrace = { version = "0.14.0", features = [ + "esp32s3", + "exception-handler", + "panic-handler", + "println", +] } +esp-hal = { version = "0.20.1", features = ["esp32s3"] } +esp-println = { version = "0.11.0", features = ["esp32s3", "log"] } +log = { version = "0.4.21" } +esp-alloc = { version = "0.4.0" } +embedded-io = "0.6.1" +esp-wifi = { version = "0.8.0", features = [ + "esp32s3", + "phy-enable-usb", + "utils", + "wifi", +] } +heapless = { version = "0.8.0", default-features = false } +smoltcp = { version = "0.11.0", default-features = false, features = [ + "medium-ethernet", + "proto-dhcpv4", + "proto-igmp", + "proto-ipv4", + "socket-dhcpv4", + "socket-icmp", + "socket-raw", + "socket-tcp", + "socket-udp", +] } +embassy-executor = { version = "0.6.0", features = ["task-arena-size-12288"] } +embassy-futures = "0.1.1" +# embassy-net = { version = "0.4.0", features = ["tcp", "udp", "dhcpv4"] } embassy-sync = "0.6.0" +embassy-time = "0.3.1" +embassy-time-driver = { version = "0.1.0", optional = true } +embedded-hal = "1.0.0" +embedded-hal-02 = { version = "0.2.7", package = "embedded-hal", features = [ + "unproven", +] } +embedded-hal-async = "1.0.0" +embedded-hal-bus = "0.2.0" +embedded-io-async = "0.6.1" +embedded-storage = "0.3.1" +anyhow = { version = "1.0.87", default-features = false } +palette = { version = "0.7.6", default-features = false, features = ["libm"] } +bincode = { version = "2.0.0-rc.3", default-features = false, features = [ + "derive", +] } +[profile.dev] +# Rust debug is too slow. +# For debug builds always builds with some optimization +opt-level = "s" -[build-dependencies] -embuild = "0.32.0" +[profile.release] +codegen-units = 1 # LLVM can perform better optimizations using a single thread +debug = 2 +debug-assertions = false +incremental = false +lto = 'fat' +opt-level = 's' +overflow-checks = false diff --git a/build.rs b/build.rs index 112ec3f..9c94ad6 100644 --- a/build.rs +++ b/build.rs @@ -1,3 +1,5 @@ fn main() { - embuild::espidf::sysenv::output(); + println!("cargo:rustc-link-arg-bins=-Tlinkall.x"); + + println!("cargo:rustc-link-arg-bins=-Trom_functions.x"); } diff --git a/src/eeprom.rs b/src/eeprom.rs index 078d3ae..3e58d7b 100644 --- a/src/eeprom.rs +++ b/src/eeprom.rs @@ -1,8 +1,8 @@ // use super::ceil; use core::mem::size_of; use embassy_time::{Duration, Timer}; -use esp_idf_svc::hal::spi::{SpiDeviceDriver, SpiDriver}; use log::info; +use palette::num::Round; const READ_INSTRUCTION: u8 = 0b0000_0011; const WRITE_INSTRUCTION: u8 = 0b0000_0010; @@ -19,8 +19,14 @@ const CONFIG_VERSION: u8 = 1; const DELAY: Duration = Duration::from_millis(10); -pub struct Eeprom<'a> { - spi: SpiDeviceDriver<'a, SpiDriver<'a>>, +trait Spi { + fn write(&mut self, data: &[u8]) -> anyhow::Result<()>; + + fn read(&mut self, data: &mut [u8]) -> anyhow::Result<()>; +} + +pub struct Eeprom { + spi: S, pub metadata: Metadata, } @@ -44,40 +50,40 @@ const BINCODE_CONFIG: bincode::config::Configuration .with_big_endian() .with_variable_int_encoding(); -impl<'a> Eeprom<'a> { - pub async fn from_spi(spi: SpiDeviceDriver<'a, SpiDriver<'a>>) -> anyhow::Result { - let mut eeprom = Self { - spi, - metadata: Default::default(), - }; +impl Eeprom { + // pub async fn from_spi(spi: SpiDeviceDriver<'a, SpiDriver<'a>>) -> anyhow::Result { + // let mut eeprom = Self { + // spi, + // metadata: Default::default(), + // }; - eeprom.write_status(0).await?; + // eeprom.write_status(0).await?; - info!( - "Read status register: 0b{:08b}", - eeprom.read_status().await? - ); + // info!( + // "Read status register: 0b{:08b}", + // eeprom.read_status().await? + // ); - eeprom.assert_read_write_works().await?; + // eeprom.assert_read_write_works().await?; - let mut metadata = [0x0; size_of::()]; + // let mut metadata = [0x0; size_of::()]; - eeprom - .read_bytes(METADATA_BLOCK_START, &mut metadata) - .await?; + // eeprom + // .read_bytes(METADATA_BLOCK_START, &mut metadata) + // .await?; - let (metadata, _) = bincode::decode_from_slice::(&metadata, BINCODE_CONFIG) - .expect("decode metadata"); + // let (metadata, _) = bincode::decode_from_slice::(&metadata, BINCODE_CONFIG) + // .expect("decode metadata"); - if metadata.config_version != CONFIG_VERSION { - eeprom.erase().await?; - eeprom.write_config().await?; - } else { - eeprom.metadata = metadata; - } + // if metadata.config_version != CONFIG_VERSION { + // eeprom.erase().await?; + // eeprom.write_config().await?; + // } else { + // eeprom.metadata = metadata; + // } - Ok(eeprom) - } + // Ok(eeprom) + // } async fn write_config(&mut self) -> anyhow::Result<()> { let mut metadata = [0x0_u8; size_of::()]; diff --git a/src/main.rs b/src/main.rs index 55df609..e3e7b49 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,58 +1,146 @@ -use embassy_time::Timer; -use esp_idf_svc::{ - hal::{ - delay::FreeRtos, - prelude::Peripherals, - task::{self, block_on}, - }, - wifi::{ - AsyncWifi, AuthMethod, ClientConfiguration, Configuration, EspWifi, PmfConfiguration, - ScanMethod, - }, +#![no_std] +#![no_main] + +use esp_backtrace as _; +use esp_hal::{ + clock::ClockControl, delay::Delay, peripherals::Peripherals, prelude::*, system::SystemControl, }; -use sign_firmware::{Block, Leds}; - -#[toml_cfg::toml_config] -pub struct Config { - #[default("")] - wifi_ssid: &'static str, - #[default("")] - wifi_username: &'static str, - #[default("")] - wifi_password: &'static str, + +extern crate alloc; +use core::mem::MaybeUninit; + +#[global_allocator] +static ALLOCATOR: esp_alloc::EspHeap = esp_alloc::EspHeap::empty(); + +fn init_heap() { + const HEAP_SIZE: usize = 32 * 1024; + static mut HEAP: MaybeUninit<[u8; HEAP_SIZE]> = MaybeUninit::uninit(); + + unsafe { + ALLOCATOR.init(HEAP.as_mut_ptr() as *mut u8, HEAP_SIZE); + } } -fn main() { - // It is necessary to call this function once. Otherwise some patches to the runtime - // implemented by esp-idf-sys might not link properly. See https://github.com/esp-rs/esp-idf-template/issues/71 - esp_idf_svc::sys::link_patches(); +static mut APP_CORE_STACK: Stack<8192> = Stack::new(); + +/// Waits for a message that contains a duration, then flashes a led for that +/// duration of time. +#[embassy_executor::task] +async fn control_led( + mut led: Output<'static>, + control: &'static Signal, +) { + println!("Starting control_led() on core {}", get_core() as usize); + loop { + if control.wait().await { + esp_println::println!("LED on"); + led.set_low(); + } else { + esp_println::println!("LED off"); + led.set_high(); + } + } +} - // Bind the log crate to the ESP Logging facilities - esp_idf_svc::log::EspLogger::initialize_default(); +/// Sends periodic messages to control_led, enabling or disabling it. +#[embassy_executor::task] +async fn enable_disable_led(control: &'static Signal) { + println!( + "Starting enable_disable_led() on core {}", + get_core() as usize + ); + let mut ticker = Ticker::every(Duration::from_secs(1)); + loop { + esp_println::println!("Sending LED on"); + control.signal(true); + ticker.next().await; - block_on(amain()); + esp_println::println!("Sending LED off"); + control.signal(false); + ticker.next().await; + } } -async fn amain() { - let Ok(mut leds) = Leds::create() else { - log::error!("LEDs are fucked up, goodbye."); +#[entry] +fn main() -> ! { + init_heap(); - panic!() - }; + let peripherals = esp_hal::init(esp_hal::Config::default()); - log::info!("Hello, world!"); + let sw_ints = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT); - // leds.set_color(palette::Srgb::new(255, 255, 255), Block::Center); + let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - loop { - Timer::after_millis(100).await - } + let timg0 = TimerGroup::new(peripherals.TIMG0); + let timer0: ErasedTimer = timg0.timer0.into(); + let timer1: ErasedTimer = timg0.timer1.into(); + esp_hal_embassy::init([timer0, timer1]); + + let _init = esp_wifi::initialize( + esp_wifi::EspWifiInitFor::Wifi, + timg0.timer0, + esp_hal::rng::Rng::new(peripherals.RNG), + peripherals.RADIO_CLK, + &clocks, + ) + .unwrap(); + + let mut cpu_control = CpuControl::new(peripherals.CPU_CTRL); + + static LED_CTRL: StaticCell> = StaticCell::new(); + let led_ctrl_signal = &*LED_CTRL.init(Signal::new()); + + let led = Output::new(io.pins.gpio0.degrade(), Level::Low); + + static EXECUTOR_CORE_1: StaticCell> = StaticCell::new(); + let executor_core1 = InterruptExecutor::new(sw_ints.software_interrupt1); + let executor_core1 = EXECUTOR_CORE_1.init(executor_core1); + + let _guard = cpu_control + .start_app_core(unsafe { &mut *addr_of_mut!(APP_CORE_STACK) }, move || { + let spawner = executor_core1.start(Priority::Priority1); + + spawner.spawn(control_led(led, led_ctrl_signal)).ok(); + + // Just loop to show that the main thread does not need to poll the executor. + loop {} + }) + .unwrap(); + + static EXECUTOR_CORE_0: StaticCell> = StaticCell::new(); + let executor_core0 = InterruptExecutor::new(sw_ints.software_interrupt0); + let executor_core0 = EXECUTOR_CORE_0.init(executor_core0); + + let spawner = executor_core0.start(Priority::Priority1); + spawner.spawn(enable_disable_led(led_ctrl_signal)).ok(); + + // Just loop to show that the main thread does not need to poll the executor. + loop {} } -async fn connect_to_wifi( - wifi: &mut AsyncWifi>, - cfg: &Config, -) -> anyhow::Result<()> { - // esp_idf_svc::sys::esp_eap_client_set_identity(); - Ok(()) +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let system = SystemControl::new(peripherals.SYSTEM); + + let clocks = ClockControl::max(system.clock_control).freeze(); + let delay = Delay::new(&clocks); + init_heap(); + + esp_println::logger::init_logger_from_env(); + + let timg0 = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG0, &clocks); + let _init = esp_wifi::initialize( + esp_wifi::EspWifiInitFor::Wifi, + timg0.timer0, + esp_hal::rng::Rng::new(peripherals.RNG), + peripherals.RADIO_CLK, + &clocks, + ) + .unwrap(); + + loop { + log::info!("Hello world!"); + delay.delay(500.millis()); + } }