diff options
| -rw-r--r-- | embassy-nrf/Cargo.toml | 3 | ||||
| -rw-r--r-- | embassy-nrf/src/qspi.rs | 231 | ||||
| -rw-r--r-- | examples/nrf/src/bin/qspi.rs | 5 | ||||
| -rw-r--r-- | examples/nrf/src/bin/qspi_lowpower.rs | 5 |
4 files changed, 207 insertions, 37 deletions
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 858ff1f6e..5299c04a8 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml | |||
| @@ -18,7 +18,7 @@ flavors = [ | |||
| 18 | [features] | 18 | [features] |
| 19 | 19 | ||
| 20 | # Enable nightly-only features | 20 | # Enable nightly-only features |
| 21 | nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async", "embassy-usb"] | 21 | nightly = ["embassy/nightly", "embedded-hal-1", "embedded-hal-async", "embassy-usb", "embedded-storage-async"] |
| 22 | 22 | ||
| 23 | # Reexport the PAC for the currently enabled chip at `embassy_nrf::pac`. | 23 | # Reexport the PAC for the currently enabled chip at `embassy_nrf::pac`. |
| 24 | # This is unstable because semver-minor (non-breaking) releases of embassy-nrf may major-bump (breaking) the PAC version. | 24 | # This is unstable because semver-minor (non-breaking) releases of embassy-nrf may major-bump (breaking) the PAC version. |
| @@ -80,6 +80,7 @@ critical-section = "0.2.5" | |||
| 80 | rand_core = "0.6.3" | 80 | rand_core = "0.6.3" |
| 81 | fixed = "1.10.0" | 81 | fixed = "1.10.0" |
| 82 | embedded-storage = "0.3.0" | 82 | embedded-storage = "0.3.0" |
| 83 | embedded-storage-async = { version = "0.3.0", optional = true } | ||
| 83 | cfg-if = "1.0.0" | 84 | cfg-if = "1.0.0" |
| 84 | 85 | ||
| 85 | nrf52805-pac = { version = "0.11.0", optional = true, features = [ "rt" ] } | 86 | nrf52805-pac = { version = "0.11.0", optional = true, features = [ "rt" ] } |
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs index 89262ac05..8902879f8 100644 --- a/embassy-nrf/src/qspi.rs +++ b/embassy-nrf/src/qspi.rs | |||
| @@ -60,16 +60,18 @@ impl Default for Config { | |||
| 60 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 60 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 61 | #[non_exhaustive] | 61 | #[non_exhaustive] |
| 62 | pub enum Error { | 62 | pub enum Error { |
| 63 | OutOfBounds, | ||
| 63 | // TODO add "not in data memory" error and check for it | 64 | // TODO add "not in data memory" error and check for it |
| 64 | } | 65 | } |
| 65 | 66 | ||
| 66 | pub struct Qspi<'d, T: Instance> { | 67 | pub struct Qspi<'d, T: Instance, const FLASH_SIZE: usize> { |
| 68 | irq: T::Interrupt, | ||
| 67 | dpm_enabled: bool, | 69 | dpm_enabled: bool, |
| 68 | phantom: PhantomData<&'d mut T>, | 70 | phantom: PhantomData<&'d mut T>, |
| 69 | } | 71 | } |
| 70 | 72 | ||
| 71 | impl<'d, T: Instance> Qspi<'d, T> { | 73 | impl<'d, T: Instance, const FLASH_SIZE: usize> Qspi<'d, T, FLASH_SIZE> { |
| 72 | pub async fn new( | 74 | pub fn new( |
| 73 | _qspi: impl Unborrow<Target = T> + 'd, | 75 | _qspi: impl Unborrow<Target = T> + 'd, |
| 74 | irq: impl Unborrow<Target = T::Interrupt> + 'd, | 76 | irq: impl Unborrow<Target = T::Interrupt> + 'd, |
| 75 | sck: impl Unborrow<Target = impl GpioPin> + 'd, | 77 | sck: impl Unborrow<Target = impl GpioPin> + 'd, |
| @@ -79,7 +81,7 @@ impl<'d, T: Instance> Qspi<'d, T> { | |||
| 79 | io2: impl Unborrow<Target = impl GpioPin> + 'd, | 81 | io2: impl Unborrow<Target = impl GpioPin> + 'd, |
| 80 | io3: impl Unborrow<Target = impl GpioPin> + 'd, | 82 | io3: impl Unborrow<Target = impl GpioPin> + 'd, |
| 81 | config: Config, | 83 | config: Config, |
| 82 | ) -> Qspi<'d, T> { | 84 | ) -> Qspi<'d, T, FLASH_SIZE> { |
| 83 | unborrow!(irq, sck, csn, io0, io1, io2, io3); | 85 | unborrow!(irq, sck, csn, io0, io1, io2, io3); |
| 84 | 86 | ||
| 85 | let r = T::regs(); | 87 | let r = T::regs(); |
| @@ -142,6 +144,7 @@ impl<'d, T: Instance> Qspi<'d, T> { | |||
| 142 | 144 | ||
| 143 | let mut res = Self { | 145 | let mut res = Self { |
| 144 | dpm_enabled: config.deep_power_down.is_some(), | 146 | dpm_enabled: config.deep_power_down.is_some(), |
| 147 | irq, | ||
| 145 | phantom: PhantomData, | 148 | phantom: PhantomData, |
| 146 | }; | 149 | }; |
| 147 | 150 | ||
| @@ -150,7 +153,7 @@ impl<'d, T: Instance> Qspi<'d, T> { | |||
| 150 | 153 | ||
| 151 | r.tasks_activate.write(|w| w.tasks_activate().bit(true)); | 154 | r.tasks_activate.write(|w| w.tasks_activate().bit(true)); |
| 152 | 155 | ||
| 153 | res.wait_ready().await; | 156 | res.blocking_wait_ready(); |
| 154 | 157 | ||
| 155 | res | 158 | res |
| 156 | } | 159 | } |
| @@ -173,8 +176,36 @@ impl<'d, T: Instance> Qspi<'d, T> { | |||
| 173 | ) -> Result<(), Error> { | 176 | ) -> Result<(), Error> { |
| 174 | let bomb = DropBomb::new(); | 177 | let bomb = DropBomb::new(); |
| 175 | 178 | ||
| 179 | let len = core::cmp::max(req.len(), resp.len()) as u8; | ||
| 180 | self.custom_instruction_start(opcode, req, len)?; | ||
| 181 | |||
| 182 | self.wait_ready().await; | ||
| 183 | |||
| 184 | self.custom_instruction_finish(resp)?; | ||
| 185 | |||
| 186 | bomb.defuse(); | ||
| 187 | |||
| 188 | Ok(()) | ||
| 189 | } | ||
| 190 | |||
| 191 | pub fn blocking_custom_instruction( | ||
| 192 | &mut self, | ||
| 193 | opcode: u8, | ||
| 194 | req: &[u8], | ||
| 195 | resp: &mut [u8], | ||
| 196 | ) -> Result<(), Error> { | ||
| 197 | let len = core::cmp::max(req.len(), resp.len()) as u8; | ||
| 198 | self.custom_instruction_start(opcode, req, len)?; | ||
| 199 | |||
| 200 | self.blocking_wait_ready(); | ||
| 201 | |||
| 202 | self.custom_instruction_finish(resp)?; | ||
| 203 | |||
| 204 | Ok(()) | ||
| 205 | } | ||
| 206 | |||
| 207 | fn custom_instruction_start(&mut self, opcode: u8, req: &[u8], len: u8) -> Result<(), Error> { | ||
| 176 | assert!(req.len() <= 8); | 208 | assert!(req.len() <= 8); |
| 177 | assert!(resp.len() <= 8); | ||
| 178 | 209 | ||
| 179 | let mut dat0: u32 = 0; | 210 | let mut dat0: u32 = 0; |
| 180 | let mut dat1: u32 = 0; | 211 | let mut dat1: u32 = 0; |
| @@ -190,8 +221,6 @@ impl<'d, T: Instance> Qspi<'d, T> { | |||
| 190 | } | 221 | } |
| 191 | } | 222 | } |
| 192 | 223 | ||
| 193 | let len = core::cmp::max(req.len(), resp.len()) as u8; | ||
| 194 | |||
| 195 | let r = T::regs(); | 224 | let r = T::regs(); |
| 196 | r.cinstrdat0.write(|w| unsafe { w.bits(dat0) }); | 225 | r.cinstrdat0.write(|w| unsafe { w.bits(dat0) }); |
| 197 | r.cinstrdat1.write(|w| unsafe { w.bits(dat1) }); | 226 | r.cinstrdat1.write(|w| unsafe { w.bits(dat1) }); |
| @@ -210,9 +239,10 @@ impl<'d, T: Instance> Qspi<'d, T> { | |||
| 210 | let w = w.lfstop().bit(false); | 239 | let w = w.lfstop().bit(false); |
| 211 | w | 240 | w |
| 212 | }); | 241 | }); |
| 242 | Ok(()) | ||
| 243 | } | ||
| 213 | 244 | ||
| 214 | self.wait_ready().await; | 245 | fn custom_instruction_finish(&mut self, resp: &mut [u8]) -> Result<(), Error> { |
| 215 | |||
| 216 | let r = T::regs(); | 246 | let r = T::regs(); |
| 217 | 247 | ||
| 218 | let dat0 = r.cinstrdat0.read().bits(); | 248 | let dat0 = r.cinstrdat0.read().bits(); |
| @@ -227,9 +257,6 @@ impl<'d, T: Instance> Qspi<'d, T> { | |||
| 227 | resp[i] = (dat1 >> (i * 8)) as u8; | 257 | resp[i] = (dat1 >> (i * 8)) as u8; |
| 228 | } | 258 | } |
| 229 | } | 259 | } |
| 230 | |||
| 231 | bomb.defuse(); | ||
| 232 | |||
| 233 | Ok(()) | 260 | Ok(()) |
| 234 | } | 261 | } |
| 235 | 262 | ||
| @@ -246,12 +273,22 @@ impl<'d, T: Instance> Qspi<'d, T> { | |||
| 246 | .await | 273 | .await |
| 247 | } | 274 | } |
| 248 | 275 | ||
| 249 | pub async fn read(&mut self, address: usize, data: &mut [u8]) -> Result<(), Error> { | 276 | fn blocking_wait_ready(&mut self) { |
| 250 | let bomb = DropBomb::new(); | 277 | loop { |
| 278 | let r = T::regs(); | ||
| 279 | if r.events_ready.read().bits() != 0 { | ||
| 280 | break; | ||
| 281 | } | ||
| 282 | } | ||
| 283 | } | ||
| 251 | 284 | ||
| 285 | fn start_read(&mut self, address: usize, data: &mut [u8]) -> Result<(), Error> { | ||
| 252 | assert_eq!(data.as_ptr() as u32 % 4, 0); | 286 | assert_eq!(data.as_ptr() as u32 % 4, 0); |
| 253 | assert_eq!(data.len() as u32 % 4, 0); | 287 | assert_eq!(data.len() as u32 % 4, 0); |
| 254 | assert_eq!(address as u32 % 4, 0); | 288 | assert_eq!(address as u32 % 4, 0); |
| 289 | if address > FLASH_SIZE { | ||
| 290 | return Err(Error::OutOfBounds); | ||
| 291 | } | ||
| 255 | 292 | ||
| 256 | let r = T::regs(); | 293 | let r = T::regs(); |
| 257 | 294 | ||
| @@ -269,19 +306,20 @@ impl<'d, T: Instance> Qspi<'d, T> { | |||
| 269 | r.intenset.write(|w| w.ready().set()); | 306 | r.intenset.write(|w| w.ready().set()); |
| 270 | r.tasks_readstart.write(|w| w.tasks_readstart().bit(true)); | 307 | r.tasks_readstart.write(|w| w.tasks_readstart().bit(true)); |
| 271 | 308 | ||
| 272 | self.wait_ready().await; | ||
| 273 | |||
| 274 | bomb.defuse(); | ||
| 275 | |||
| 276 | Ok(()) | 309 | Ok(()) |
| 277 | } | 310 | } |
| 278 | 311 | ||
| 279 | pub async fn write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> { | 312 | fn start_write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> { |
| 280 | let bomb = DropBomb::new(); | 313 | //info!("start_write ptr {}", data.as_ptr() as u32); |
| 281 | |||
| 282 | assert_eq!(data.as_ptr() as u32 % 4, 0); | 314 | assert_eq!(data.as_ptr() as u32 % 4, 0); |
| 315 | //info!("start_write OK ptr"); | ||
| 283 | assert_eq!(data.len() as u32 % 4, 0); | 316 | assert_eq!(data.len() as u32 % 4, 0); |
| 317 | //info!("start_write OK len"); | ||
| 284 | assert_eq!(address as u32 % 4, 0); | 318 | assert_eq!(address as u32 % 4, 0); |
| 319 | //info!("start_write OK addr"); | ||
| 320 | if address > FLASH_SIZE { | ||
| 321 | return Err(Error::OutOfBounds); | ||
| 322 | } | ||
| 285 | 323 | ||
| 286 | let r = T::regs(); | 324 | let r = T::regs(); |
| 287 | r.write | 325 | r.write |
| @@ -298,17 +336,14 @@ impl<'d, T: Instance> Qspi<'d, T> { | |||
| 298 | r.intenset.write(|w| w.ready().set()); | 336 | r.intenset.write(|w| w.ready().set()); |
| 299 | r.tasks_writestart.write(|w| w.tasks_writestart().bit(true)); | 337 | r.tasks_writestart.write(|w| w.tasks_writestart().bit(true)); |
| 300 | 338 | ||
| 301 | self.wait_ready().await; | ||
| 302 | |||
| 303 | bomb.defuse(); | ||
| 304 | |||
| 305 | Ok(()) | 339 | Ok(()) |
| 306 | } | 340 | } |
| 307 | 341 | ||
| 308 | pub async fn erase(&mut self, address: usize) -> Result<(), Error> { | 342 | fn start_erase(&mut self, address: usize) -> Result<(), Error> { |
| 309 | let bomb = DropBomb::new(); | ||
| 310 | |||
| 311 | assert_eq!(address as u32 % 4096, 0); | 343 | assert_eq!(address as u32 % 4096, 0); |
| 344 | if address > FLASH_SIZE { | ||
| 345 | return Err(Error::OutOfBounds); | ||
| 346 | } | ||
| 312 | 347 | ||
| 313 | let r = T::regs(); | 348 | let r = T::regs(); |
| 314 | r.erase | 349 | r.erase |
| @@ -320,15 +355,65 @@ impl<'d, T: Instance> Qspi<'d, T> { | |||
| 320 | r.intenset.write(|w| w.ready().set()); | 355 | r.intenset.write(|w| w.ready().set()); |
| 321 | r.tasks_erasestart.write(|w| w.tasks_erasestart().bit(true)); | 356 | r.tasks_erasestart.write(|w| w.tasks_erasestart().bit(true)); |
| 322 | 357 | ||
| 358 | Ok(()) | ||
| 359 | } | ||
| 360 | |||
| 361 | pub async fn read(&mut self, address: usize, data: &mut [u8]) -> Result<(), Error> { | ||
| 362 | let bomb = DropBomb::new(); | ||
| 363 | |||
| 364 | self.start_read(address, data)?; | ||
| 323 | self.wait_ready().await; | 365 | self.wait_ready().await; |
| 324 | 366 | ||
| 325 | bomb.defuse(); | 367 | bomb.defuse(); |
| 326 | 368 | ||
| 327 | Ok(()) | 369 | Ok(()) |
| 328 | } | 370 | } |
| 371 | |||
| 372 | pub async fn write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> { | ||
| 373 | let bomb = DropBomb::new(); | ||
| 374 | |||
| 375 | //info!("WRITE {} bytes at {}", data.len(), address); | ||
| 376 | self.start_write(address, data)?; | ||
| 377 | //info!("STARTED"); | ||
| 378 | self.wait_ready().await; | ||
| 379 | //info!("WRITE DONE"); | ||
| 380 | |||
| 381 | bomb.defuse(); | ||
| 382 | |||
| 383 | Ok(()) | ||
| 384 | } | ||
| 385 | |||
| 386 | pub async fn erase(&mut self, address: usize) -> Result<(), Error> { | ||
| 387 | let bomb = DropBomb::new(); | ||
| 388 | |||
| 389 | self.start_erase(address)?; | ||
| 390 | self.wait_ready().await; | ||
| 391 | |||
| 392 | bomb.defuse(); | ||
| 393 | |||
| 394 | Ok(()) | ||
| 395 | } | ||
| 396 | |||
| 397 | pub fn blocking_read(&mut self, address: usize, data: &mut [u8]) -> Result<(), Error> { | ||
| 398 | self.start_read(address, data)?; | ||
| 399 | self.blocking_wait_ready(); | ||
| 400 | Ok(()) | ||
| 401 | } | ||
| 402 | |||
| 403 | pub fn blocking_write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> { | ||
| 404 | self.start_write(address, data)?; | ||
| 405 | self.blocking_wait_ready(); | ||
| 406 | Ok(()) | ||
| 407 | } | ||
| 408 | |||
| 409 | pub fn blocking_erase(&mut self, address: usize) -> Result<(), Error> { | ||
| 410 | self.start_erase(address)?; | ||
| 411 | self.blocking_wait_ready(); | ||
| 412 | Ok(()) | ||
| 413 | } | ||
| 329 | } | 414 | } |
| 330 | 415 | ||
| 331 | impl<'d, T: Instance> Drop for Qspi<'d, T> { | 416 | impl<'d, T: Instance, const FLASH_SIZE: usize> Drop for Qspi<'d, T, FLASH_SIZE> { |
| 332 | fn drop(&mut self) { | 417 | fn drop(&mut self) { |
| 333 | let r = T::regs(); | 418 | let r = T::regs(); |
| 334 | 419 | ||
| @@ -358,6 +443,8 @@ impl<'d, T: Instance> Drop for Qspi<'d, T> { | |||
| 358 | 443 | ||
| 359 | r.enable.write(|w| w.enable().disabled()); | 444 | r.enable.write(|w| w.enable().disabled()); |
| 360 | 445 | ||
| 446 | self.irq.disable(); | ||
| 447 | |||
| 361 | // Note: we do NOT deconfigure CSN here. If DPM is in use and we disconnect CSN, | 448 | // Note: we do NOT deconfigure CSN here. If DPM is in use and we disconnect CSN, |
| 362 | // leaving it floating, the flash chip might read it as zero which would cause it to | 449 | // leaving it floating, the flash chip might read it as zero which would cause it to |
| 363 | // spuriously exit DPM. | 450 | // spuriously exit DPM. |
| @@ -371,6 +458,90 @@ impl<'d, T: Instance> Drop for Qspi<'d, T> { | |||
| 371 | } | 458 | } |
| 372 | } | 459 | } |
| 373 | 460 | ||
| 461 | use embedded_storage::nor_flash::{ | ||
| 462 | ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash, | ||
| 463 | }; | ||
| 464 | |||
| 465 | impl<'d, T: Instance, const FLASH_SIZE: usize> ErrorType for Qspi<'d, T, FLASH_SIZE> { | ||
| 466 | type Error = Error; | ||
| 467 | } | ||
| 468 | |||
| 469 | impl NorFlashError for Error { | ||
| 470 | fn kind(&self) -> NorFlashErrorKind { | ||
| 471 | NorFlashErrorKind::Other | ||
| 472 | } | ||
| 473 | } | ||
| 474 | |||
| 475 | impl<'d, T: Instance, const FLASH_SIZE: usize> ReadNorFlash for Qspi<'d, T, FLASH_SIZE> { | ||
| 476 | const READ_SIZE: usize = 4; | ||
| 477 | |||
| 478 | fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { | ||
| 479 | self.blocking_read(offset as usize, bytes)?; | ||
| 480 | Ok(()) | ||
| 481 | } | ||
| 482 | |||
| 483 | fn capacity(&self) -> usize { | ||
| 484 | FLASH_SIZE | ||
| 485 | } | ||
| 486 | } | ||
| 487 | |||
| 488 | impl<'d, T: Instance, const FLASH_SIZE: usize> NorFlash for Qspi<'d, T, FLASH_SIZE> { | ||
| 489 | const WRITE_SIZE: usize = 4; | ||
| 490 | const ERASE_SIZE: usize = 4096; | ||
| 491 | |||
| 492 | fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { | ||
| 493 | for address in (from as usize..to as usize).step_by(<Self as NorFlash>::ERASE_SIZE) { | ||
| 494 | self.blocking_erase(address)?; | ||
| 495 | } | ||
| 496 | Ok(()) | ||
| 497 | } | ||
| 498 | |||
| 499 | fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { | ||
| 500 | self.blocking_write(offset as usize, bytes)?; | ||
| 501 | Ok(()) | ||
| 502 | } | ||
| 503 | } | ||
| 504 | |||
| 505 | cfg_if::cfg_if! { | ||
| 506 | if #[cfg(feature = "nightly")] | ||
| 507 | { | ||
| 508 | use embedded_storage_async::nor_flash::{AsyncNorFlash, AsyncReadNorFlash}; | ||
| 509 | use core::future::Future; | ||
| 510 | |||
| 511 | impl<'d, T: Instance, const FLASH_SIZE: usize> AsyncNorFlash for Qspi<'d, T, FLASH_SIZE> { | ||
| 512 | const WRITE_SIZE: usize = <Self as NorFlash>::WRITE_SIZE; | ||
| 513 | const ERASE_SIZE: usize = <Self as NorFlash>::ERASE_SIZE; | ||
| 514 | |||
| 515 | type WriteFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; | ||
| 516 | fn write<'a>(&'a mut self, offset: u32, data: &'a [u8]) -> Self::WriteFuture<'a> { | ||
| 517 | async move { self.write(offset as usize, data).await } | ||
| 518 | } | ||
| 519 | |||
| 520 | type EraseFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; | ||
| 521 | fn erase<'a>(&'a mut self, from: u32, to: u32) -> Self::EraseFuture<'a> { | ||
| 522 | async move { | ||
| 523 | for address in (from as usize..to as usize).step_by(<Self as AsyncNorFlash>::ERASE_SIZE) { | ||
| 524 | self.erase(address).await? | ||
| 525 | } | ||
| 526 | Ok(()) | ||
| 527 | } | ||
| 528 | } | ||
| 529 | } | ||
| 530 | |||
| 531 | impl<'d, T: Instance, const FLASH_SIZE: usize> AsyncReadNorFlash for Qspi<'d, T, FLASH_SIZE> { | ||
| 532 | const READ_SIZE: usize = 4; | ||
| 533 | type ReadFuture<'a> = impl Future<Output = Result<(), Self::Error>> + 'a where Self: 'a; | ||
| 534 | fn read<'a>(&'a mut self, address: u32, data: &'a mut [u8]) -> Self::ReadFuture<'a> { | ||
| 535 | async move { self.read(address as usize, data).await } | ||
| 536 | } | ||
| 537 | |||
| 538 | fn capacity(&self) -> usize { | ||
| 539 | FLASH_SIZE | ||
| 540 | } | ||
| 541 | } | ||
| 542 | } | ||
| 543 | } | ||
| 544 | |||
| 374 | pub(crate) mod sealed { | 545 | pub(crate) mod sealed { |
| 375 | use embassy::waitqueue::AtomicWaker; | 546 | use embassy::waitqueue::AtomicWaker; |
| 376 | 547 | ||
diff --git a/examples/nrf/src/bin/qspi.rs b/examples/nrf/src/bin/qspi.rs index ba60716c8..8673b7961 100644 --- a/examples/nrf/src/bin/qspi.rs +++ b/examples/nrf/src/bin/qspi.rs | |||
| @@ -26,10 +26,9 @@ async fn main(_spawner: Spawner, p: Peripherals) { | |||
| 26 | config.write_page_size = qspi::WritePageSize::_256BYTES; | 26 | config.write_page_size = qspi::WritePageSize::_256BYTES; |
| 27 | 27 | ||
| 28 | let irq = interrupt::take!(QSPI); | 28 | let irq = interrupt::take!(QSPI); |
| 29 | let mut q = qspi::Qspi::new( | 29 | let mut q: qspi::Qspi<_, 67108864> = qspi::Qspi::new( |
| 30 | p.QSPI, irq, p.P0_19, p.P0_17, p.P0_20, p.P0_21, p.P0_22, p.P0_23, config, | 30 | p.QSPI, irq, p.P0_19, p.P0_17, p.P0_20, p.P0_21, p.P0_22, p.P0_23, config, |
| 31 | ) | 31 | ); |
| 32 | .await; | ||
| 33 | 32 | ||
| 34 | let mut id = [1; 3]; | 33 | let mut id = [1; 3]; |
| 35 | unwrap!(q.custom_instruction(0x9F, &[], &mut id).await); | 34 | unwrap!(q.custom_instruction(0x9F, &[], &mut id).await); |
diff --git a/examples/nrf/src/bin/qspi_lowpower.rs b/examples/nrf/src/bin/qspi_lowpower.rs index a8184cd63..255ce5d5e 100644 --- a/examples/nrf/src/bin/qspi_lowpower.rs +++ b/examples/nrf/src/bin/qspi_lowpower.rs | |||
| @@ -32,7 +32,7 @@ async fn main(_spawner: Spawner, mut p: Peripherals) { | |||
| 32 | exit_time: 3, // tRDP = 35uS | 32 | exit_time: 3, // tRDP = 35uS |
| 33 | }); | 33 | }); |
| 34 | 34 | ||
| 35 | let mut q = qspi::Qspi::new( | 35 | let mut q: qspi::Qspi<_, 67108864> = qspi::Qspi::new( |
| 36 | &mut p.QSPI, | 36 | &mut p.QSPI, |
| 37 | &mut irq, | 37 | &mut irq, |
| 38 | &mut p.P0_19, | 38 | &mut p.P0_19, |
| @@ -42,8 +42,7 @@ async fn main(_spawner: Spawner, mut p: Peripherals) { | |||
| 42 | &mut p.P0_22, | 42 | &mut p.P0_22, |
| 43 | &mut p.P0_23, | 43 | &mut p.P0_23, |
| 44 | config, | 44 | config, |
| 45 | ) | 45 | ); |
| 46 | .await; | ||
| 47 | 46 | ||
| 48 | let mut id = [1; 3]; | 47 | let mut id = [1; 3]; |
| 49 | unwrap!(q.custom_instruction(0x9F, &[], &mut id).await); | 48 | unwrap!(q.custom_instruction(0x9F, &[], &mut id).await); |
