Skip to content
Open
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
147 changes: 147 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,36 @@ async fn init_project(
chip_or_board.clone()
};

// Ask about embassy-boot (DFU) for RP2040-based chips only.
let mut embassy_boot = false;
let mut flash_size: u32 = 2 * 1024 * 1024; // default 2 MB
if chip_or_board == "rp2040" || chip_or_board == "pico_w" {
embassy_boot = Select::new(
"Use embassy-boot (DFU firmware update via USB)?",
vec!["No", "Yes"],
)
.prompt()?
== "Yes";
if embassy_boot {
flash_size = Select::new(
"Total flash size:",
vec!["2 MB", "4 MB", "8 MB", "16 MB"],
)
.with_help_message(
"When in doubt, use 2 MB. Smaller works on bigger flashes.",
)
.prompt()
.map(|s| match s {
"2 MB" => 2 * 1024 * 1024,
"4 MB" => 4 * 1024 * 1024,
"8 MB" => 8 * 1024 * 1024,
"16 MB" => 16 * 1024 * 1024,
_ => unreachable!(),
})?;
}
}

let target_dir_clone = target_dir.clone();
let project_info = ProjectInfo {
project_name,
target_dir,
Expand Down Expand Up @@ -261,6 +291,123 @@ async fn init_project(
// Post-process
post_process(project_info)?;

// Apply embassy-boot customisations
if embassy_boot {
apply_embassy_boot(&target_dir_clone, flash_size)?;
}

Ok(())
}

/// Apply embassy-boot (DFU) template customisations to a generated project.
fn apply_embassy_boot(
target_dir: &Path,
flash_size: u32,
) -> Result<(), Box<dyn Error>> {
// ── memory.x ──────────────────────────────────────────────────────
// No BOOT2 region — the embassy-boot bootloader (e.g. bootymcbootface)
// provides it. The firmware starts at the ACTIVE slot (0x10007000).
let flash_len = flash_size / 4;
let flash_len_str = if flash_len >= 1024 * 1024 {
format!("{}M", flash_len / (1024 * 1024))
} else if flash_len % 1024 == 0 {
format!("{}K", flash_len / 1024)
} else {
flash_len.to_string()
};
let memory_x = format!(
"MEMORY {{\n\
\x20 FLASH : ORIGIN = 0x10007000, LENGTH = {}\n\
\x20 RAM : ORIGIN = 0x20000000, LENGTH = 256K\n\
}}\n",
flash_len_str
);
fs::write(target_dir.join("memory.x"), memory_x)?;

// ── Cargo.toml ────────────────────────────────────────────────────
let cargo_path = target_dir.join("Cargo.toml");
let cargo = fs::read_to_string(&cargo_path)?;

// 1 rmk feature: "rp2040" → "dfu_rp"
let cargo = cargo.replace(
r#"features = ["rp2040"]"#,
r#"features = ["dfu_rp"]"#,
);

// 2 cortex-m-rt: add set-vtor
let cargo = cargo.replace(
"cortex-m-rt = \"0.7.5\"",
"cortex-m-rt = { version = \"0.7.5\", features = [\"set-vtor\"] }",
);

// 3 embassy-rp: add critical-section-impl feature
let cargo = cargo.replace(
r#"features = [
"rp2040",
"defmt",
"time-driver",
]"#,
r#"features = [
"rp2040",
"defmt",
"time-driver",
"critical-section-impl",
]"#,
);

// 4 Add portable-atomic (needed by embassy-boot-rp)
let cargo = if cargo.contains("portable-atomic") {
cargo
} else {
// Insert after the embassy-rp / embassy-executor block
cargo.replace(
"embassy-executor",
"portable-atomic = { version = \"1.11\", features = [\"critical-section\"] }\nembassy-executor",
)
};

// 6 embassy-rp: bump version to 0.10 (needed by embassy-boot-rp)
let cargo = cargo.replace(
"embassy-rp = { version = \"0.8\", features = [",
"embassy-rp = { version = \"0.10\", features = [",

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we want to update all the targets anyway?

);

// 7 Add embassy-usb-driver (needed by embassy-usb-dfu on RP2040)
let cargo = if cargo.contains("embassy-usb-driver") {
cargo
} else {
cargo.replace(
"panic-probe",
"embassy-usb-driver = \"=0.2.0\"\npanic-probe",
)
};

fs::write(&cargo_path, cargo)?;

// ── keyboard.toml ─────────────────────────────────────────────────
let kb_path = target_dir.join("keyboard.toml");
let mut kb = fs::read_to_string(&kb_path)?;
// ensure [storage] is present (needed by dfu_rp flash init)
if !kb.contains("[storage]") {
kb.push_str("\n[storage]\nenabled = true\n");
}
kb.push_str(
"\n\
[dfu]\n\
led = \"PIN_25\"\n",
);
fs::write(&kb_path, kb)?;

// ── build.rs – strip flip-link ────────────────────────────────────
let build_path = target_dir.join("build.rs");
if build_path.exists() {
let build = fs::read_to_string(&build_path)?;
// comment out any flip-link references
let build = build.replace("flip-link", "# flip-link");
fs::write(&build_path, build)?;
}

println!("✓ embassy-boot (DFU) template applied");
Ok(())
}

Expand Down