diff options
| author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-08-01 15:40:05 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-08-01 15:40:05 +0000 |
| commit | a903215423e463ec08c13e9831fbbefca2f9c6fa (patch) | |
| tree | 89972c7f931918743d8a60e7f1330dccfaf350b4 | |
| parent | 2b0786129aacb0c5089e74415f45617bbf07a3eb (diff) | |
| parent | 43b8c0c71ebbae6b0cbcb867fb90d6903e577ddf (diff) | |
Merge #888
888: Extend QSPI config with freq, delay, spi mode, and address mode r=Dirbaio a=TilBlechschmidt
Fixes #886 among some of the TODOs which have been flying around in the source file :)
I'll make one more commit to remove some old commented out code from the file and take some time this evening to verify that it works.
Co-authored-by: Til Blechschmidt <[email protected]>
| -rw-r--r-- | embassy-nrf/src/qspi.rs | 56 |
1 files changed, 35 insertions, 21 deletions
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs index cedf88de5..6d7ebb4b1 100644 --- a/embassy-nrf/src/qspi.rs +++ b/embassy-nrf/src/qspi.rs | |||
| @@ -12,18 +12,9 @@ use crate::interrupt::{Interrupt, InterruptExt}; | |||
| 12 | pub use crate::pac::qspi::ifconfig0::{ | 12 | pub use crate::pac::qspi::ifconfig0::{ |
| 13 | ADDRMODE_A as AddressMode, PPSIZE_A as WritePageSize, READOC_A as ReadOpcode, WRITEOC_A as WriteOpcode, | 13 | ADDRMODE_A as AddressMode, PPSIZE_A as WritePageSize, READOC_A as ReadOpcode, WRITEOC_A as WriteOpcode, |
| 14 | }; | 14 | }; |
| 15 | pub use crate::pac::qspi::ifconfig1::SPIMODE_A as SpiMode; | ||
| 15 | use crate::{pac, Peripheral}; | 16 | use crate::{pac, Peripheral}; |
| 16 | 17 | ||
| 17 | // TODO | ||
| 18 | // - config: | ||
| 19 | // - 32bit address mode | ||
| 20 | // - SPI freq | ||
| 21 | // - SPI sck delay | ||
| 22 | // - Deep power down mode (DPM) | ||
| 23 | // - SPI mode 3 | ||
| 24 | // - activate/deactivate | ||
| 25 | // - set gpio in high drive | ||
| 26 | |||
| 27 | pub struct DeepPowerDownConfig { | 18 | pub struct DeepPowerDownConfig { |
| 28 | /// Time required for entering DPM, in units of 16us | 19 | /// Time required for entering DPM, in units of 16us |
| 29 | pub enter_time: u16, | 20 | pub enter_time: u16, |
| @@ -31,6 +22,25 @@ pub struct DeepPowerDownConfig { | |||
| 31 | pub exit_time: u16, | 22 | pub exit_time: u16, |
| 32 | } | 23 | } |
| 33 | 24 | ||
| 25 | pub enum Frequency { | ||
| 26 | M32 = 0, | ||
| 27 | M16 = 1, | ||
| 28 | M10_7 = 2, | ||
| 29 | M8 = 3, | ||
| 30 | M6_4 = 4, | ||
| 31 | M5_3 = 5, | ||
| 32 | M4_6 = 6, | ||
| 33 | M4 = 7, | ||
| 34 | M3_6 = 8, | ||
| 35 | M3_2 = 9, | ||
| 36 | M2_9 = 10, | ||
| 37 | M2_7 = 11, | ||
| 38 | M2_5 = 12, | ||
| 39 | M2_3 = 13, | ||
| 40 | M2_1 = 14, | ||
| 41 | M2 = 15, | ||
| 42 | } | ||
| 43 | |||
| 34 | #[non_exhaustive] | 44 | #[non_exhaustive] |
| 35 | pub struct Config { | 45 | pub struct Config { |
| 36 | pub xip_offset: u32, | 46 | pub xip_offset: u32, |
| @@ -38,6 +48,12 @@ pub struct Config { | |||
| 38 | pub write_opcode: WriteOpcode, | 48 | pub write_opcode: WriteOpcode, |
| 39 | pub write_page_size: WritePageSize, | 49 | pub write_page_size: WritePageSize, |
| 40 | pub deep_power_down: Option<DeepPowerDownConfig>, | 50 | pub deep_power_down: Option<DeepPowerDownConfig>, |
| 51 | pub frequency: Frequency, | ||
| 52 | /// Value is specified in number of 16 MHz periods (62.5 ns) | ||
| 53 | pub sck_delay: u8, | ||
| 54 | /// Whether data is captured on the clock rising edge and data is output on a falling edge (MODE0) or vice-versa (MODE3) | ||
| 55 | pub spi_mode: SpiMode, | ||
| 56 | pub address_mode: AddressMode, | ||
| 41 | } | 57 | } |
| 42 | 58 | ||
| 43 | impl Default for Config { | 59 | impl Default for Config { |
| @@ -48,6 +64,10 @@ impl Default for Config { | |||
| 48 | xip_offset: 0, | 64 | xip_offset: 0, |
| 49 | write_page_size: WritePageSize::_256BYTES, | 65 | write_page_size: WritePageSize::_256BYTES, |
| 50 | deep_power_down: None, | 66 | deep_power_down: None, |
| 67 | frequency: Frequency::M8, | ||
| 68 | sck_delay: 80, | ||
| 69 | spi_mode: SpiMode::MODE0, | ||
| 70 | address_mode: AddressMode::_24BIT, | ||
| 51 | } | 71 | } |
| 52 | } | 72 | } |
| 53 | } | 73 | } |
| @@ -102,7 +122,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> { | |||
| 102 | r.psel.io3.write(|w| unsafe { w.bits(io3.psel_bits()) }); | 122 | r.psel.io3.write(|w| unsafe { w.bits(io3.psel_bits()) }); |
| 103 | 123 | ||
| 104 | r.ifconfig0.write(|w| { | 124 | r.ifconfig0.write(|w| { |
| 105 | w.addrmode().variant(AddressMode::_24BIT); | 125 | w.addrmode().variant(config.address_mode); |
| 106 | w.dpmenable().bit(config.deep_power_down.is_some()); | 126 | w.dpmenable().bit(config.deep_power_down.is_some()); |
| 107 | w.ppsize().variant(config.write_page_size); | 127 | w.ppsize().variant(config.write_page_size); |
| 108 | w.readoc().variant(config.read_opcode); | 128 | w.readoc().variant(config.read_opcode); |
| @@ -119,10 +139,10 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> { | |||
| 119 | } | 139 | } |
| 120 | 140 | ||
| 121 | r.ifconfig1.write(|w| unsafe { | 141 | r.ifconfig1.write(|w| unsafe { |
| 122 | w.sckdelay().bits(80); | 142 | w.sckdelay().bits(config.sck_delay); |
| 123 | w.dpmen().exit(); | 143 | w.dpmen().exit(); |
| 124 | w.spimode().mode0(); | 144 | w.spimode().variant(config.spi_mode); |
| 125 | w.sckfreq().bits(3); | 145 | w.sckfreq().bits(config.frequency as u8); |
| 126 | w | 146 | w |
| 127 | }); | 147 | }); |
| 128 | 148 | ||
| @@ -289,13 +309,10 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> { | |||
| 289 | } | 309 | } |
| 290 | 310 | ||
| 291 | fn start_write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> { | 311 | fn start_write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> { |
| 292 | //info!("start_write ptr {}", data.as_ptr() as u32); | ||
| 293 | assert_eq!(data.as_ptr() as u32 % 4, 0); | 312 | assert_eq!(data.as_ptr() as u32 % 4, 0); |
| 294 | //info!("start_write OK ptr"); | ||
| 295 | assert_eq!(data.len() as u32 % 4, 0); | 313 | assert_eq!(data.len() as u32 % 4, 0); |
| 296 | //info!("start_write OK len"); | ||
| 297 | assert_eq!(address as u32 % 4, 0); | 314 | assert_eq!(address as u32 % 4, 0); |
| 298 | //info!("start_write OK addr"); | 315 | |
| 299 | if address > FLASH_SIZE { | 316 | if address > FLASH_SIZE { |
| 300 | return Err(Error::OutOfBounds); | 317 | return Err(Error::OutOfBounds); |
| 301 | } | 318 | } |
| @@ -343,11 +360,8 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> { | |||
| 343 | pub async fn write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> { | 360 | pub async fn write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> { |
| 344 | let bomb = DropBomb::new(); | 361 | let bomb = DropBomb::new(); |
| 345 | 362 | ||
| 346 | //info!("WRITE {} bytes at {}", data.len(), address); | ||
| 347 | self.start_write(address, data)?; | 363 | self.start_write(address, data)?; |
| 348 | //info!("STARTED"); | ||
| 349 | self.wait_ready().await; | 364 | self.wait_ready().await; |
| 350 | //info!("WRITE DONE"); | ||
| 351 | 365 | ||
| 352 | bomb.defuse(); | 366 | bomb.defuse(); |
| 353 | 367 | ||
