Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pigg_669 #886

Merged
merged 19 commits into from
Mar 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Expand Down
5 changes: 4 additions & 1 deletion dist-workspace.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
2 changes: 1 addition & 1 deletion pigdef/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand Down
38 changes: 25 additions & 13 deletions porky/.cargo/config.toml
Original file line number Diff line number Diff line change
@@ -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"
16 changes: 12 additions & 4 deletions porky/BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 4 additions & 5 deletions porky/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand All @@ -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
Expand All @@ -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 }

Expand Down
4 changes: 2 additions & 2 deletions porky/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Binary file modified porky/assets/43439A0.bin
Binary file not shown.
Binary file modified porky/assets/43439A0_clm.bin
Binary file not shown.
2 changes: 1 addition & 1 deletion porky/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion porky/memory2.x
Original file line number Diff line number Diff line change
@@ -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
Expand Down
26 changes: 20 additions & 6 deletions porky/src/flash.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand All @@ -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
Expand Down Expand Up @@ -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<DbFlash<Flash<'static, FLASH, Blocking, FLASH_SIZE>>, NoopRawMutex> {
) -> Database<DbFlash<Flash<'static, FLASH, Blocking, FLASH_SIZE>>, 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<Flash<_, _, FLASH_SIZE>> = 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
}
16 changes: 8 additions & 8 deletions porky/src/persistence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<DbFlash<Flash<'p, FLASH, Blocking, { flash::FLASH_SIZE }>>, NoopRawMutex>,
pub async fn get_config(
db: &Database<DbFlash<Flash<'_, FLASH, Blocking, { flash::FLASH_SIZE }>>, NoopRawMutex>,
) -> HardwareConfig {
let mut pin_functions: FnvIndexMap<BCMPinNumber, PinFunction, 32> = FnvIndexMap::new();
let mut buf: [u8; 1024] = [0; 1024];
Expand All @@ -56,8 +56,8 @@ pub async fn get_config<'p>(
HardwareConfig { pin_functions }
}

pub async fn store_config_change<'p>(
db: &Database<DbFlash<Flash<'p, FLASH, Blocking, { flash::FLASH_SIZE }>>, NoopRawMutex>,
pub async fn store_config_change(
db: &Database<DbFlash<Flash<'_, FLASH, Blocking, { flash::FLASH_SIZE }>>, NoopRawMutex>,
hardware_config_message: &HardwareConfigMessage,
) -> Result<(), &'static str> {
let mut buf: [u8; 1024] = [0; 1024];
Expand Down Expand Up @@ -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<DbFlash<Flash<'p, FLASH, Blocking, { flash::FLASH_SIZE }>>, NoopRawMutex>,
pub async fn store_ssid_spec(
db: &Database<DbFlash<Flash<'_, FLASH, Blocking, { flash::FLASH_SIZE }>>, NoopRawMutex>,
ssid_spec: SsidSpec,
) -> Result<(), &'static str> {
let mut buf: [u8; 1024] = [0; 1024];
Expand All @@ -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<DbFlash<Flash<'p, FLASH, Blocking, { flash::FLASH_SIZE }>>, NoopRawMutex>,
pub async fn delete_ssid_spec(
db: &Database<DbFlash<Flash<'_, FLASH, Blocking, { flash::FLASH_SIZE }>>, NoopRawMutex>,
) -> Result<(), &'static str> {
let mut wtx = db.write_transaction().await;
wtx.delete(SSID_SPEC_KEY)
Expand Down
10 changes: 10 additions & 0 deletions porky/src/porky.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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<PIO0>;
Expand Down Expand Up @@ -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")]
Expand All @@ -256,6 +265,7 @@ async fn main(spawner: Spawner) {
Database<DbFlash<Flash<'static, FLASH, Blocking, { flash::FLASH_SIZE }>>, 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();
Expand Down
2 changes: 1 addition & 1 deletion porky/src/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<'_>,
Expand Down
2 changes: 1 addition & 1 deletion porky/src/usb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, In>, Endpoint<'static, USB, Out>>,
hw_config: &mut HardwareConfig,
Expand Down
Loading