Skip to content

Commit 3e04cba

Browse files
committed
Use quad read command for QSPI
We aren't actually making use of all 4 lines on the QSPI chip. Use the appropriate command to get a nice performance improvement. It does come at the cost of needing to drop the QSPI clock. Only enable it on boards we've been able to validate.
1 parent 3f419ef commit 3e04cba

File tree

5 files changed

+50
-13
lines changed

5 files changed

+50
-13
lines changed

drv/auxflash-server/src/main.rs

Lines changed: 3 additions & 2 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, QspiError};
22+
use drv_stm32h7_qspi::{Qspi, QspiError, ReadSetting};
2323
use drv_stm32xx_sys_api as sys_api;
2424

2525
task_slot!(SYS, sys);
@@ -71,7 +71,8 @@ fn main() -> ! {
7171
sys.leave_reset(sys_api::Peripheral::QuadSpi);
7272

7373
let reg = unsafe { &*device::QUADSPI::ptr() };
74-
let qspi = Qspi::new(reg, notifications::QSPI_IRQ_MASK);
74+
let qspi =
75+
Qspi::new(reg, notifications::QSPI_IRQ_MASK, ReadSetting::Single);
7576

7677
let clock = 5; // 200MHz kernel / 5 = 40MHz clock
7778
const MEMORY_SIZE: usize = SLOT_COUNT as usize * SLOT_SIZE;

drv/gimlet-hf-server/src/bsp/gimlet_bcdef.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ use drv_stm32xx_sys_api as sys_api;
88

99
#[allow(dead_code)]
1010
pub(crate) fn init(qspi: &Qspi, sys: &sys_api::Sys) -> Config {
11-
let clock = 6; // 200MHz kernel / 6 = 33.333MHz clock
11+
// 33.33MHz was too fast to be able to use the full
12+
// quad read commands, this seems to work
13+
let clock = 7; // 200MHz kernel / 7 = 28.5714MHz clock
1214
qspi.configure(
1315
clock, 25, // 2**25 = 32MiB = 256Mib
1416
);

drv/gimlet-hf-server/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use userlib::{
2828
};
2929

3030
use drv_hf_api::{HashData, HashState, SlotHash, SECTOR_SIZE_BYTES};
31-
use drv_stm32h7_qspi::{Qspi, QspiError};
31+
use drv_stm32h7_qspi::{Qspi, QspiError, ReadSetting};
3232
use drv_stm32xx_sys_api as sys_api;
3333
use idol_runtime::{
3434
ClientError, Leased, LenLimit, NotificationHandler, RequestError, R, W,
@@ -97,7 +97,7 @@ fn main() -> ! {
9797
sys.leave_reset(sys_api::Peripheral::QuadSpi);
9898

9999
let reg = unsafe { &*device::QUADSPI::ptr() };
100-
let qspi = Qspi::new(reg, notifications::QSPI_IRQ_MASK);
100+
let qspi = Qspi::new(reg, notifications::QSPI_IRQ_MASK, ReadSetting::Quad);
101101

102102
// Build a pin struct using a board-specific init function
103103
let cfg = bsp::init(&qspi, &sys);

drv/qspi-api/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ pub const PAGE_SIZE_BYTES: usize = 256;
2222
/// will need to change to something more flexible.
2323
pub const SECTOR_SIZE_BYTES: usize = 65_536;
2424

25+
#[derive(Copy, Clone)]
2526
pub enum Command {
2627
ReadStatusReg = 0x05,
2728
WriteEnable = 0x06,
@@ -36,6 +37,12 @@ pub enum Command {
3637

3738
BulkErase = 0xC7,
3839
SectorErase = 0xDC,
40+
// 4-BYTE QUAD OUTPUT FAST READ
41+
QuadRead = 0x6C,
42+
// 4-BYTE DTR QUAD INPUT/OUTPUT FAST READ
43+
// Does not work at the moment
44+
QuadDdrRead = 0xEE,
45+
DdrRead = 0x0E,
3946
}
4047

4148
impl From<Command> for u8 {

drv/stm32h7-qspi/src/lib.rs

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,19 @@ use zerocopy::IntoBytes;
1919
const FIFO_SIZE: usize = 32;
2020
const FIFO_THRESH: usize = 16;
2121

22+
// In a perfect world we would use quad read everywhere because it is fast.
23+
// We've seen some inconsistency with the quad read command on some targets
24+
// so limit its use to targets where we've confirmed.
25+
pub enum ReadSetting {
26+
Single,
27+
Quad,
28+
}
29+
2230
/// Wrapper for a reference to the register block.
2331
pub struct Qspi {
2432
reg: &'static device::quadspi::RegisterBlock,
2533
interrupt: u32,
34+
read_command: Command,
2635
}
2736

2837
pub enum QspiError {
@@ -35,8 +44,16 @@ impl Qspi {
3544
pub fn new(
3645
reg: &'static device::quadspi::RegisterBlock,
3746
interrupt: u32,
47+
read: ReadSetting,
3848
) -> Self {
39-
Self { reg, interrupt }
49+
Self {
50+
reg,
51+
interrupt,
52+
read_command: match read {
53+
ReadSetting::Single => Command::Read,
54+
ReadSetting::Quad => Command::QuadRead,
55+
},
56+
}
4057
}
4158

4259
/// Sets up the QSPI controller with some canned settings.
@@ -94,7 +111,7 @@ impl Qspi {
94111
address: u32,
95112
data: &mut [u8],
96113
) -> Result<(), QspiError> {
97-
self.read_impl(Command::Read, Some(address), data)
114+
self.read_impl(self.read_command, Some(address), data)
98115
}
99116

100117
/// Sets the Write Enable Latch on the flash chip, allowing a write/erase
@@ -311,22 +328,32 @@ impl Qspi {
311328
// hanging around from some previous transfer -- ensure this:
312329
self.reg.fcr.write(|w| w.ctcf().set_bit());
313330

331+
let (quad_setting, ddr_setting) = match command {
332+
Command::QuadRead => (true, false),
333+
Command::QuadDdrRead => (true, true),
334+
Command::DdrRead => (false, true),
335+
_ => (false, false),
336+
};
337+
314338
#[rustfmt::skip]
315339
#[allow(clippy::bool_to_int_with_if)]
316340
self.reg.ccr.write(|w| unsafe {
317341
w
342+
// Set DDR mode if quad read
343+
.ddrm().bit(ddr_setting)
344+
.dhhc().bit(ddr_setting)
318345
// Indirect read
319346
.fmode().bits(0b01)
320-
// Data on single line, or no data
321-
.dmode().bits(if out.is_empty() { 0b00 } else { 0b01 })
322-
// Dummy cycles = 0 for this
323-
.dcyc().bits(0)
347+
// Data on single line, 4 lines if quad or no line
348+
.dmode().bits(if out.is_empty() { 0b00 } else if quad_setting { 0b11 } else { 0b01 } )
349+
// Dummy cycles = 0 for single read, 8 for quad
350+
.dcyc().bits(if quad_setting { 8 } else { 0 })
324351
// No alternate bytes
325352
.abmode().bits(0)
326353
// 32-bit address if present.
327354
.adsize().bits(if addr.is_some() { 0b11 } else { 0b00 })
328-
// ...on one line for now, if present.
329-
.admode().bits(if addr.is_some() { 0b01 } else { 0b00 })
355+
// ...on one line for now (or 4 for the DDR command), if present.
356+
.admode().bits(if addr.is_some() { if ddr_setting { 0b11} else { 0b01 } } else { 0b00 })
330357
// Instruction on single line
331358
.imode().bits(0b01)
332359
// And, the op

0 commit comments

Comments
 (0)