Skip to content

Commit

Permalink
Standalone spartan-7 loader (#2003)
Browse files Browse the repository at this point in the history
For Grapefruit and Cosmo, the Spartan-7 FPGA is used as a memory-mapped
peripheral once its bitstream is loaded. It's important that it not die
or be reset, because that will be Very Confusing for any tasks writing
directly into its memory space.

This PR moves loading that FPGA into a standalone task, separate from
`grapefruit-seq` (and the eventual `cosmo-seq`). The new task is
infallible once it enters the Idol runtime loop, and can provide
unforgeable tokens that prove the FPGA was loaded; eventually, I'd like
for FPGA-based peripherals to take those tokens in their constructors.

The code changes in this PR are mostly reorganization and boilerplate,
pulling stuff from `grapefruit-seq` into `drv-spartan7-loader` and
writing `drv-spartan7-loader-api` / Idol files.

Tested on Grapefruit (standalone).
  • Loading branch information
mkeeter authored Feb 7, 2025
1 parent 24cb4ca commit 49d76b6
Show file tree
Hide file tree
Showing 15 changed files with 474 additions and 209 deletions.
39 changes: 35 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 20 additions & 5 deletions app/grapefruit/app.toml
Original file line number Diff line number Diff line change
Expand Up @@ -173,13 +173,28 @@ interrupts = {"spi4.irq" = "spi-irq"}
[tasks.grapefruit_seq]
name = "drv-grapefruit-seq-server"
features = ["h753"]
priority = 4
priority = 5
max-sizes = {flash = 131072, ram = 16384 }
stacksize = 2600
start = true
task-slots = ["sys", {spi = "spi2_driver"}, "auxflash", "jefe", "packrat"]
task-slots = ["sys", "jefe", "packrat", "spartan7_loader"]
uses = ["fmc_nor_psram_bank_1"]

[tasks.spartan7_loader]
name = "drv-spartan7-loader"
features = ["h753"]
priority = 4
max-sizes = {flash = 131072, ram = 16384 }
stacksize = 2600
start = true
task-slots = ["sys", {spi = "spi2_driver"}, "auxflash"]

[tasks.spartan7_loader.config]
program_l = "sys_api::Port::B.pin(6)"
init_l = "sys_api::Port::B.pin(5)"
config_done = "sys_api::Port::B.pin(4)"
user_reset_l = "sys_api::Port::I.pin(15)"

[tasks.thermal]
name = "task-thermal"
features = ["grapefruit"]
Expand Down Expand Up @@ -326,7 +341,7 @@ name = "drv-cosmo-hf"
priority = 5
start = true
uses = ["fmc_nor_psram_bank_1"]
task-slots = ["hash_driver", "grapefruit_seq"]
task-slots = ["hash_driver", "spartan7_loader"]
stacksize = 4000

[config.net]
Expand Down Expand Up @@ -551,7 +566,7 @@ outputs = [
]
input = {port = "B", pin = 14, af = 5} # not actually used in FPGA config

[config.spi.spi2.devices.fpga]
[config.spi.spi2.devices.spartan7_fpga]
mux = "port_b"
cs = []
# no CS pin; we're using the SPI peripheral to send synchronized CLK + DATA
Expand Down Expand Up @@ -580,4 +595,4 @@ slot-count = 16 # 2 MiB slots
file = "drv/grapefruit-seq-server/grapefruit.bz2"
unzip = "bz2"
compress = true
tag = "FPGA"
tag = "SPA7" # used by drv-spartan7-loader
2 changes: 1 addition & 1 deletion drv/cosmo-hf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ edition = "2021"

[dependencies]
counters = { path = "../../lib/counters" }
drv-cpu-seq-api = { path = "../cpu-seq-api" }
drv-hash-api = { path = "../hash-api" }
drv-hf-api = { path = "../hf-api" }
drv-spartan7-loader-api = { path = "../spartan7-loader-api" }
ringbuf = { path = "../../lib/ringbuf" }
userlib = { path = "../../sys/userlib", features = ["panic-messages"] }

Expand Down
7 changes: 4 additions & 3 deletions drv/cosmo-hf/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use userlib::{hl::sleep_for, task_slot};

mod hf; // implementation of `HostFlash` API

task_slot!(SEQ, grapefruit_seq);
task_slot!(LOADER, spartan7_loader);

#[derive(Debug, Clone, Copy, PartialEq, counters::Count)]
enum Trace {
Expand Down Expand Up @@ -65,8 +65,9 @@ pub const FLASH_SIZE_BYTES: u32 = 128 * 1024 * 1024;
fn main() -> ! {
// Wait for the FPGA to be configured; the sequencer task only starts its
// Idol loop after the FPGA has been brought up.
let seq = drv_cpu_seq_api::Sequencer::from(SEQ.get_task_id());
let _ = seq.get_state();
let seq =
drv_spartan7_loader_api::Spartan7Loader::from(LOADER.get_task_id());
seq.ping();

let id = unsafe { reg::BASE.read_volatile() };
if id != 0x1de {
Expand Down
4 changes: 1 addition & 3 deletions drv/grapefruit-seq-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ counters = { path = "../../lib/counters" }
drv-auxflash-api = { path = "../auxflash-api" }
drv-cpu-power-state = { path = "../cpu-power-state" }
drv-cpu-seq-api = { path = "../cpu-seq-api" }
drv-spartan7-spi-program = { path = "../spartan7-spi-program" }
drv-spi-api = { path = "../spi-api" }
drv-spartan7-loader-api = { path = "../spartan7-loader-api" }
drv-stm32xx-sys-api = { path = "../stm32xx-sys-api" }
gnarle = { path = "../../lib/gnarle" }
task-packrat-api = { path = "../../task/packrat-api" }
ringbuf = { path = "../../lib/ringbuf" }
userlib = { path = "../../sys/userlib", features = ["panic-messages"] }
Expand Down
23 changes: 0 additions & 23 deletions drv/grapefruit-seq-server/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

use std::{fs, io::Write};

fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
build_util::expose_target_board();

let out_dir = build_util::out_dir();
let out_file = out_dir.join("grapefruit_fpga.rs");
let mut file = fs::File::create(out_file)?;

// Check that a valid bitstream is available for this board.
let board = build_util::env_var("HUBRIS_BOARD")?;
if board != "grapefruit" {
panic!("unknown target board");
}

// Pull the bitstream checksum from an environment variable
// (injected by `xtask` itself as part of auxiliary flash packing)
let checksum =
build_util::env_var("HUBRIS_AUXFLASH_CHECKSUM_FPGA").unwrap();
writeln!(
&mut file,
"\npub const FPGA_BITSTREAM_CHECKSUM: [u8; 32] = {};",
checksum,
)?;

idol::Generator::new().build_server_support(
"../../idl/cpu-seq.idol",
"server_stub.rs",
Expand Down
Loading

0 comments on commit 49d76b6

Please sign in to comment.