tudelft_quadrupel/
flash.rs1use crate::mutex::Mutex;
2use crate::once_cell::OnceCell;
3use crate::time::{delay_ms_assembly, delay_us_assembly};
4use nb::block;
5use nrf51_hal::gpio::p0::{P0_00, P0_09, P0_11, P0_13, P0_17, P0_18};
6use nrf51_hal::gpio::Level;
7use nrf51_hal::gpio::{Disconnected, Output, PushPull};
8use nrf51_hal::prelude::OutputPin;
9use nrf51_hal::spi::{Frequency, Pins};
10use nrf51_hal::spi::{FullDuplex, MODE_0};
11use nrf51_hal::Spi;
12use nrf51_pac::SPI1;
13
14const WRSR: u8 = 0x01;
15const BYTEWRITE: u8 = 0x02;
16const BYTEREAD: u8 = 0x03;
17const WRDI: u8 = 0x04;
18const WREN: u8 = 0x06;
20const EWSR: u8 = 0x50;
21const CHIP_ERASE: u8 = 0x60;
22const AAI: u8 = 0xAF;
23
24static FLASH: Mutex<OnceCell<SpiFlash>> = Mutex::new(OnceCell::uninitialized());
25
26#[derive(Debug)]
28pub enum FlashError {
29 SpiError(nrf51_hal::spi::Error),
31 OutOfSpace,
34}
35
36impl From<void::Void> for FlashError {
37 fn from(v: void::Void) -> Self {
38 match v {}
39 }
40}
41
42impl From<nrf51_hal::spi::Error> for FlashError {
43 fn from(e: nrf51_hal::spi::Error) -> Self {
44 FlashError::SpiError(e)
45 }
46}
47
48struct SpiFlash {
49 spi: Spi<SPI1>,
50 _pin_wp: P0_00<Output<PushPull>>,
51 _pin_hold: P0_13<Output<PushPull>>,
52 pin_cs: P0_17<Output<PushPull>>,
53}
54
55pub(crate) fn initialize(
57 spi1: SPI1,
58 pin_cs: P0_17<Disconnected>,
59 pin_miso: P0_18<Disconnected>,
60 pin_wp: P0_00<Disconnected>,
61 pin_hold: P0_13<Disconnected>,
62 pin_sck: P0_11<Disconnected>,
63 pin_mosi: P0_09<Disconnected>,
64) -> Result<(), FlashError> {
65 let spi = Spi::new(
66 spi1,
67 Pins {
68 sck: Some(pin_sck.into_push_pull_output(Level::Low).degrade()),
69 mosi: Some(pin_mosi.into_push_pull_output(Level::Low).degrade()),
70 miso: Some(pin_miso.into_floating_input().degrade()),
71 },
72 Frequency::M4,
73 MODE_0,
74 );
75 let pin_wp = pin_wp.into_push_pull_output(Level::High);
76 let pin_hold = pin_hold.into_push_pull_output(Level::High);
77 let pin_cs = pin_cs.into_push_pull_output(Level::High);
78
79 FLASH.modify(|spi_flash| {
80 spi_flash.initialize(SpiFlash {
81 spi,
82 _pin_wp: pin_wp,
83 _pin_hold: pin_hold,
84 pin_cs,
85 });
86 });
87
88 flash_enable_wsr()?;
89 flash_set_wrsr()?;
90 flash_chip_erase()?;
91 flash_write_enable()?;
92 Ok(())
93}
94
95fn spi_master_tx(tx_data: &[u8]) -> Result<(), FlashError> {
97 assert_ne!(tx_data.len(), 0);
98
99 let guard = unsafe { FLASH.no_critical_section_lock_mut() };
101
102 guard.pin_cs.set_low()?;
104
105 block!(guard.spi.send(tx_data[0]))?;
106 for i in 0..tx_data.len() - 1 {
107 block!(guard.spi.send(tx_data[i + 1]))?;
108 let _ = block!(guard.spi.read())?;
109 }
110 let _ = block!(guard.spi.read())?;
111
112 guard.pin_cs.set_high()?;
114 Ok(())
115}
116
117fn spi_master_tx_rx_fast_read(tx_data: [u8; 4], rx_data: &mut [u8]) -> Result<(), FlashError> {
119 assert_ne!(rx_data.len(), 0);
120
121 let guard = unsafe { FLASH.no_critical_section_lock_mut() };
123
124 guard.pin_cs.set_low()?;
126
127 for byte in tx_data {
128 block!(guard.spi.send(byte))?;
129 let _ = block!(guard.spi.read())?;
130 }
131
132 for byte in rx_data {
133 block!(guard.spi.send(0))?;
134 *byte = block!(guard.spi.read())?;
135 }
136
137 guard.pin_cs.set_high()?;
139
140 Ok(())
141}
142
143fn spi_master_tx_rx_fast_write(tx_data: [u8; 4], bytes: &[u8]) -> Result<(), FlashError> {
145 assert_ne!(bytes.len(), 0);
146
147 let mut bytes_written: u32 = 0;
148 let address: u32 =
149 u32::from(tx_data[3]) + (u32::from(tx_data[2]) << 8) + (u32::from(tx_data[1]) << 16);
150
151 let guard = unsafe { FLASH.no_critical_section_lock_mut() };
153
154 guard.pin_cs.set_low()?;
156
157 for byte in tx_data {
158 block!(guard.spi.send(byte))?;
159 let _ = block!(guard.spi.read())?;
160 }
161
162 block!(guard.spi.send(bytes[0]))?;
164 let _ = block!(guard.spi.read())?;
165
166 guard.pin_cs.set_high()?;
168
169 for i in 1..bytes.len() {
170 delay_us_assembly(15);
171
172 guard.pin_cs.set_low()?;
174 block!(guard.spi.send(AAI))?;
175 let _ = block!(guard.spi.read())?;
176
177 block!(guard.spi.send(bytes[i]))?;
178 let _ = block!(guard.spi.read())?;
179
180 bytes_written += 1;
181
182 guard.pin_cs.set_high()?;
184
185 if address + bytes_written >= 0x1FFFF && i < bytes.len() - 1 {
186 return Err(FlashError::OutOfSpace);
187 }
188 }
189
190 delay_us_assembly(20);
191
192 guard.pin_cs.set_low()?;
194
195 block!(guard.spi.send(WRDI))?;
197 let _ = block!(guard.spi.read())?;
198
199 guard.pin_cs.set_high()?;
201
202 Ok(())
203}
204
205fn flash_write_enable() -> Result<(), FlashError> {
207 spi_master_tx(&[WREN])
208}
209
210pub fn flash_chip_erase() -> Result<(), FlashError> {
217 flash_write_enable()?;
218 spi_master_tx(&[CHIP_ERASE])?;
219 delay_ms_assembly(100);
220 Ok(())
221}
222
223fn flash_enable_wsr() -> Result<(), FlashError> {
225 spi_master_tx(&[EWSR])
226}
227
228fn flash_set_wrsr() -> Result<(), FlashError> {
230 spi_master_tx(&[WRSR, 0x00])
231}
232
233pub fn flash_write_byte(address: u32, byte: u8) -> Result<(), FlashError> {
245 flash_write_enable()?;
246 spi_master_tx(&[
247 BYTEWRITE,
248 address.to_ne_bytes()[2],
249 address.to_ne_bytes()[1],
250 address.to_ne_bytes()[0],
251 byte,
252 0x00,
253 ])?;
254 delay_us_assembly(20);
255 Ok(())
256}
257
258pub fn flash_write_bytes(address: u32, bytes: &[u8]) -> Result<(), FlashError> {
271 flash_write_enable()?;
272 spi_master_tx_rx_fast_write(
273 [
274 AAI,
275 address.to_ne_bytes()[2],
276 address.to_ne_bytes()[1],
277 address.to_ne_bytes()[0],
278 ],
279 bytes,
280 )?;
281 Ok(())
282}
283
284pub fn flash_read_byte(address: u32) -> Result<u8, FlashError> {
291 let mut rx_data = [0];
292 spi_master_tx_rx_fast_read(
293 [
294 BYTEREAD,
295 address.to_ne_bytes()[2],
296 address.to_ne_bytes()[1],
297 address.to_ne_bytes()[0],
298 ],
299 &mut rx_data,
300 )?;
301 Ok(rx_data[0])
302}
303
304pub fn flash_read_bytes(address: u32, buffer: &mut [u8]) -> Result<(), FlashError> {
312 spi_master_tx_rx_fast_read(
313 [
314 BYTEREAD,
315 address.to_ne_bytes()[2],
316 address.to_ne_bytes()[1],
317 address.to_ne_bytes()[0],
318 ],
319 buffer,
320 )?;
321 Ok(())
322}