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

add read_fpga_regs() entry point + sequencer register descriptions #1204

Merged
merged 8 commits into from
Mar 13, 2023
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
1 change: 1 addition & 0 deletions app/gimlet/rev-b.toml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ stacksize = 1600
start = true
task-slots = ["sys", "i2c_driver", {spi_driver = "spi2_driver"}, "hf", "jefe"]
notifications = ["timer"]
copy-to-archive = ["register_defs"]

[tasks.gimlet_seq.config]
fpga_image = "fpga-b.bin"
Expand Down
1 change: 1 addition & 0 deletions app/gimlet/rev-c.toml
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ stacksize = 1600
start = true
task-slots = ["sys", "i2c_driver", {spi_driver = "spi2_driver"}, "hf", "jefe"]
notifications = ["timer"]
copy-to-archive = ["register_defs"]

[tasks.gimlet_seq.config]
fpga_image = "fpga-b.bin"
Expand Down
76 changes: 76 additions & 0 deletions build/xtask/src/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,82 @@ fn build_archive(cfg: &PackageConfig, image_name: &str) -> Result<PathBuf> {
)?;
}

let mut metadata = None;

//
// Iterate over tasks looking for elements that should be copied into
// the archive. These are specified by the "copy-to-archive" array,
// which consists of keys into the config table; the values associated
// with these keys have the names of the files to add to the archive.
// All files added to the archive for a particular task will be in
// a directory dedicated to that task; all such directories will
// themselves be subdirectories in the "task" directory.
//
for (name, task) in &cfg.toml.tasks {
for c in &task.copy_to_archive {
match &task.config {
None => {
bail!(
"task {name}: {c} is specified to be copied \
into archive, but config table is missing"
);
}
Some(config) => match config.get(c) {
Some(ordered_toml::Value::String(s)) => {
//
// This is a bit of a heavy hammer: we need the
// directory name for the task to find the file to be
// copied into the archive, so we're going to iterate
// over all packages to find the crate assocated with
// this task. (We cache the metadata itself, as it
// takes on the order of ~150 ms to gather.)
//
use cargo_metadata::MetadataCommand;
bcantrill marked this conversation as resolved.
Show resolved Hide resolved
let metadata = match metadata.as_ref() {
Some(m) => m,
None => {
let d = MetadataCommand::new()
.manifest_path("./Cargo.toml")
.exec()?;
metadata.get_or_insert(d)
}
};

let pkg = metadata
.packages
.iter()
.find(|p| p.name == task.name)
.unwrap();

let dir = pkg.manifest_path.parent().unwrap();

let f = dir.join(s);
let task_dir = PathBuf::from("task").join(name).join(s);
archive.copy(f, task_dir).with_context(|| {
format!(
"task {name}: failed to copy \"{s}\" in {} \
into the archive",
dir.display()
)
})?;
}
Some(_) => {
bail!(
"task {name}: {c} is specified to be copied into \
the archive, but isn't a string in the config table"
);
}
None => {
bail!(
"task {name}: {c} is specified to be copied into \
the archive, but is missing in the config table"
);
}
},
}
}
}

archive.finish()?;
Ok(archive_path)
}
Expand Down
1 change: 1 addition & 0 deletions drv/gimlet-seq-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub enum SeqError {
MuxToHostCPUFailed,
MuxToSPFailed,
ClockConfigFailed,
ReadRegsFailed,

#[idol(server_death)]
ServerRestarted,
Expand Down
16 changes: 16 additions & 0 deletions drv/gimlet-seq-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,22 @@ impl<S: SpiServer> idl::InOrderSequencerImpl for ServerImpl<S> {
self.sys.gpio_set(SP_TO_SP3_NMI_SYNC_FLOOD_L);
Ok(())
}

fn read_fpga_regs(
&mut self,
_: &RecvMessage,
) -> Result<[u8; 64], RequestError<SeqError>> {
let mut buf = [0; 64];
let size = 8;

for i in (0..buf.len()).step_by(size) {
self.seq
.read_bytes(i as u16, &mut buf[i..i + size])
.map_err(|_| SeqError::ReadRegsFailed)?;
}

Ok(buf)
}
}

fn reprogram_fpga<S: SpiServer>(
Expand Down
10 changes: 6 additions & 4 deletions drv/gimlet-seq-server/src/seq_spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl<S: SpiServer> SequencerFpga<S> {
}

/// Performs the READ command against `addr`. This can read as many bytes as
/// you like into `data_out`.
/// you like into `data_out`, limited by `raw_spi_read` buffer size
pub fn read_bytes(
&self,
addr: impl Into<u16>,
Expand Down Expand Up @@ -142,14 +142,16 @@ impl<S: SpiServer> SequencerFpga<S> {
let header = CmdHeader { cmd, addr };
let header = header.as_bytes();

if data_out.len() > data.len() - header.len() {
return Err(spi_api::SpiError::BadTransferSize);
}
bcantrill marked this conversation as resolved.
Show resolved Hide resolved

data[..header.len()].copy_from_slice(header);

self.spi.exchange(&data, &mut rval)?;

for i in 0..data_out.len() {
if i + header.len() < data.len() {
data_out[i] = rval[i + header.len()];
}
data_out[i] = rval[i + header.len()];
}

Ok(())
Expand Down
19 changes: 13 additions & 6 deletions drv/local-vpd/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ struct EepromReader<'a> {
#[derive(Copy, Clone, PartialEq)]
enum Trace {
EepromError(drv_i2c_devices::at24csw080::Error),
Error(LocalVpdError),
None,
}

Expand Down Expand Up @@ -122,26 +123,32 @@ pub fn read_config_into(
i2c_config::devices::at24csw080_local_vpd(i2c_task),
);
let eeprom_reader = EepromReader { eeprom: &eeprom };

let err = |e| {
ringbuf_entry!(Trace::Error(e));
e
};

let mut reader = TlvcReader::begin(eeprom_reader)
.map_err(|_| LocalVpdError::DeviceError)?;
.map_err(|_| err(LocalVpdError::DeviceError))?;

while let Ok(Some(chunk)) = reader.next() {
let mut scratch = [0u8; 32];
if chunk.header().tag == *b"FRU0" {
chunk
.check_body_checksum(&mut scratch)
.map_err(|_| LocalVpdError::InvalidChecksum)?;
.map_err(|_| err(LocalVpdError::InvalidChecksum))?;
let mut inner = chunk.read_as_chunks();
while let Ok(Some(chunk)) = inner.next() {
if chunk.header().tag == tag {
chunk
.check_body_checksum(&mut scratch)
.map_err(|_| LocalVpdError::InvalidChecksum)?;
.map_err(|_| err(LocalVpdError::InvalidChecksum))?;

let chunk_len = chunk.len() as usize;

if chunk_len > out.len() {
return Err(LocalVpdError::InvalidChunkSize);
return Err(err(LocalVpdError::InvalidChunkSize));
}

chunk
Expand All @@ -150,10 +157,10 @@ pub fn read_config_into(
return Ok(chunk_len);
}
}
return Err(LocalVpdError::NoSuchChunk);
return Err(err(LocalVpdError::NoSuchChunk));
}
}
Err(LocalVpdError::NoRootChunk)
Err(err(LocalVpdError::NoRootChunk))
}

include!(concat!(env!("OUT_DIR"), "/i2c_config.rs"));
7 changes: 7 additions & 0 deletions drv/mock-gimlet-seq-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@ impl idl::InOrderSequencerImpl for ServerImpl {
) -> Result<(), RequestError<core::convert::Infallible>> {
Ok(())
}

fn read_fpga_regs(
&mut self,
_: &RecvMessage,
) -> Result<[u8; 64], RequestError<SeqError>> {
Ok([0; 64])
}
}

mod idl {
Expand Down
8 changes: 8 additions & 0 deletions idl/gimlet-seq.idol
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,13 @@ Interface(
err: ServerDeath,
),
),
"read_fpga_regs": (
doc: "Raw read of the FPGA registers",
args: {},
reply: Result(
ok: "[u8; 64]",
err: CLike("SeqError"),
),
),
},
)
2 changes: 2 additions & 0 deletions lib/toml-task/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ pub struct Task<T = ordered_toml::Value> {
pub features: Vec<String>,
#[serde(default)]
pub notifications: Vec<String>,
#[serde(default)]
pub copy_to_archive: Vec<String>,

// Order matters here:
// TOML serialization doesn't allow us to put a value type after any Table
Expand Down