Skip to content

Commit 91e2f6e

Browse files
committed
Improve gimlet qspi error reporting
We currently ignore any errors when working with the QSPI driver. The biggest place this is noticable is if we happen to give a bad address for reading we will loop forever. Fix this up to actually handle errors.
1 parent 1ef6911 commit 91e2f6e

File tree

5 files changed

+235
-67
lines changed

5 files changed

+235
-67
lines changed

drv/auxflash-api/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ pub enum AuxFlashError {
4747
NoSuchBlob,
4848
/// Writes to the currently-active slot are not allowed
4949
SlotActive,
50-
50+
/// QSPI Timed out
51+
QspiTimeout,
52+
/// QSPI Transfer error
53+
QspiTransferError,
5154
#[idol(server_death)]
5255
ServerRestarted,
5356
}

drv/auxflash-server/src/main.rs

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use userlib::{hl, task_slot, RecvMessage, UnwrapLite};
1919
#[cfg(feature = "h753")]
2020
use stm32h7::stm32h753 as device;
2121

22-
use drv_stm32h7_qspi::Qspi;
22+
use drv_stm32h7_qspi::{Qspi, QspiError};
2323
use drv_stm32xx_sys_api as sys_api;
2424

2525
task_slot!(SYS, sys);
@@ -34,7 +34,7 @@ struct SlotReader<'a> {
3434
}
3535

3636
impl<'a> TlvcRead for SlotReader<'a> {
37-
type Error = core::convert::Infallible;
37+
type Error = AuxFlashError;
3838

3939
fn extent(&self) -> Result<u64, TlvcReadError<Self::Error>> {
4040
// Hard-coded slot size, on a per-board basis
@@ -46,13 +46,23 @@ impl<'a> TlvcRead for SlotReader<'a> {
4646
dest: &mut [u8],
4747
) -> Result<(), TlvcReadError<Self::Error>> {
4848
let addr: u32 = self.base + u32::try_from(offset).unwrap_lite();
49-
self.qspi.read_memory(addr, dest);
49+
self.qspi
50+
.read_memory(addr, dest)
51+
.map_err(|x| TlvcReadError::User(qspi_to_auxflash(x)))?;
5052
Ok(())
5153
}
5254
}
5355

5456
////////////////////////////////////////////////////////////////////////////////
5557

58+
// There isn't a great crate to do `From` implementation so do this manually
59+
fn qspi_to_auxflash(val: QspiError) -> AuxFlashError {
60+
match val {
61+
QspiError::Timeout => AuxFlashError::QspiTimeout,
62+
QspiError::TransferError => AuxFlashError::QspiTransferError,
63+
}
64+
}
65+
5666
#[export_name = "main"]
5767
fn main() -> ! {
5868
let sys = sys_api::Sys::from(SYS.get_task_id());
@@ -133,9 +143,12 @@ impl ServerImpl {
133143
///
134144
/// Sleep times are in ticks (typically milliseconds) and are somewhat
135145
/// experimentally determined, see hubris#753 for details.
136-
fn poll_for_write_complete(&self, sleep: Option<u64>) {
146+
fn poll_for_write_complete(
147+
&self,
148+
sleep: Option<u64>,
149+
) -> Result<(), AuxFlashError> {
137150
loop {
138-
let status = self.qspi.read_status();
151+
let status = self.qspi.read_status().map_err(qspi_to_auxflash)?;
139152
if status & 1 == 0 {
140153
// ooh we're done
141154
break;
@@ -144,11 +157,12 @@ impl ServerImpl {
144157
hl::sleep_for(sleep);
145158
}
146159
}
160+
Ok(())
147161
}
148162

149163
fn set_and_check_write_enable(&self) -> Result<(), AuxFlashError> {
150-
self.qspi.write_enable();
151-
let status = self.qspi.read_status();
164+
self.qspi.write_enable().map_err(qspi_to_auxflash)?;
165+
let status = self.qspi.read_status().map_err(qspi_to_auxflash)?;
152166

153167
if status & 0b10 == 0 {
154168
// oh oh
@@ -197,20 +211,26 @@ impl ServerImpl {
197211
let amount = (read_end - read_addr).min(buf.len());
198212

199213
// Read from the active slot
200-
self.qspi.read_memory(read_addr as u32, &mut buf[..amount]);
214+
self.qspi
215+
.read_memory(read_addr as u32, &mut buf[..amount])
216+
.map_err(qspi_to_auxflash)?;
201217

202218
// If we're at the start of a sector, erase it before we start
203219
// writing the copy.
204220
if write_addr % SECTOR_SIZE_BYTES == 0 {
205221
self.set_and_check_write_enable()?;
206-
self.qspi.sector_erase(write_addr as u32);
207-
self.poll_for_write_complete(Some(1));
222+
self.qspi
223+
.sector_erase(write_addr as u32)
224+
.map_err(qspi_to_auxflash)?;
225+
self.poll_for_write_complete(Some(1))?;
208226
}
209227

210228
// Write back to the redundant slot
211229
self.set_and_check_write_enable()?;
212-
self.qspi.page_program(write_addr as u32, &buf[..amount]);
213-
self.poll_for_write_complete(None);
230+
self.qspi
231+
.page_program(write_addr as u32, &buf[..amount])
232+
.map_err(qspi_to_auxflash)?;
233+
self.poll_for_write_complete(None)?;
214234

215235
read_addr += amount;
216236
write_addr += amount;
@@ -232,15 +252,15 @@ impl idl::InOrderAuxFlashImpl for ServerImpl {
232252
_: &RecvMessage,
233253
) -> Result<AuxFlashId, RequestError<AuxFlashError>> {
234254
let mut idbuf = [0; 20];
235-
self.qspi.read_id(&mut idbuf);
255+
self.qspi.read_id(&mut idbuf).map_err(qspi_to_auxflash)?;
236256
Ok(AuxFlashId(idbuf))
237257
}
238258

239259
fn read_status(
240260
&mut self,
241261
_: &RecvMessage,
242262
) -> Result<u8, RequestError<AuxFlashError>> {
243-
Ok(self.qspi.read_status())
263+
Ok(self.qspi.read_status().map_err(qspi_to_auxflash)?)
244264
}
245265

246266
fn slot_count(
@@ -282,9 +302,11 @@ impl idl::InOrderAuxFlashImpl for ServerImpl {
282302
let mut addr = mem_start;
283303
while addr < mem_end {
284304
self.set_and_check_write_enable()?;
285-
self.qspi.sector_erase(addr as u32);
305+
self.qspi
306+
.sector_erase(addr as u32)
307+
.map_err(qspi_to_auxflash)?;
286308
addr += SECTOR_SIZE_BYTES;
287-
self.poll_for_write_complete(Some(1));
309+
self.poll_for_write_complete(Some(1))?;
288310
}
289311
Ok(())
290312
}
@@ -307,8 +329,10 @@ impl idl::InOrderAuxFlashImpl for ServerImpl {
307329
}
308330

309331
self.set_and_check_write_enable()?;
310-
self.qspi.sector_erase(addr as u32);
311-
self.poll_for_write_complete(Some(1));
332+
self.qspi
333+
.sector_erase(addr as u32)
334+
.map_err(qspi_to_auxflash)?;
335+
self.poll_for_write_complete(Some(1))?;
312336
Ok(())
313337
}
314338

@@ -343,8 +367,10 @@ impl idl::InOrderAuxFlashImpl for ServerImpl {
343367
.map_err(|_| RequestError::Fail(ClientError::WentAway))?;
344368

345369
self.set_and_check_write_enable()?;
346-
self.qspi.page_program(addr as u32, &buf[..amount]);
347-
self.poll_for_write_complete(None);
370+
self.qspi
371+
.page_program(addr as u32, &buf[..amount])
372+
.map_err(qspi_to_auxflash)?;
373+
self.poll_for_write_complete(None)?;
348374
addr += amount;
349375
read += amount;
350376
}
@@ -369,7 +395,9 @@ impl idl::InOrderAuxFlashImpl for ServerImpl {
369395
let mut buf = [0u8; 256];
370396
while addr < end {
371397
let amount = (end - addr).min(buf.len());
372-
self.qspi.read_memory(addr as u32, &mut buf[..amount]);
398+
self.qspi
399+
.read_memory(addr as u32, &mut buf[..amount])
400+
.map_err(qspi_to_auxflash)?;
373401
dest.write_range(write..(write + amount), &buf[..amount])
374402
.map_err(|_| RequestError::Fail(ClientError::WentAway))?;
375403
write += amount;

0 commit comments

Comments
 (0)