diff --git a/Makefile b/Makefile index c53ccffc5..42bf2dc55 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ $(eval PI = $(shell cat /proc/cpuinfo 2>&1 | grep "Raspberry Pi")) .PHONY: all -all: clippy build build-arm build-porky build-web test +all: clippy format-check build build-arm build-porky build-web test .PHONY: clean clean: @@ -34,6 +34,10 @@ setup: clippy: cargo clippy --tests --no-deps +.PHONY: format-check +format-check: + cargo fmt --all -- --check + .PHONY: build build: cargo build diff --git a/dist-workspace.toml b/dist-workspace.toml index 4ed4b3e21..d64b8d908 100644 --- a/dist-workspace.toml +++ b/dist-workspace.toml @@ -35,7 +35,10 @@ armv7-unknown-linux-musleabihf = "ubuntu-24.04" [[dist.extra-artifacts]] artifacts = [ "porky/target/thumbv6m-none-eabi/release/porky_pico_w.uf2", + "porky/target/thumbv6m-none-eabi/release/porky_pico_w2.uf2", "porky/target/thumbv6m-none-eabi/release/porky_pico.uf2", + "porky/target/thumbv6m-none-eabi/release/porky_pico2.uf2", "70.pigg.rules" ] -build = ["make", "-C", "porky", "install-uf2", "uf2-w", "uf2"] +# For porky binary builds - install the 'elf2uf2-rs' tool, then build the uf2 files for artifacts above +build = ["make", "-C", "porky", "install-uf2", "uf2s"] diff --git a/pigdef/src/config.rs b/pigdef/src/config.rs index 2acd746e3..7700a150b 100644 --- a/pigdef/src/config.rs +++ b/pigdef/src/config.rs @@ -28,7 +28,7 @@ use std::time::Duration; /// [HardwareConfig] captures the current configuration of programmable GPIO pins #[cfg_attr(feature = "std", derive(Debug))] -#[cfg_attr(debug_assertions, derive(PartialEq))] +#[cfg_attr(all(debug_assertions, feature = "std"), derive(PartialEq))] #[derive(Clone, Serialize, Deserialize, Default)] pub struct HardwareConfig { #[cfg(feature = "std")] diff --git a/porky/.cargo/config.toml b/porky/.cargo/config.toml index 5f0a4ce15..0d8e468da 100644 --- a/porky/.cargo/config.toml +++ b/porky/.cargo/config.toml @@ -1,27 +1,39 @@ -[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +# See https://doc.rust-lang.org/cargo/reference/config.html for details of possible config keys and values + # Choose a default "cargo run" tool (see README for more info) -# - `probe-rs` provides flashing and defmt via a hardware debugger, and stack unwind on panic -# - `picotool`- used while the pico2 was lacking probe-rs support -# - elf2uf2-rs loads firmware over USB when the rp2040 is in boot mode -runner = ["probe-rs", +# - probe-rs - provides flashing and defmt via a hardware debugger, and stack unwind on panic +# - picotool - used while the pico2 was lacking probe-rs support +# - runner = "picotool load -u -v -x -t elf" +# - elf2uf2-rs - loads firmware over USB when the rp2040 is in boot mode +# - runner = "elf2uf2-rs -d" + +# Runner to use for pico +[target.thumbv6m-none-eabi] +runner = [ + "probe-rs", "run", "--chip", "RP2040", - # "RP235x", "--protocol", "swd", "--log-format", "{[{L}]%bold} {s} {{c}", "--restore-unwritten" ] -#runner = "picotool load -u -v -x -t elf" -#runner = "elf2uf2-rs -d" -#[build] -# Since we are now switching target between building for Pico and Pico 2 - we cannot have a static target here. -#it is specified on the command line to the compiler from the Makrfile -#target = "thumbv6m-none-eabi" # Pico -#target = "thumbv8m.main-none-eabihf" # Pico 2 +# Runner to use for pico 2 +[target.thumbv8m.main-none-eabihf] +runner = [ + "probe-rs", + "run", + "--chip", + "RP235x", + "--protocol", + "swd", + "--log-format", + "{[{L}]%bold} {s} {{c}", + "--restore-unwritten" +] [env] DEFMT_LOG = "info" diff --git a/porky/BUILDING.md b/porky/BUILDING.md index a97667de0..70262afd1 100644 --- a/porky/BUILDING.md +++ b/porky/BUILDING.md @@ -86,16 +86,24 @@ Wi-Fi network, and the output of its IP and the port it is listening for TCP con ## Creating a UF2 file -Use `make uf2` Makefile target. +The `porky/Makefile` has 5 targets for uf2 files: -This uses [`elf2usb2-rs`](https://github.com/JoNil/elf2uf2-rs). This can be installed using: +- `uf2-w`: Build UF2 file (`target/thumbv6m-none-eabi/release/porky_pico_w.uf2`) for Pico 1 W (Wi-Fi) +- `uf2-w2`: Build UF2 file (`target/thumbv6m-none-eabi/release/porky_pico_w2.uf2`)for Pico 2 W (Wi-Fi) +- `uf2`: Build UF2 file (`target/thumbv6m-none-eabi/release/porky_pico.uf2`) for Pico 1 (no Wi-Fi) +- `uf2-2`: Build UF2 file (`target/thumbv6m-none-eabi/release/porky_pico2.uf2`) for Pico 2 (no Wi-Fi) +- `uf2s`: Build all of the above + +This uses [`elf2usb2-rs`](https://github.com/JoNil/elf2uf2-rs). This can be installed using the `porky/Makefile` target +`install-uf2` or +manually: - `cargo binstall elf2uf2-rs` if you use `cargo binstall` to install a pre-compiled binary - `cargo install elf2uf2-rs` to build it from source and install it -This will produce the file `target/thumbv6m-none-eabi/release/porky_pico_w.uf2` +You can check the generated files using: `file`. -You can check its type using: `file target/thumbv6m-none-eabi/release/porky_pico_w.uf2`: +For example: `file target/thumbv6m-none-eabi/release/porky_pico_w.uf2`: ``` target/thumbv6m-none-eabi/release/porky_pico_w.uf2: UF2 firmware image, family Raspberry Pi RP2040, address 0x10000000, 1608 total blocks diff --git a/porky/Cargo.toml b/porky/Cargo.toml index ba2ad9a6d..bfcd765a1 100644 --- a/porky/Cargo.toml +++ b/porky/Cargo.toml @@ -16,7 +16,7 @@ path = "src/porky.rs" default = [] pico1 = ["embassy-rp/rp2040"] pico2 = ["embassy-rp/rp235xa"] -wifi = ["dep:cyw43", "tcp", "discovery"] +wifi = ["dep:cyw43", "discovery", "tcp"] debug-probe = [] usb = ["pigdef/usb", "dep:embassy-usb"] discovery = ["pigdef/discovery", "dep:edge-mdns", "dep:edge-nal-embassy", "dep:edge-nal"] @@ -28,11 +28,11 @@ pigdef = { path = "../pigdef" } # Embassy Dependencies (crates in https://github.com/embassy-rs/embassy) embassy-time = { version = "0.4.0", default-features = false, features = ["defmt", "defmt-timestamp-uptime"] } embassy-executor = { version = "0.7.0", default-features = false, features = ["task-arena-size-65536", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } -embassy-rp = { version = "0.3.1", default-features = false, features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl"] } +embassy-rp = { version = "0.3", default-features = false, features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl"] } embassy-sync = { version = "0.6.2", default-features = false } embassy-futures = { version = "0.1.1", default-features = false } -# Needed even when no wifi - I don't know why yet. Reported to Embassy +# Needed even when no Wi-Fi - I don't know why yet. Reported to Embassy cyw43-pio = { version = "0.3.0", default-features = false, features = ["defmt"] } # Optional Embassy Dependencies @@ -54,14 +54,13 @@ cortex-m-rt = { version = "0.7.5", default-features = false } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } rand = { version = "0.8.5", default-features = false } -# To convert device_id into hex for use as a string faster-hex = { version = "0.10.0", default-features = false } serde = { version = "1.0.208", default-features = false, features = ["derive"] } postcard = { version = "1.0.10", default-features = false, features = ["heapless"] } heapless = { version = "0.8.0", default-features = false, features = ["serde"] } -edge-mdns = { version = "0.5.0", optional = true, features = ["io"] } +edge-mdns = { version = "0.5.0", default-features = false, optional = true, features = ["io"] } #TODO check out "embassy" https://github.com/ivmarkov/edge-net/issues/63 edge-nal-embassy = { version = "0.5.0", default-features = false, optional = true } edge-nal = { version = "0.5.0", default-features = false, optional = true } diff --git a/porky/Makefile b/porky/Makefile index 7dd4c406d..fe0b2a696 100644 --- a/porky/Makefile +++ b/porky/Makefile @@ -46,7 +46,7 @@ install-uf2: curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash cargo binstall elf2uf2-rs -uf2s: uf2-w uf2-w2 uf2 uf22 +uf2s: uf2-w uf2-w2 uf2 uf2-2 uf2-w: build-w elf2uf2-rs target/thumbv6m-none-eabi/release/porky target/thumbv6m-none-eabi/release/porky_pico_w.uf2 @@ -57,5 +57,5 @@ uf2-w2: build-w2 uf2: build elf2uf2-rs target/thumbv6m-none-eabi/release/porky target/thumbv6m-none-eabi/release/porky_pico.uf2 -uf22: build2 +uf2-2: build2 elf2uf2-rs target/thumbv6m-none-eabi/release/porky target/thumbv6m-none-eabi/release/porky_pico2.uf2 \ No newline at end of file diff --git a/porky/assets/43439A0.bin b/porky/assets/43439A0.bin index 017375277..a05482fe9 100755 Binary files a/porky/assets/43439A0.bin and b/porky/assets/43439A0.bin differ diff --git a/porky/assets/43439A0_clm.bin b/porky/assets/43439A0_clm.bin index 1fedd753a..dc4ee0252 100755 Binary files a/porky/assets/43439A0_clm.bin and b/porky/assets/43439A0_clm.bin differ diff --git a/porky/build.rs b/porky/build.rs index 09e929a7e..a702f0a49 100644 --- a/porky/build.rs +++ b/porky/build.rs @@ -84,7 +84,7 @@ fn main() -> io::Result<()> { #[cfg(feature = "pico1")] file.write_all(include_bytes!("memory1.x"))?; #[cfg(feature = "pico2")] - file.write_all(include_bytes!("memory2.x")).unwrap(); + file.write_all(include_bytes!("memory2.x"))?; println!("cargo:rustc-link-search={}", out.display()); println!("cargo:rerun-if-changed={}", SSID_FILE_NAME); diff --git a/porky/memory2.x b/porky/memory2.x index 5f4a57a0f..2891c87b7 100644 --- a/porky/memory2.x +++ b/porky/memory2.x @@ -1,5 +1,5 @@ MEMORY { - FLASH : ORIGIN = 0x10000000, LENGTH = 1024K + FLASH : ORIGIN = 0x10000000, LENGTH = 2048K CONFIG : ORIGIN = ORIGIN(FLASH) + LENGTH(FLASH), LENGTH = 256K RAM : ORIGIN = 0x20000000, LENGTH = 512K SRAM4 : ORIGIN = 0x20080000, LENGTH = 4K diff --git a/porky/src/flash.rs b/porky/src/flash.rs index 030db8e1f..872828b33 100644 --- a/porky/src/flash.rs +++ b/porky/src/flash.rs @@ -1,6 +1,6 @@ #[cfg(feature = "pico1")] use core::str; -use defmt::info; +use defmt::{error, info}; use ekv::flash::{self, PageID}; use ekv::{config, Database}; use embassy_rp::flash::{Blocking, Flash}; @@ -13,7 +13,13 @@ use faster_hex::hex_encode; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; +#[cfg(not(any(feature = "pico1", feature = "pico2")))] +compile_error!("You must choose either feature \"pico1\" or \"pico2\""); + +#[cfg(all(feature = "pico1", not(feature = "pico2")))] pub const FLASH_SIZE: usize = 2 * 1024 * 1024; +#[cfg(all(feature = "pico2", not(feature = "pico1")))] +pub const FLASH_SIZE: usize = 4 * 1024 * 1024; extern "C" { // Flash storage used for configuration @@ -93,18 +99,26 @@ pub fn get_flash<'a>(flash_pin: FLASH) -> Flash<'a, FLASH, Blocking, FLASH_SIZE> pub async fn db_init( flash: Flash<'static, FLASH, Blocking, FLASH_SIZE>, -) -> Database>, NoopRawMutex> { +) -> Database>, NoopRawMutex>{ + + #[cfg(feature = "pico1")] + const OFFSET: usize = 0x0; + #[cfg(not(feature = "pico1"))] // The start of flash address needs adjusting on pico 2 + const OFFSET: usize = 0x1000_0000; + let flash: DbFlash> = DbFlash { flash, - start: unsafe { &__config_start as *const u32 as usize }, + start: unsafe { &__config_start as *const u32 as usize - OFFSET}, }; let db = Database::<_, NoopRawMutex>::new(flash, ekv::Config::default()); if db.mount().await.is_err() { - info!("Initializing Flash DB..."); - db.format().await.unwrap(); + info!("Formatting Flash DB..."); + match db.format().await { + Ok(..) => info!("Flash Database is up"), + Err(_e) => error!("Error initializing Flash DB"), + } } - info!("Flash Database is up"); db } diff --git a/porky/src/persistence.rs b/porky/src/persistence.rs index 1c7cab9e5..6d455cb9b 100644 --- a/porky/src/persistence.rs +++ b/porky/src/persistence.rs @@ -28,8 +28,8 @@ use pigdef::pin_function::PinFunction::Output; const SSID_SPEC_KEY: &[u8] = b"ssid_spec"; /// Load any pre-existing config from flash, if there is none then just return a default config -pub async fn get_config<'p>( - db: &Database>, NoopRawMutex>, +pub async fn get_config( + db: &Database>, NoopRawMutex>, ) -> HardwareConfig { let mut pin_functions: FnvIndexMap = FnvIndexMap::new(); let mut buf: [u8; 1024] = [0; 1024]; @@ -56,8 +56,8 @@ pub async fn get_config<'p>( HardwareConfig { pin_functions } } -pub async fn store_config_change<'p>( - db: &Database>, NoopRawMutex>, +pub async fn store_config_change( + db: &Database>, NoopRawMutex>, hardware_config_message: &HardwareConfigMessage, ) -> Result<(), &'static str> { let mut buf: [u8; 1024] = [0; 1024]; @@ -130,8 +130,8 @@ pub async fn get_ssid_spec<'a>( #[allow(dead_code)] // Not used in porky #[cfg(feature = "wifi")] /// Write the [SsidSpec] to the flash database -pub async fn store_ssid_spec<'p>( - db: &Database>, NoopRawMutex>, +pub async fn store_ssid_spec( + db: &Database>, NoopRawMutex>, ssid_spec: SsidSpec, ) -> Result<(), &'static str> { let mut buf: [u8; 1024] = [0; 1024]; @@ -147,8 +147,8 @@ pub async fn store_ssid_spec<'p>( #[allow(dead_code)] // Not used in porky #[cfg(feature = "wifi")] /// Delete the [SsidSpec] from the flash database -pub async fn delete_ssid_spec<'p>( - db: &Database>, NoopRawMutex>, +pub async fn delete_ssid_spec( + db: &Database>, NoopRawMutex>, ) -> Result<(), &'static str> { let mut wtx = db.write_transaction().await; wtx.delete(SSID_SPEC_KEY) diff --git a/porky/src/porky.rs b/porky/src/porky.rs index 88433698a..3977e389d 100644 --- a/porky/src/porky.rs +++ b/porky/src/porky.rs @@ -20,6 +20,8 @@ use embassy_executor::Spawner; #[cfg(all(feature = "usb", feature = "wifi"))] use embassy_futures::select::{select, Either}; use embassy_rp::bind_interrupts; +#[cfg(feature = "pico2")] +use embassy_rp::block::ImageDef; use embassy_rp::flash::{Blocking, Flash}; #[cfg(feature = "wifi")] use embassy_rp::gpio::{Level, Output}; @@ -80,6 +82,11 @@ mod mdns; /// The Pi Pico GPIO [PinDefinition]s that get passed to the GUI mod pin_descriptions; +#[cfg(feature = "pico2")] +#[link_section = ".start_block"] +#[used] +pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe(); + #[cfg(feature = "usb")] bind_interrupts!(struct Irqs { PIO0_IRQ_0 => PioInterruptHandler; @@ -241,6 +248,8 @@ async fn main(spawner: Spawner) { // create hardware description #[allow(unused_mut)] let mut flash = flash::get_flash(peripherals.FLASH); + #[cfg(feature = "pico2")] // pico2 needs a delay + embassy_time::Timer::after_millis(10).await; #[cfg(feature = "pico1")] let serial_number = flash::serial_number(&mut flash); #[cfg(feature = "pico2")] @@ -256,6 +265,7 @@ async fn main(spawner: Spawner) { Database>, NoopRawMutex>, > = StaticCell::new(); let db = DATABASE.init(flash::db_init(flash).await); + // TODO log flash/db error here #[cfg(feature = "wifi")] static STATIC_BUF: StaticCell<[u8; 200]> = StaticCell::new(); diff --git a/porky/src/tcp.rs b/porky/src/tcp.rs index 3935bce8c..ea125aab8 100644 --- a/porky/src/tcp.rs +++ b/porky/src/tcp.rs @@ -84,7 +84,7 @@ pub async fn wait_connection<'a>( accept(tcp_socket).await } -pub async fn message_loop<'a>( +pub async fn message_loop( gpio: &mut Gpio, mut socket: TcpSocket<'_>, hw_desc: &HardwareDescription<'_>, diff --git a/porky/src/usb.rs b/porky/src/usb.rs index 78149bf5a..19128fc87 100644 --- a/porky/src/usb.rs +++ b/porky/src/usb.rs @@ -350,7 +350,7 @@ pub async fn wait_connection( /// Enter a loop waiting for messages either via USB (from Piggui) or from the Hardware. /// - When receive a message over USB from Piggui, apply to the hardware, save in Flash /// - WHen receiving from hardware, send the message to Piggui over USB -pub async fn message_loop<'a>( +pub async fn message_loop( gpio: &mut Gpio, usb_connection: &mut UsbConnection, Endpoint<'static, USB, Out>>, hw_config: &mut HardwareConfig,