Skip to content

Commit c821c3f

Browse files
committed
Merge remote-tracking branch 'phoracek/demo_qspi_daisy' into octospi-pr
2 parents 08f921c + 24aca42 commit c821c3f

File tree

2 files changed

+192
-0
lines changed

2 files changed

+192
-0
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ required-features = ["xspi", "rm0433"]
151151
name = "qspi_mdma"
152152
required-features = ["xspi", "rm0433"]
153153

154+
[[example]]
155+
name = "qspi_flash_memory"
156+
required-features = ["xspi", "rm0433"]
157+
154158
[[example]]
155159
name = "octospi"
156160
required-features = ["xspi", "rm0468"]

examples/qspi_flash_memory.rs

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
//! Example of communication with flash memory over QSPI interface. This
2+
//! specific program is made for Daisy Seed board and its IS25LP064A flash
3+
//! memory chip. This demo provides a non-volatile restart counter. When it is
4+
//! odd, LED will light up, when even, it stays off.
5+
6+
#![deny(warnings)]
7+
#![no_main]
8+
#![no_std]
9+
10+
#[macro_use]
11+
mod utilities;
12+
13+
use core::mem::transmute;
14+
15+
use cortex_m_rt::entry;
16+
use stm32h7xx_hal::gpio::Speed;
17+
use stm32h7xx_hal::hal::digital::v2::OutputPin;
18+
use stm32h7xx_hal::{
19+
pac, prelude::*, xspi::Qspi, xspi::QspiMode, xspi::QspiWord,
20+
};
21+
22+
use log::info;
23+
24+
// SPI commands from IS25LP064 datasheet
25+
const WRITE_STATUS_REGISTRY_CMD: u8 = 0x01; // WRSR
26+
const WRITE_CMD: u8 = 0x02; // PP
27+
const NORMAL_READ_CMD: u8 = 0x03; // NORD
28+
const READ_STATUS_REGISTRY_CMD: u8 = 0x05; // RDSR
29+
const WRITE_ENABLE_CMD: u8 = 0x06; // WREN
30+
const SET_READ_PARAMETERS_CMD: u8 = 0xC0; // SRP
31+
const SECTOR_ERASE_CMD: u8 = 0xD8; // SER
32+
33+
// Address in the external memory that will be used for the counter
34+
const COUNTER_ADDRESS: u32 = 0x00;
35+
36+
#[entry]
37+
fn main() -> ! {
38+
utilities::logger::init();
39+
let dp = pac::Peripherals::take().unwrap();
40+
41+
// Constrain and Freeze power
42+
let pwr = dp.PWR.constrain();
43+
let pwrcfg = example_power!(pwr).freeze();
44+
45+
// Constrain and Freeze clock
46+
let rcc = dp.RCC.constrain();
47+
let ccdr = rcc.sys_ck(96.mhz()).freeze(pwrcfg, &dp.SYSCFG);
48+
49+
// Acquire the GPIO peripherals
50+
let gpioc = dp.GPIOC.split(ccdr.peripheral.GPIOC);
51+
let gpiof = dp.GPIOF.split(ccdr.peripheral.GPIOF);
52+
let gpiog = dp.GPIOG.split(ccdr.peripheral.GPIOG);
53+
54+
// Even though it is not directly used, CS pin must be acquired and configured
55+
let _qspi_cs = gpiog.pg6.into_alternate_af10().set_speed(Speed::VeryHigh);
56+
57+
let sck = gpiof.pf10.into_alternate_af9().set_speed(Speed::VeryHigh);
58+
let io0 = gpiof.pf8.into_alternate_af10().set_speed(Speed::VeryHigh);
59+
let io1 = gpiof.pf9.into_alternate_af10().set_speed(Speed::VeryHigh);
60+
let io2 = gpiof.pf7.into_alternate_af9().set_speed(Speed::VeryHigh);
61+
let io3 = gpiof.pf6.into_alternate_af9().set_speed(Speed::VeryHigh);
62+
63+
let mut led = gpioc.pc7.into_push_pull_output();
64+
65+
info!("");
66+
info!("stm32h7xx-hal example - QSPI Flash Memory");
67+
info!("");
68+
69+
// Initialise the QSPI peripheral
70+
let mut qspi = dp.QUADSPI.bank1(
71+
(sck, io0, io1, io2, io3),
72+
3.mhz(),
73+
&ccdr.clocks,
74+
ccdr.peripheral.QSPI,
75+
);
76+
qspi.configure_mode(QspiMode::OneBit).unwrap();
77+
78+
// Reset configuration of the flash memory
79+
reset_status_registry(&mut qspi);
80+
reset_read_registry(&mut qspi);
81+
82+
// Read the current value and increment it
83+
let original = read_u32(&mut qspi, COUNTER_ADDRESS);
84+
write_u32(&mut qspi, COUNTER_ADDRESS, original.overflowing_add(1).0);
85+
86+
// Based on the original value, enable or disable LED on the board
87+
if original % 2 == 0 {
88+
led.set_low().unwrap();
89+
} else {
90+
led.set_high().unwrap();
91+
}
92+
93+
loop {
94+
cortex_m::asm::nop();
95+
}
96+
}
97+
98+
fn read_u32(qspi: &mut Qspi<pac::QUADSPI>, address: u32) -> u32 {
99+
let mut buffer: [u8; 4] = [0xFF; 4];
100+
qspi.read_extended(
101+
QspiWord::U8(NORMAL_READ_CMD),
102+
QspiWord::U24(address),
103+
QspiWord::None,
104+
0,
105+
&mut buffer,
106+
)
107+
.unwrap();
108+
u32::from_be_bytes(buffer)
109+
}
110+
111+
fn write_u32(qspi: &mut Qspi<pac::QUADSPI>, address: u32, value: u32) {
112+
enable_write_operation(qspi);
113+
qspi.write_extended(
114+
QspiWord::U8(SECTOR_ERASE_CMD),
115+
QspiWord::U24(address),
116+
QspiWord::None,
117+
&[],
118+
)
119+
.unwrap();
120+
wait_for_write_completition(qspi);
121+
122+
let bytes: [u8; 4] = unsafe { transmute(value.to_be()) };
123+
enable_write_operation(qspi);
124+
qspi.write_extended(
125+
QspiWord::U8(WRITE_CMD),
126+
QspiWord::U24(address),
127+
QspiWord::None,
128+
&bytes,
129+
)
130+
.unwrap();
131+
wait_for_write_completition(qspi);
132+
}
133+
134+
fn reset_status_registry(qspi: &mut Qspi<pac::QUADSPI>) {
135+
enable_write_operation(qspi);
136+
137+
qspi.write_extended(
138+
QspiWord::U8(WRITE_STATUS_REGISTRY_CMD),
139+
QspiWord::U8(0b00000000),
140+
QspiWord::None,
141+
&[],
142+
)
143+
.unwrap();
144+
145+
wait_for_write_completition(qspi);
146+
}
147+
148+
fn reset_read_registry(qspi: &mut Qspi<pac::QUADSPI>) {
149+
enable_write_operation(qspi);
150+
151+
qspi.write_extended(
152+
QspiWord::U8(SET_READ_PARAMETERS_CMD),
153+
QspiWord::U8(0b11100000),
154+
QspiWord::None,
155+
&[],
156+
)
157+
.unwrap();
158+
159+
wait_for_write_completition(qspi);
160+
}
161+
162+
fn enable_write_operation(qspi: &mut Qspi<pac::QUADSPI>) {
163+
qspi.write_extended(
164+
QspiWord::U8(WRITE_ENABLE_CMD),
165+
QspiWord::None,
166+
QspiWord::None,
167+
&[],
168+
)
169+
.unwrap();
170+
}
171+
172+
fn wait_for_write_completition(qspi: &mut Qspi<pac::QUADSPI>) {
173+
loop {
174+
let mut status: [u8; 1] = [0xFF; 1];
175+
qspi.read_extended(
176+
QspiWord::U8(READ_STATUS_REGISTRY_CMD),
177+
QspiWord::None,
178+
QspiWord::None,
179+
0,
180+
&mut status,
181+
)
182+
.unwrap();
183+
184+
if status[0] & 0x01 == 0 {
185+
break;
186+
}
187+
}
188+
}

0 commit comments

Comments
 (0)