aboutsummaryrefslogtreecommitdiff
path: root/embassy-nrf
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-09-27 21:18:29 +0200
committerDario Nieuwenhuis <[email protected]>2025-09-28 21:05:37 +0200
commit19fdd8d96c778697610386c829f6a0a655c39940 (patch)
treea5e209048d1252def5f75e8051022da02e6dc338 /embassy-nrf
parent6a262521811a435f2cfedd7e25fb70a1aab957ca (diff)
nrf/qspi: erase instance generics
Diffstat (limited to 'embassy-nrf')
-rwxr-xr-xembassy-nrf/src/qspi.rs109
1 files changed, 52 insertions, 57 deletions
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs
index e6e829f6e..94ad3f0d6 100755
--- a/embassy-nrf/src/qspi.rs
+++ b/embassy-nrf/src/qspi.rs
@@ -138,16 +138,18 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
138} 138}
139 139
140/// QSPI flash driver. 140/// QSPI flash driver.
141pub struct Qspi<'d, T: Instance> { 141pub struct Qspi<'d> {
142 _peri: Peri<'d, T>, 142 r: pac::qspi::Qspi,
143 state: &'static State,
143 dpm_enabled: bool, 144 dpm_enabled: bool,
144 capacity: u32, 145 capacity: u32,
146 _phantom: PhantomData<&'d ()>,
145} 147}
146 148
147impl<'d, T: Instance> Qspi<'d, T> { 149impl<'d> Qspi<'d> {
148 /// Create a new QSPI driver. 150 /// Create a new QSPI driver.
149 pub fn new( 151 pub fn new<T: Instance>(
150 qspi: Peri<'d, T>, 152 _qspi: Peri<'d, T>,
151 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 153 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
152 sck: Peri<'d, impl GpioPin>, 154 sck: Peri<'d, impl GpioPin>,
153 csn: Peri<'d, impl GpioPin>, 155 csn: Peri<'d, impl GpioPin>,
@@ -214,9 +216,11 @@ impl<'d, T: Instance> Qspi<'d, T> {
214 r.enable().write(|w| w.set_enable(true)); 216 r.enable().write(|w| w.set_enable(true));
215 217
216 let res = Self { 218 let res = Self {
217 _peri: qspi, 219 r: T::regs(),
220 state: T::state(),
218 dpm_enabled: config.deep_power_down.is_some(), 221 dpm_enabled: config.deep_power_down.is_some(),
219 capacity: config.capacity, 222 capacity: config.capacity,
223 _phantom: PhantomData,
220 }; 224 };
221 225
222 r.events_ready().write_value(0); 226 r.events_ready().write_value(0);
@@ -274,14 +278,13 @@ impl<'d, T: Instance> Qspi<'d, T> {
274 } 278 }
275 } 279 }
276 280
277 let r = T::regs(); 281 self.r.cinstrdat0().write(|w| w.0 = dat0);
278 r.cinstrdat0().write(|w| w.0 = dat0); 282 self.r.cinstrdat1().write(|w| w.0 = dat1);
279 r.cinstrdat1().write(|w| w.0 = dat1);
280 283
281 r.events_ready().write_value(0); 284 self.r.events_ready().write_value(0);
282 r.intenset().write(|w| w.set_ready(true)); 285 self.r.intenset().write(|w| w.set_ready(true));
283 286
284 r.cinstrconf().write(|w| { 287 self.r.cinstrconf().write(|w| {
285 w.set_opcode(opcode); 288 w.set_opcode(opcode);
286 w.set_length(vals::Length::from_bits(len + 1)); 289 w.set_length(vals::Length::from_bits(len + 1));
287 w.set_lio2(true); 290 w.set_lio2(true);
@@ -295,10 +298,8 @@ impl<'d, T: Instance> Qspi<'d, T> {
295 } 298 }
296 299
297 fn custom_instruction_finish(&mut self, resp: &mut [u8]) -> Result<(), Error> { 300 fn custom_instruction_finish(&mut self, resp: &mut [u8]) -> Result<(), Error> {
298 let r = T::regs(); 301 let dat0 = self.r.cinstrdat0().read().0;
299 302 let dat1 = self.r.cinstrdat1().read().0;
300 let dat0 = r.cinstrdat0().read().0;
301 let dat1 = r.cinstrdat1().read().0;
302 for i in 0..4 { 303 for i in 0..4 {
303 if i < resp.len() { 304 if i < resp.len() {
304 resp[i] = (dat0 >> (i * 8)) as u8; 305 resp[i] = (dat0 >> (i * 8)) as u8;
@@ -313,9 +314,9 @@ impl<'d, T: Instance> Qspi<'d, T> {
313 } 314 }
314 315
315 fn wait_ready(&mut self) -> impl Future<Output = ()> { 316 fn wait_ready(&mut self) -> impl Future<Output = ()> {
317 let r = self.r;
318 let s = self.state;
316 poll_fn(move |cx| { 319 poll_fn(move |cx| {
317 let r = T::regs();
318 let s = T::state();
319 s.waker.register(cx.waker()); 320 s.waker.register(cx.waker());
320 if r.events_ready().read() != 0 { 321 if r.events_ready().read() != 0 {
321 return Poll::Ready(()); 322 return Poll::Ready(());
@@ -326,7 +327,7 @@ impl<'d, T: Instance> Qspi<'d, T> {
326 327
327 fn blocking_wait_ready() { 328 fn blocking_wait_ready() {
328 loop { 329 loop {
329 let r = T::regs(); 330 let r = pac::QSPI;
330 if r.events_ready().read() != 0 { 331 if r.events_ready().read() != 0 {
331 break; 332 break;
332 } 333 }
@@ -339,15 +340,13 @@ impl<'d, T: Instance> Qspi<'d, T> {
339 assert_eq!(data.len() as u32 % 4, 0); 340 assert_eq!(data.len() as u32 % 4, 0);
340 assert_eq!(address % 4, 0); 341 assert_eq!(address % 4, 0);
341 342
342 let r = T::regs(); 343 self.r.read().src().write_value(address);
343 344 self.r.read().dst().write_value(data.as_ptr() as u32);
344 r.read().src().write_value(address); 345 self.r.read().cnt().write(|w| w.set_cnt(data.len() as u32));
345 r.read().dst().write_value(data.as_ptr() as u32);
346 r.read().cnt().write(|w| w.set_cnt(data.len() as u32));
347 346
348 r.events_ready().write_value(0); 347 self.r.events_ready().write_value(0);
349 r.intenset().write(|w| w.set_ready(true)); 348 self.r.intenset().write(|w| w.set_ready(true));
350 r.tasks_readstart().write_value(1); 349 self.r.tasks_readstart().write_value(1);
351 350
352 Ok(()) 351 Ok(())
353 } 352 }
@@ -358,14 +357,13 @@ impl<'d, T: Instance> Qspi<'d, T> {
358 assert_eq!(data.len() as u32 % 4, 0); 357 assert_eq!(data.len() as u32 % 4, 0);
359 assert_eq!(address % 4, 0); 358 assert_eq!(address % 4, 0);
360 359
361 let r = T::regs(); 360 self.r.write().src().write_value(data.as_ptr() as u32);
362 r.write().src().write_value(data.as_ptr() as u32); 361 self.r.write().dst().write_value(address);
363 r.write().dst().write_value(address); 362 self.r.write().cnt().write(|w| w.set_cnt(data.len() as u32));
364 r.write().cnt().write(|w| w.set_cnt(data.len() as u32));
365 363
366 r.events_ready().write_value(0); 364 self.r.events_ready().write_value(0);
367 r.intenset().write(|w| w.set_ready(true)); 365 self.r.intenset().write(|w| w.set_ready(true));
368 r.tasks_writestart().write_value(1); 366 self.r.tasks_writestart().write_value(1);
369 367
370 Ok(()) 368 Ok(())
371 } 369 }
@@ -374,13 +372,12 @@ impl<'d, T: Instance> Qspi<'d, T> {
374 // TODO: Return these as errors instead. 372 // TODO: Return these as errors instead.
375 assert_eq!(address % 4096, 0); 373 assert_eq!(address % 4096, 0);
376 374
377 let r = T::regs(); 375 self.r.erase().ptr().write_value(address);
378 r.erase().ptr().write_value(address); 376 self.r.erase().len().write(|w| w.set_len(vals::Len::_4KB));
379 r.erase().len().write(|w| w.set_len(vals::Len::_4KB));
380 377
381 r.events_ready().write_value(0); 378 self.r.events_ready().write_value(0);
382 r.intenset().write(|w| w.set_ready(true)); 379 self.r.intenset().write(|w| w.set_ready(true));
383 r.tasks_erasestart().write_value(1); 380 self.r.tasks_erasestart().write_value(1);
384 381
385 Ok(()) 382 Ok(())
386 } 383 }
@@ -520,19 +517,17 @@ impl<'d, T: Instance> Qspi<'d, T> {
520 } 517 }
521} 518}
522 519
523impl<'d, T: Instance> Drop for Qspi<'d, T> { 520impl<'d> Drop for Qspi<'d> {
524 fn drop(&mut self) { 521 fn drop(&mut self) {
525 let r = T::regs();
526
527 if self.dpm_enabled { 522 if self.dpm_enabled {
528 trace!("qspi: doing deep powerdown..."); 523 trace!("qspi: doing deep powerdown...");
529 524
530 r.ifconfig1().modify(|w| w.set_dpmen(true)); 525 self.r.ifconfig1().modify(|w| w.set_dpmen(true));
531 526
532 // Wait for DPM enter. 527 // Wait for DPM enter.
533 // Unfortunately we must spin. There's no way to do this interrupt-driven. 528 // Unfortunately we must spin. There's no way to do this interrupt-driven.
534 // The READY event does NOT fire on DPM enter (but it does fire on DPM exit :shrug:) 529 // The READY event does NOT fire on DPM enter (but it does fire on DPM exit :shrug:)
535 while !r.status().read().dpm() {} 530 while !self.r.status().read().dpm() {}
536 531
537 // Wait MORE for DPM enter. 532 // Wait MORE for DPM enter.
538 // I have absolutely no idea why, but the wait above is not enough :'( 533 // I have absolutely no idea why, but the wait above is not enough :'(
@@ -541,29 +536,29 @@ impl<'d, T: Instance> Drop for Qspi<'d, T> {
541 } 536 }
542 537
543 // it seems events_ready is not generated in response to deactivate. nrfx doesn't wait for it. 538 // it seems events_ready is not generated in response to deactivate. nrfx doesn't wait for it.
544 r.tasks_deactivate().write_value(1); 539 self.r.tasks_deactivate().write_value(1);
545 540
546 // Workaround https://docs.nordicsemi.com/bundle/errata_nRF52840_Rev3/page/ERR/nRF52840/Rev3/latest/anomaly_840_122.html 541 // Workaround https://docs.nordicsemi.com/bundle/errata_nRF52840_Rev3/page/ERR/nRF52840/Rev3/latest/anomaly_840_122.html
547 // Note that the doc has 2 register writes, but the first one is really the write to tasks_deactivate, 542 // Note that the doc has 2 register writes, but the first one is really the write to tasks_deactivate,
548 // so we only do the second one here. 543 // so we only do the second one here.
549 unsafe { ptr::write_volatile(0x40029054 as *mut u32, 1) } 544 unsafe { ptr::write_volatile(0x40029054 as *mut u32, 1) }
550 545
551 r.enable().write(|w| w.set_enable(false)); 546 self.r.enable().write(|w| w.set_enable(false));
552 547
553 // Note: we do NOT deconfigure CSN here. If DPM is in use and we disconnect CSN, 548 // Note: we do NOT deconfigure CSN here. If DPM is in use and we disconnect CSN,
554 // leaving it floating, the flash chip might read it as zero which would cause it to 549 // leaving it floating, the flash chip might read it as zero which would cause it to
555 // spuriously exit DPM. 550 // spuriously exit DPM.
556 gpio::deconfigure_pin(r.psel().sck().read()); 551 gpio::deconfigure_pin(self.r.psel().sck().read());
557 gpio::deconfigure_pin(r.psel().io0().read()); 552 gpio::deconfigure_pin(self.r.psel().io0().read());
558 gpio::deconfigure_pin(r.psel().io1().read()); 553 gpio::deconfigure_pin(self.r.psel().io1().read());
559 gpio::deconfigure_pin(r.psel().io2().read()); 554 gpio::deconfigure_pin(self.r.psel().io2().read());
560 gpio::deconfigure_pin(r.psel().io3().read()); 555 gpio::deconfigure_pin(self.r.psel().io3().read());
561 556
562 trace!("qspi: dropped"); 557 trace!("qspi: dropped");
563 } 558 }
564} 559}
565 560
566impl<'d, T: Instance> ErrorType for Qspi<'d, T> { 561impl<'d> ErrorType for Qspi<'d> {
567 type Error = Error; 562 type Error = Error;
568} 563}
569 564
@@ -573,7 +568,7 @@ impl NorFlashError for Error {
573 } 568 }
574} 569}
575 570
576impl<'d, T: Instance> ReadNorFlash for Qspi<'d, T> { 571impl<'d> ReadNorFlash for Qspi<'d> {
577 const READ_SIZE: usize = 4; 572 const READ_SIZE: usize = 4;
578 573
579 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { 574 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
@@ -586,7 +581,7 @@ impl<'d, T: Instance> ReadNorFlash for Qspi<'d, T> {
586 } 581 }
587} 582}
588 583
589impl<'d, T: Instance> NorFlash for Qspi<'d, T> { 584impl<'d> NorFlash for Qspi<'d> {
590 const WRITE_SIZE: usize = 4; 585 const WRITE_SIZE: usize = 4;
591 const ERASE_SIZE: usize = 4096; 586 const ERASE_SIZE: usize = 4096;
592 587
@@ -611,7 +606,7 @@ mod _eh1 {
611 606
612 use super::*; 607 use super::*;
613 608
614 impl<'d, T: Instance> AsyncNorFlash for Qspi<'d, T> { 609 impl<'d> AsyncNorFlash for Qspi<'d> {
615 const WRITE_SIZE: usize = <Self as NorFlash>::WRITE_SIZE; 610 const WRITE_SIZE: usize = <Self as NorFlash>::WRITE_SIZE;
616 const ERASE_SIZE: usize = <Self as NorFlash>::ERASE_SIZE; 611 const ERASE_SIZE: usize = <Self as NorFlash>::ERASE_SIZE;
617 612
@@ -627,7 +622,7 @@ mod _eh1 {
627 } 622 }
628 } 623 }
629 624
630 impl<'d, T: Instance> AsyncReadNorFlash for Qspi<'d, T> { 625 impl<'d> AsyncReadNorFlash for Qspi<'d> {
631 const READ_SIZE: usize = 4; 626 const READ_SIZE: usize = 4;
632 async fn read(&mut self, address: u32, data: &mut [u8]) -> Result<(), Self::Error> { 627 async fn read(&mut self, address: u32, data: &mut [u8]) -> Result<(), Self::Error> {
633 self.read(address, data).await 628 self.read(address, data).await