diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-03-05 03:19:11 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-03-05 03:19:11 +0100 |
| commit | bf013be9ba51c50ff6ad16b38dede08387b4e117 (patch) | |
| tree | c46141ee3f07f011bd74e90a7990a15c9fccc72d /embassy-nrf | |
| parent | d91efe3e6252336a6e226700ca72afef2e13abc0 (diff) | |
| parent | f7dfc49c5c40d70852d6d3c7313973adf97e4716 (diff) | |
Merge pull request #1232 from embassy-rs/nrf-qspi-fixes
nrf/qspi: nrf53 support, u32 addrs, remove const generic, add raw read/write.
Diffstat (limited to 'embassy-nrf')
| -rw-r--r-- | embassy-nrf/src/chips/nrf5340_app.rs | 5 | ||||
| -rw-r--r-- | embassy-nrf/src/lib.rs | 2 | ||||
| -rw-r--r-- | embassy-nrf/src/qspi.rs | 242 |
3 files changed, 155 insertions, 94 deletions
diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs index 2e1c7f384..9c7b738e6 100644 --- a/embassy-nrf/src/chips/nrf5340_app.rs +++ b/embassy-nrf/src/chips/nrf5340_app.rs | |||
| @@ -250,6 +250,9 @@ embassy_hal_common::peripherals! { | |||
| 250 | TIMER1, | 250 | TIMER1, |
| 251 | TIMER2, | 251 | TIMER2, |
| 252 | 252 | ||
| 253 | // QSPI | ||
| 254 | QSPI, | ||
| 255 | |||
| 253 | // GPIOTE | 256 | // GPIOTE |
| 254 | GPIOTE_CH0, | 257 | GPIOTE_CH0, |
| 255 | GPIOTE_CH1, | 258 | GPIOTE_CH1, |
| @@ -393,6 +396,8 @@ impl_timer!(TIMER0, TIMER0, TIMER0); | |||
| 393 | impl_timer!(TIMER1, TIMER1, TIMER1); | 396 | impl_timer!(TIMER1, TIMER1, TIMER1); |
| 394 | impl_timer!(TIMER2, TIMER2, TIMER2); | 397 | impl_timer!(TIMER2, TIMER2, TIMER2); |
| 395 | 398 | ||
| 399 | impl_qspi!(QSPI, QSPI, QSPI); | ||
| 400 | |||
| 396 | impl_pin!(P0_00, 0, 0); | 401 | impl_pin!(P0_00, 0, 0); |
| 397 | impl_pin!(P0_01, 0, 1); | 402 | impl_pin!(P0_01, 0, 1); |
| 398 | #[cfg(feature = "nfc-pins-as-gpio")] | 403 | #[cfg(feature = "nfc-pins-as-gpio")] |
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 6b7dc7791..3c5db5c7c 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs | |||
| @@ -57,7 +57,7 @@ pub mod ppi; | |||
| 57 | pub mod pwm; | 57 | pub mod pwm; |
| 58 | #[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340")))] | 58 | #[cfg(not(any(feature = "nrf51", feature = "_nrf9160", feature = "_nrf5340")))] |
| 59 | pub mod qdec; | 59 | pub mod qdec; |
| 60 | #[cfg(feature = "nrf52840")] | 60 | #[cfg(any(feature = "nrf52840", feature = "_nrf5340-app"))] |
| 61 | pub mod qspi; | 61 | pub mod qspi; |
| 62 | #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] | 62 | #[cfg(not(any(feature = "_nrf5340", feature = "_nrf9160")))] |
| 63 | pub mod rng; | 63 | pub mod rng; |
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs index d434327fc..d514e0274 100644 --- a/embassy-nrf/src/qspi.rs +++ b/embassy-nrf/src/qspi.rs | |||
| @@ -8,6 +8,7 @@ use core::task::Poll; | |||
| 8 | 8 | ||
| 9 | use embassy_hal_common::drop::OnDrop; | 9 | use embassy_hal_common::drop::OnDrop; |
| 10 | use embassy_hal_common::{into_ref, PeripheralRef}; | 10 | use embassy_hal_common::{into_ref, PeripheralRef}; |
| 11 | use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; | ||
| 11 | 12 | ||
| 12 | use crate::gpio::{self, Pin as GpioPin}; | 13 | use crate::gpio::{self, Pin as GpioPin}; |
| 13 | use crate::interrupt::{Interrupt, InterruptExt}; | 14 | use crate::interrupt::{Interrupt, InterruptExt}; |
| @@ -82,6 +83,8 @@ pub struct Config { | |||
| 82 | pub spi_mode: SpiMode, | 83 | pub spi_mode: SpiMode, |
| 83 | /// Addressing mode (24-bit or 32-bit) | 84 | /// Addressing mode (24-bit or 32-bit) |
| 84 | pub address_mode: AddressMode, | 85 | pub address_mode: AddressMode, |
| 86 | /// Flash memory capacity in bytes. This is the value reported by the `embedded-storage` traits. | ||
| 87 | pub capacity: u32, | ||
| 85 | } | 88 | } |
| 86 | 89 | ||
| 87 | impl Default for Config { | 90 | impl Default for Config { |
| @@ -96,6 +99,7 @@ impl Default for Config { | |||
| 96 | sck_delay: 80, | 99 | sck_delay: 80, |
| 97 | spi_mode: SpiMode::MODE0, | 100 | spi_mode: SpiMode::MODE0, |
| 98 | address_mode: AddressMode::_24BIT, | 101 | address_mode: AddressMode::_24BIT, |
| 102 | capacity: 0, | ||
| 99 | } | 103 | } |
| 100 | } | 104 | } |
| 101 | } | 105 | } |
| @@ -111,12 +115,13 @@ pub enum Error { | |||
| 111 | } | 115 | } |
| 112 | 116 | ||
| 113 | /// QSPI flash driver. | 117 | /// QSPI flash driver. |
| 114 | pub struct Qspi<'d, T: Instance, const FLASH_SIZE: usize> { | 118 | pub struct Qspi<'d, T: Instance> { |
| 115 | irq: PeripheralRef<'d, T::Interrupt>, | 119 | irq: PeripheralRef<'d, T::Interrupt>, |
| 116 | dpm_enabled: bool, | 120 | dpm_enabled: bool, |
| 121 | capacity: u32, | ||
| 117 | } | 122 | } |
| 118 | 123 | ||
| 119 | impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> { | 124 | impl<'d, T: Instance> Qspi<'d, T> { |
| 120 | /// Create a new QSPI driver. | 125 | /// Create a new QSPI driver. |
| 121 | pub fn new( | 126 | pub fn new( |
| 122 | _qspi: impl Peripheral<P = T> + 'd, | 127 | _qspi: impl Peripheral<P = T> + 'd, |
| @@ -128,30 +133,31 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> { | |||
| 128 | io2: impl Peripheral<P = impl GpioPin> + 'd, | 133 | io2: impl Peripheral<P = impl GpioPin> + 'd, |
| 129 | io3: impl Peripheral<P = impl GpioPin> + 'd, | 134 | io3: impl Peripheral<P = impl GpioPin> + 'd, |
| 130 | config: Config, | 135 | config: Config, |
| 131 | ) -> Qspi<'d, T, FLASH_SIZE> { | 136 | ) -> Self { |
| 132 | into_ref!(irq, sck, csn, io0, io1, io2, io3); | 137 | into_ref!(irq, sck, csn, io0, io1, io2, io3); |
| 133 | 138 | ||
| 134 | let r = T::regs(); | 139 | let r = T::regs(); |
| 135 | 140 | ||
| 136 | sck.set_high(); | 141 | macro_rules! config_pin { |
| 137 | csn.set_high(); | 142 | ($pin:ident) => { |
| 138 | io0.set_high(); | 143 | $pin.set_high(); |
| 139 | io1.set_high(); | 144 | $pin.conf().write(|w| { |
| 140 | io2.set_high(); | 145 | w.dir().output(); |
| 141 | io3.set_high(); | 146 | w.drive().h0h1(); |
| 142 | sck.conf().write(|w| w.dir().output().drive().h0h1()); | 147 | #[cfg(feature = "_nrf5340-s")] |
| 143 | csn.conf().write(|w| w.dir().output().drive().h0h1()); | 148 | w.mcusel().peripheral(); |
| 144 | io0.conf().write(|w| w.dir().output().drive().h0h1()); | 149 | w |
| 145 | io1.conf().write(|w| w.dir().output().drive().h0h1()); | 150 | }); |
| 146 | io2.conf().write(|w| w.dir().output().drive().h0h1()); | 151 | r.psel.$pin.write(|w| unsafe { w.bits($pin.psel_bits()) }); |
| 147 | io3.conf().write(|w| w.dir().output().drive().h0h1()); | 152 | }; |
| 148 | 153 | } | |
| 149 | r.psel.sck.write(|w| unsafe { w.bits(sck.psel_bits()) }); | 154 | |
| 150 | r.psel.csn.write(|w| unsafe { w.bits(csn.psel_bits()) }); | 155 | config_pin!(sck); |
| 151 | r.psel.io0.write(|w| unsafe { w.bits(io0.psel_bits()) }); | 156 | config_pin!(csn); |
| 152 | r.psel.io1.write(|w| unsafe { w.bits(io1.psel_bits()) }); | 157 | config_pin!(io0); |
| 153 | r.psel.io2.write(|w| unsafe { w.bits(io2.psel_bits()) }); | 158 | config_pin!(io1); |
| 154 | r.psel.io3.write(|w| unsafe { w.bits(io3.psel_bits()) }); | 159 | config_pin!(io2); |
| 160 | config_pin!(io3); | ||
| 155 | 161 | ||
| 156 | r.ifconfig0.write(|w| { | 162 | r.ifconfig0.write(|w| { |
| 157 | w.addrmode().variant(config.address_mode); | 163 | w.addrmode().variant(config.address_mode); |
| @@ -193,6 +199,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> { | |||
| 193 | let res = Self { | 199 | let res = Self { |
| 194 | dpm_enabled: config.deep_power_down.is_some(), | 200 | dpm_enabled: config.deep_power_down.is_some(), |
| 195 | irq, | 201 | irq, |
| 202 | capacity: config.capacity, | ||
| 196 | }; | 203 | }; |
| 197 | 204 | ||
| 198 | r.events_ready.reset(); | 205 | r.events_ready.reset(); |
| @@ -321,17 +328,15 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> { | |||
| 321 | } | 328 | } |
| 322 | } | 329 | } |
| 323 | 330 | ||
| 324 | fn start_read(&mut self, address: usize, data: &mut [u8]) -> Result<(), Error> { | 331 | fn start_read(&mut self, address: u32, data: &mut [u8]) -> Result<(), Error> { |
| 332 | // TODO: Return these as errors instead. | ||
| 325 | assert_eq!(data.as_ptr() as u32 % 4, 0); | 333 | assert_eq!(data.as_ptr() as u32 % 4, 0); |
| 326 | assert_eq!(data.len() as u32 % 4, 0); | 334 | assert_eq!(data.len() as u32 % 4, 0); |
| 327 | assert_eq!(address as u32 % 4, 0); | 335 | assert_eq!(address % 4, 0); |
| 328 | if address > FLASH_SIZE { | ||
| 329 | return Err(Error::OutOfBounds); | ||
| 330 | } | ||
| 331 | 336 | ||
| 332 | let r = T::regs(); | 337 | let r = T::regs(); |
| 333 | 338 | ||
| 334 | r.read.src.write(|w| unsafe { w.src().bits(address as u32) }); | 339 | r.read.src.write(|w| unsafe { w.src().bits(address) }); |
| 335 | r.read.dst.write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) }); | 340 | r.read.dst.write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) }); |
| 336 | r.read.cnt.write(|w| unsafe { w.cnt().bits(data.len() as u32) }); | 341 | r.read.cnt.write(|w| unsafe { w.cnt().bits(data.len() as u32) }); |
| 337 | 342 | ||
| @@ -342,18 +347,15 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> { | |||
| 342 | Ok(()) | 347 | Ok(()) |
| 343 | } | 348 | } |
| 344 | 349 | ||
| 345 | fn start_write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> { | 350 | fn start_write(&mut self, address: u32, data: &[u8]) -> Result<(), Error> { |
| 351 | // TODO: Return these as errors instead. | ||
| 346 | assert_eq!(data.as_ptr() as u32 % 4, 0); | 352 | assert_eq!(data.as_ptr() as u32 % 4, 0); |
| 347 | assert_eq!(data.len() as u32 % 4, 0); | 353 | assert_eq!(data.len() as u32 % 4, 0); |
| 348 | assert_eq!(address as u32 % 4, 0); | 354 | assert_eq!(address % 4, 0); |
| 349 | |||
| 350 | if address > FLASH_SIZE { | ||
| 351 | return Err(Error::OutOfBounds); | ||
| 352 | } | ||
| 353 | 355 | ||
| 354 | let r = T::regs(); | 356 | let r = T::regs(); |
| 355 | r.write.src.write(|w| unsafe { w.src().bits(data.as_ptr() as u32) }); | 357 | r.write.src.write(|w| unsafe { w.src().bits(data.as_ptr() as u32) }); |
| 356 | r.write.dst.write(|w| unsafe { w.dst().bits(address as u32) }); | 358 | r.write.dst.write(|w| unsafe { w.dst().bits(address) }); |
| 357 | r.write.cnt.write(|w| unsafe { w.cnt().bits(data.len() as u32) }); | 359 | r.write.cnt.write(|w| unsafe { w.cnt().bits(data.len() as u32) }); |
| 358 | 360 | ||
| 359 | r.events_ready.reset(); | 361 | r.events_ready.reset(); |
| @@ -363,14 +365,12 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> { | |||
| 363 | Ok(()) | 365 | Ok(()) |
| 364 | } | 366 | } |
| 365 | 367 | ||
| 366 | fn start_erase(&mut self, address: usize) -> Result<(), Error> { | 368 | fn start_erase(&mut self, address: u32) -> Result<(), Error> { |
| 367 | assert_eq!(address as u32 % 4096, 0); | 369 | // TODO: Return these as errors instead. |
| 368 | if address > FLASH_SIZE { | 370 | assert_eq!(address % 4096, 0); |
| 369 | return Err(Error::OutOfBounds); | ||
| 370 | } | ||
| 371 | 371 | ||
| 372 | let r = T::regs(); | 372 | let r = T::regs(); |
| 373 | r.erase.ptr.write(|w| unsafe { w.ptr().bits(address as u32) }); | 373 | r.erase.ptr.write(|w| unsafe { w.ptr().bits(address) }); |
| 374 | r.erase.len.write(|w| w.len()._4kb()); | 374 | r.erase.len.write(|w| w.len()._4kb()); |
| 375 | 375 | ||
| 376 | r.events_ready.reset(); | 376 | r.events_ready.reset(); |
| @@ -380,8 +380,12 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> { | |||
| 380 | Ok(()) | 380 | Ok(()) |
| 381 | } | 381 | } |
| 382 | 382 | ||
| 383 | /// Read data from the flash memory. | 383 | /// Raw QSPI read. |
| 384 | pub async fn read(&mut self, address: usize, data: &mut [u8]) -> Result<(), Error> { | 384 | /// |
| 385 | /// The difference with `read` is that this does not do bounds checks | ||
| 386 | /// against the flash capacity. It is intended for use when QSPI is used as | ||
| 387 | /// a raw bus, not with flash memory. | ||
| 388 | pub async fn read_raw(&mut self, address: u32, data: &mut [u8]) -> Result<(), Error> { | ||
| 385 | let ondrop = OnDrop::new(Self::blocking_wait_ready); | 389 | let ondrop = OnDrop::new(Self::blocking_wait_ready); |
| 386 | 390 | ||
| 387 | self.start_read(address, data)?; | 391 | self.start_read(address, data)?; |
| @@ -392,8 +396,12 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> { | |||
| 392 | Ok(()) | 396 | Ok(()) |
| 393 | } | 397 | } |
| 394 | 398 | ||
| 395 | /// Write data to the flash memory. | 399 | /// Raw QSPI write. |
| 396 | pub async fn write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> { | 400 | /// |
| 401 | /// The difference with `write` is that this does not do bounds checks | ||
| 402 | /// against the flash capacity. It is intended for use when QSPI is used as | ||
| 403 | /// a raw bus, not with flash memory. | ||
| 404 | pub async fn write_raw(&mut self, address: u32, data: &[u8]) -> Result<(), Error> { | ||
| 397 | let ondrop = OnDrop::new(Self::blocking_wait_ready); | 405 | let ondrop = OnDrop::new(Self::blocking_wait_ready); |
| 398 | 406 | ||
| 399 | self.start_write(address, data)?; | 407 | self.start_write(address, data)?; |
| @@ -404,8 +412,46 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> { | |||
| 404 | Ok(()) | 412 | Ok(()) |
| 405 | } | 413 | } |
| 406 | 414 | ||
| 415 | /// Raw QSPI read, blocking version. | ||
| 416 | /// | ||
| 417 | /// The difference with `blocking_read` is that this does not do bounds checks | ||
| 418 | /// against the flash capacity. It is intended for use when QSPI is used as | ||
| 419 | /// a raw bus, not with flash memory. | ||
| 420 | pub fn blocking_read_raw(&mut self, address: u32, data: &mut [u8]) -> Result<(), Error> { | ||
| 421 | self.start_read(address, data)?; | ||
| 422 | Self::blocking_wait_ready(); | ||
| 423 | Ok(()) | ||
| 424 | } | ||
| 425 | |||
| 426 | /// Raw QSPI write, blocking version. | ||
| 427 | /// | ||
| 428 | /// The difference with `blocking_write` is that this does not do bounds checks | ||
| 429 | /// against the flash capacity. It is intended for use when QSPI is used as | ||
| 430 | /// a raw bus, not with flash memory. | ||
| 431 | pub fn blocking_write_raw(&mut self, address: u32, data: &[u8]) -> Result<(), Error> { | ||
| 432 | self.start_write(address, data)?; | ||
| 433 | Self::blocking_wait_ready(); | ||
| 434 | Ok(()) | ||
| 435 | } | ||
| 436 | |||
| 437 | /// Read data from the flash memory. | ||
| 438 | pub async fn read(&mut self, address: u32, data: &mut [u8]) -> Result<(), Error> { | ||
| 439 | self.bounds_check(address, data.len())?; | ||
| 440 | self.read_raw(address, data).await | ||
| 441 | } | ||
| 442 | |||
| 443 | /// Write data to the flash memory. | ||
| 444 | pub async fn write(&mut self, address: u32, data: &[u8]) -> Result<(), Error> { | ||
| 445 | self.bounds_check(address, data.len())?; | ||
| 446 | self.write_raw(address, data).await | ||
| 447 | } | ||
| 448 | |||
| 407 | /// Erase a sector on the flash memory. | 449 | /// Erase a sector on the flash memory. |
| 408 | pub async fn erase(&mut self, address: usize) -> Result<(), Error> { | 450 | pub async fn erase(&mut self, address: u32) -> Result<(), Error> { |
| 451 | if address >= self.capacity { | ||
| 452 | return Err(Error::OutOfBounds); | ||
| 453 | } | ||
| 454 | |||
| 409 | let ondrop = OnDrop::new(Self::blocking_wait_ready); | 455 | let ondrop = OnDrop::new(Self::blocking_wait_ready); |
| 410 | 456 | ||
| 411 | self.start_erase(address)?; | 457 | self.start_erase(address)?; |
| @@ -417,28 +463,39 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> { | |||
| 417 | } | 463 | } |
| 418 | 464 | ||
| 419 | /// Read data from the flash memory, blocking version. | 465 | /// Read data from the flash memory, blocking version. |
| 420 | pub fn blocking_read(&mut self, address: usize, data: &mut [u8]) -> Result<(), Error> { | 466 | pub fn blocking_read(&mut self, address: u32, data: &mut [u8]) -> Result<(), Error> { |
| 421 | self.start_read(address, data)?; | 467 | self.bounds_check(address, data.len())?; |
| 422 | Self::blocking_wait_ready(); | 468 | self.blocking_read_raw(address, data) |
| 423 | Ok(()) | ||
| 424 | } | 469 | } |
| 425 | 470 | ||
| 426 | /// Write data to the flash memory, blocking version. | 471 | /// Write data to the flash memory, blocking version. |
| 427 | pub fn blocking_write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> { | 472 | pub fn blocking_write(&mut self, address: u32, data: &[u8]) -> Result<(), Error> { |
| 428 | self.start_write(address, data)?; | 473 | self.bounds_check(address, data.len())?; |
| 429 | Self::blocking_wait_ready(); | 474 | self.blocking_write_raw(address, data) |
| 430 | Ok(()) | ||
| 431 | } | 475 | } |
| 432 | 476 | ||
| 433 | /// Erase a sector on the flash memory, blocking version. | 477 | /// Erase a sector on the flash memory, blocking version. |
| 434 | pub fn blocking_erase(&mut self, address: usize) -> Result<(), Error> { | 478 | pub fn blocking_erase(&mut self, address: u32) -> Result<(), Error> { |
| 479 | if address >= self.capacity { | ||
| 480 | return Err(Error::OutOfBounds); | ||
| 481 | } | ||
| 482 | |||
| 435 | self.start_erase(address)?; | 483 | self.start_erase(address)?; |
| 436 | Self::blocking_wait_ready(); | 484 | Self::blocking_wait_ready(); |
| 437 | Ok(()) | 485 | Ok(()) |
| 438 | } | 486 | } |
| 487 | |||
| 488 | fn bounds_check(&self, address: u32, len: usize) -> Result<(), Error> { | ||
| 489 | let len_u32: u32 = len.try_into().map_err(|_| Error::OutOfBounds)?; | ||
| 490 | let end_address = address.checked_add(len_u32).ok_or(Error::OutOfBounds)?; | ||
| 491 | if end_address > self.capacity { | ||
| 492 | return Err(Error::OutOfBounds); | ||
| 493 | } | ||
| 494 | Ok(()) | ||
| 495 | } | ||
| 439 | } | 496 | } |
| 440 | 497 | ||
| 441 | impl<'d, T: Instance, const FLASH_SIZE: usize> Drop for Qspi<'d, T, FLASH_SIZE> { | 498 | impl<'d, T: Instance> Drop for Qspi<'d, T> { |
| 442 | fn drop(&mut self) { | 499 | fn drop(&mut self) { |
| 443 | let r = T::regs(); | 500 | let r = T::regs(); |
| 444 | 501 | ||
| @@ -483,9 +540,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Drop for Qspi<'d, T, FLASH_SIZE> | |||
| 483 | } | 540 | } |
| 484 | } | 541 | } |
| 485 | 542 | ||
| 486 | use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; | 543 | impl<'d, T: Instance> ErrorType for Qspi<'d, T> { |
| 487 | |||
| 488 | impl<'d, T: Instance, const FLASH_SIZE: usize> ErrorType for Qspi<'d, T, FLASH_SIZE> { | ||
| 489 | type Error = Error; | 544 | type Error = Error; |
| 490 | } | 545 | } |
| 491 | 546 | ||
| @@ -495,72 +550,73 @@ impl NorFlashError for Error { | |||
| 495 | } | 550 | } |
| 496 | } | 551 | } |
| 497 | 552 | ||
| 498 | impl<'d, T: Instance, const FLASH_SIZE: usize> ReadNorFlash for Qspi<'d, T, FLASH_SIZE> { | 553 | impl<'d, T: Instance> ReadNorFlash for Qspi<'d, T> { |
| 499 | const READ_SIZE: usize = 4; | 554 | const READ_SIZE: usize = 4; |
| 500 | 555 | ||
| 501 | fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { | 556 | fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { |
| 502 | self.blocking_read(offset as usize, bytes)?; | 557 | self.blocking_read(offset, bytes)?; |
| 503 | Ok(()) | 558 | Ok(()) |
| 504 | } | 559 | } |
| 505 | 560 | ||
| 506 | fn capacity(&self) -> usize { | 561 | fn capacity(&self) -> usize { |
| 507 | FLASH_SIZE | 562 | self.capacity as usize |
| 508 | } | 563 | } |
| 509 | } | 564 | } |
| 510 | 565 | ||
| 511 | impl<'d, T: Instance, const FLASH_SIZE: usize> NorFlash for Qspi<'d, T, FLASH_SIZE> { | 566 | impl<'d, T: Instance> NorFlash for Qspi<'d, T> { |
| 512 | const WRITE_SIZE: usize = 4; | 567 | const WRITE_SIZE: usize = 4; |
| 513 | const ERASE_SIZE: usize = 4096; | 568 | const ERASE_SIZE: usize = 4096; |
| 514 | 569 | ||
| 515 | fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { | 570 | fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { |
| 516 | for address in (from as usize..to as usize).step_by(<Self as NorFlash>::ERASE_SIZE) { | 571 | for address in (from..to).step_by(<Self as NorFlash>::ERASE_SIZE) { |
| 517 | self.blocking_erase(address)?; | 572 | self.blocking_erase(address)?; |
| 518 | } | 573 | } |
| 519 | Ok(()) | 574 | Ok(()) |
| 520 | } | 575 | } |
| 521 | 576 | ||
| 522 | fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { | 577 | fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { |
| 523 | self.blocking_write(offset as usize, bytes)?; | 578 | self.blocking_write(offset, bytes)?; |
| 524 | Ok(()) | 579 | Ok(()) |
| 525 | } | 580 | } |
| 526 | } | 581 | } |
| 527 | 582 | ||
| 528 | cfg_if::cfg_if! { | 583 | #[cfg(feature = "nightly")] |
| 529 | if #[cfg(feature = "nightly")] | 584 | mod _eh1 { |
| 530 | { | 585 | use core::future::Future; |
| 531 | use embedded_storage_async::nor_flash::{AsyncNorFlash, AsyncReadNorFlash}; | ||
| 532 | use core::future::Future; | ||
| 533 | 586 | ||
| 534 | impl<'d, T: Instance, const FLASH_SIZE: usize> AsyncNorFlash for Qspi<'d, T, FLASH_SIZE> { | 587 | use embedded_storage_async::nor_flash::{AsyncNorFlash, AsyncReadNorFlash}; |
| 535 | const WRITE_SIZE: usize = <Self as NorFlash>::WRITE_SIZE; | ||
| 536 | const ERASE_SIZE: usize = <Self as NorFlash>::ERASE_SIZE; | ||
| 537 | 588 | ||
| 538 | type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; | 589 | use super::*; |
| 539 | fn write<'a>(&'a mut self, offset: u32, data: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 540 | async move { self.write(offset as usize, data).await } | ||
| 541 | } | ||
| 542 | 590 | ||
| 543 | type EraseFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; | 591 | impl<'d, T: Instance> AsyncNorFlash for Qspi<'d, T> { |
| 544 | fn erase<'a>(&'a mut self, from: u32, to: u32) -> Self::EraseFuture<'a> { | 592 | const WRITE_SIZE: usize = <Self as NorFlash>::WRITE_SIZE; |
| 545 | async move { | 593 | const ERASE_SIZE: usize = <Self as NorFlash>::ERASE_SIZE; |
| 546 | for address in (from as usize..to as usize).step_by(<Self as AsyncNorFlash>::ERASE_SIZE) { | 594 | |
| 547 | self.erase(address).await? | 595 | type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; |
| 548 | } | 596 | fn write<'a>(&'a mut self, offset: u32, data: &'a [u8]) -> Self::WriteFuture<'a> { |
| 549 | Ok(()) | 597 | async move { self.write(offset, data).await } |
| 598 | } | ||
| 599 | |||
| 600 | type EraseFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; | ||
| 601 | fn erase<'a>(&'a mut self, from: u32, to: u32) -> Self::EraseFuture<'a> { | ||
| 602 | async move { | ||
| 603 | for address in (from..to).step_by(<Self as AsyncNorFlash>::ERASE_SIZE) { | ||
| 604 | self.erase(address).await? | ||
| 550 | } | 605 | } |
| 606 | Ok(()) | ||
| 551 | } | 607 | } |
| 552 | } | 608 | } |
| 609 | } | ||
| 553 | 610 | ||
| 554 | impl<'d, T: Instance, const FLASH_SIZE: usize> AsyncReadNorFlash for Qspi<'d, T, FLASH_SIZE> { | 611 | impl<'d, T: Instance> AsyncReadNorFlash for Qspi<'d, T> { |
| 555 | const READ_SIZE: usize = 4; | 612 | const READ_SIZE: usize = 4; |
| 556 | type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; | 613 | type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; |
| 557 | fn read<'a>(&'a mut self, address: u32, data: &'a mut [u8]) -> Self::ReadFuture<'a> { | 614 | fn read<'a>(&'a mut self, address: u32, data: &'a mut [u8]) -> Self::ReadFuture<'a> { |
| 558 | async move { self.read(address as usize, data).await } | 615 | async move { self.read(address, data).await } |
| 559 | } | 616 | } |
| 560 | 617 | ||
| 561 | fn capacity(&self) -> usize { | 618 | fn capacity(&self) -> usize { |
| 562 | FLASH_SIZE | 619 | self.capacity as usize |
| 563 | } | ||
| 564 | } | 620 | } |
| 565 | } | 621 | } |
| 566 | } | 622 | } |
