diff options
| -rw-r--r-- | .vscode/settings.json | 1 | ||||
| -rw-r--r-- | embassy-nrf-examples/Cargo.toml | 6 | ||||
| -rw-r--r-- | embassy-nrf-examples/src/bin/qspi.rs | 25 | ||||
| -rw-r--r-- | embassy-nrf/Cargo.toml | 1 | ||||
| -rw-r--r-- | embassy-nrf/src/qspi.rs | 270 | ||||
| -rw-r--r-- | embassy/src/flash.rs | 8 |
6 files changed, 192 insertions, 119 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json index 8915126a4..19efb1373 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | "rust-analyzer.checkOnSave.allTargets": false, | 6 | "rust-analyzer.checkOnSave.allTargets": false, |
| 7 | "rust-analyzer.procMacro.enable": true, | 7 | "rust-analyzer.procMacro.enable": true, |
| 8 | "rust-analyzer.cargo.loadOutDirsFromCheck": true, | 8 | "rust-analyzer.cargo.loadOutDirsFromCheck": true, |
| 9 | "rust-analyzer.cargo.target": "thumbv7em-none-eabi", | ||
| 9 | "files.watcherExclude": { | 10 | "files.watcherExclude": { |
| 10 | "**/.git/objects/**": true, | 11 | "**/.git/objects/**": true, |
| 11 | "**/.git/subtree-cache/**": true, | 12 | "**/.git/subtree-cache/**": true, |
diff --git a/embassy-nrf-examples/Cargo.toml b/embassy-nrf-examples/Cargo.toml index 364fd8a51..b7e4c340c 100644 --- a/embassy-nrf-examples/Cargo.toml +++ b/embassy-nrf-examples/Cargo.toml | |||
| @@ -17,13 +17,13 @@ defmt-error = [] | |||
| 17 | 17 | ||
| 18 | 18 | ||
| 19 | [dependencies] | 19 | [dependencies] |
| 20 | embassy = { version = "0.1.0", path = "../embassy", features = ["defmt", "defmt-trace"] } | 20 | embassy = { version = "0.1.0", path = "../embassy", features = ["defmt"] } |
| 21 | embassy-nrf = { version = "0.1.0", path = "../embassy-nrf", features = ["defmt", "defmt-trace", "52840"] } | 21 | embassy-nrf = { version = "0.1.0", path = "../embassy-nrf", features = ["defmt", "52840"] } |
| 22 | 22 | ||
| 23 | defmt = "0.2.0" | 23 | defmt = "0.2.0" |
| 24 | defmt-rtt = "0.2.0" | 24 | defmt-rtt = "0.2.0" |
| 25 | 25 | ||
| 26 | cortex-m = "0.7.1" | 26 | cortex-m = { version = "0.7.1", features = ["inline-asm"] } |
| 27 | cortex-m-rt = "0.6.13" | 27 | cortex-m-rt = "0.6.13" |
| 28 | embedded-hal = { version = "0.2.4" } | 28 | embedded-hal = { version = "0.2.4" } |
| 29 | panic-probe = "0.1.0" | 29 | panic-probe = "0.1.0" |
diff --git a/embassy-nrf-examples/src/bin/qspi.rs b/embassy-nrf-examples/src/bin/qspi.rs index 850681d7c..790dedc91 100644 --- a/embassy-nrf-examples/src/bin/qspi.rs +++ b/embassy-nrf-examples/src/bin/qspi.rs | |||
| @@ -8,6 +8,7 @@ use example_common::*; | |||
| 8 | 8 | ||
| 9 | use cortex_m_rt::entry; | 9 | use cortex_m_rt::entry; |
| 10 | use defmt::{assert_eq, panic}; | 10 | use defmt::{assert_eq, panic}; |
| 11 | use futures::pin_mut; | ||
| 11 | use nrf52840_hal::gpio; | 12 | use nrf52840_hal::gpio; |
| 12 | 13 | ||
| 13 | use embassy::executor::{task, Executor}; | 14 | use embassy::executor::{task, Executor}; |
| @@ -69,22 +70,32 @@ async fn run() { | |||
| 69 | }; | 70 | }; |
| 70 | 71 | ||
| 71 | let irq = interrupt::take!(QSPI); | 72 | let irq = interrupt::take!(QSPI); |
| 72 | let mut q = qspi::Qspi::new(p.QSPI, irq, config); | 73 | let q = qspi::Qspi::new(p.QSPI, irq, config); |
| 74 | pin_mut!(q); | ||
| 73 | 75 | ||
| 74 | let mut id = [1; 3]; | 76 | let mut id = [1; 3]; |
| 75 | q.custom_instruction(0x9F, &[], &mut id).await.unwrap(); | 77 | q.as_mut() |
| 78 | .custom_instruction(0x9F, &[], &mut id) | ||
| 79 | .await | ||
| 80 | .unwrap(); | ||
| 76 | info!("id: {}", id); | 81 | info!("id: {}", id); |
| 77 | 82 | ||
| 78 | // Read status register | 83 | // Read status register |
| 79 | let mut status = [0; 1]; | 84 | let mut status = [0; 1]; |
| 80 | q.custom_instruction(0x05, &[], &mut status).await.unwrap(); | 85 | q.as_mut() |
| 86 | .custom_instruction(0x05, &[], &mut status) | ||
| 87 | .await | ||
| 88 | .unwrap(); | ||
| 81 | 89 | ||
| 82 | info!("status: {:?}", status[0]); | 90 | info!("status: {:?}", status[0]); |
| 83 | 91 | ||
| 84 | if status[0] & 0x40 == 0 { | 92 | if status[0] & 0x40 == 0 { |
| 85 | status[0] |= 0x40; | 93 | status[0] |= 0x40; |
| 86 | 94 | ||
| 87 | q.custom_instruction(0x01, &status, &mut []).await.unwrap(); | 95 | q.as_mut() |
| 96 | .custom_instruction(0x01, &status, &mut []) | ||
| 97 | .await | ||
| 98 | .unwrap(); | ||
| 88 | 99 | ||
| 89 | info!("enabled quad in status"); | 100 | info!("enabled quad in status"); |
| 90 | } | 101 | } |
| @@ -95,19 +106,19 @@ async fn run() { | |||
| 95 | 106 | ||
| 96 | for i in 0..8 { | 107 | for i in 0..8 { |
| 97 | info!("page {:?}: erasing... ", i); | 108 | info!("page {:?}: erasing... ", i); |
| 98 | q.erase(i * PAGE_SIZE).await.unwrap(); | 109 | q.as_mut().erase(i * PAGE_SIZE).await.unwrap(); |
| 99 | 110 | ||
| 100 | for j in 0..PAGE_SIZE { | 111 | for j in 0..PAGE_SIZE { |
| 101 | buf.0[j] = pattern((j + i * PAGE_SIZE) as u32); | 112 | buf.0[j] = pattern((j + i * PAGE_SIZE) as u32); |
| 102 | } | 113 | } |
| 103 | 114 | ||
| 104 | info!("programming..."); | 115 | info!("programming..."); |
| 105 | q.write(i * PAGE_SIZE, &buf.0).await.unwrap(); | 116 | q.as_mut().write(i * PAGE_SIZE, &buf.0).await.unwrap(); |
| 106 | } | 117 | } |
| 107 | 118 | ||
| 108 | for i in 0..8 { | 119 | for i in 0..8 { |
| 109 | info!("page {:?}: reading... ", i); | 120 | info!("page {:?}: reading... ", i); |
| 110 | q.read(i * PAGE_SIZE, &mut buf.0).await.unwrap(); | 121 | q.as_mut().read(i * PAGE_SIZE, &mut buf.0).await.unwrap(); |
| 111 | 122 | ||
| 112 | info!("verifying..."); | 123 | info!("verifying..."); |
| 113 | for j in 0..PAGE_SIZE { | 124 | for j in 0..PAGE_SIZE { |
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index ddd2dc31a..6324792fc 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml | |||
| @@ -27,6 +27,7 @@ cortex-m-rt = "0.6.13" | |||
| 27 | cortex-m = "0.7.1" | 27 | cortex-m = "0.7.1" |
| 28 | embedded-hal = { version = "0.2.4" } | 28 | embedded-hal = { version = "0.2.4" } |
| 29 | embedded-dma = { version = "0.1.2" } | 29 | embedded-dma = { version = "0.1.2" } |
| 30 | futures = { version = "0.3.5", default-features = false } | ||
| 30 | 31 | ||
| 31 | nrf52810-pac = { version = "0.9.0", optional = true } | 32 | nrf52810-pac = { version = "0.9.0", optional = true } |
| 32 | nrf52811-pac = { version = "0.9.1", optional = true } | 33 | nrf52811-pac = { version = "0.9.1", optional = true } |
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs index 300b32ad5..c238a6c82 100644 --- a/embassy-nrf/src/qspi.rs +++ b/embassy-nrf/src/qspi.rs | |||
| @@ -1,6 +1,9 @@ | |||
| 1 | use crate::fmt::{assert, assert_eq, *}; | ||
| 2 | use core::future::Future; | 1 | use core::future::Future; |
| 2 | use core::pin::Pin; | ||
| 3 | use core::sync::atomic::{compiler_fence, Ordering}; | ||
| 4 | use core::task::Poll; | ||
| 3 | 5 | ||
| 6 | use crate::fmt::{assert, assert_eq, *}; | ||
| 4 | use crate::hal::gpio::{Output, Pin as GpioPin, Port as GpioPort, PushPull}; | 7 | use crate::hal::gpio::{Output, Pin as GpioPin, Port as GpioPort, PushPull}; |
| 5 | use crate::interrupt::{self, Interrupt}; | 8 | use crate::interrupt::{self, Interrupt}; |
| 6 | use crate::pac::QSPI; | 9 | use crate::pac::QSPI; |
| @@ -9,6 +12,7 @@ pub use crate::pac::qspi::ifconfig0::ADDRMODE_A as AddressMode; | |||
| 9 | pub use crate::pac::qspi::ifconfig0::PPSIZE_A as WritePageSize; | 12 | pub use crate::pac::qspi::ifconfig0::PPSIZE_A as WritePageSize; |
| 10 | pub use crate::pac::qspi::ifconfig0::READOC_A as ReadOpcode; | 13 | pub use crate::pac::qspi::ifconfig0::READOC_A as ReadOpcode; |
| 11 | pub use crate::pac::qspi::ifconfig0::WRITEOC_A as WriteOpcode; | 14 | pub use crate::pac::qspi::ifconfig0::WRITEOC_A as WriteOpcode; |
| 15 | use crate::util::peripheral::{PeripheralMutex, PeripheralState}; | ||
| 12 | 16 | ||
| 13 | // TODO | 17 | // TODO |
| 14 | // - config: | 18 | // - config: |
| @@ -21,7 +25,8 @@ pub use crate::pac::qspi::ifconfig0::WRITEOC_A as WriteOpcode; | |||
| 21 | // - set gpio in high drive | 25 | // - set gpio in high drive |
| 22 | 26 | ||
| 23 | use embassy::flash::{Error, Flash}; | 27 | use embassy::flash::{Error, Flash}; |
| 24 | use embassy::util::{DropBomb, Signal}; | 28 | use embassy::util::{DropBomb, WakerRegistration}; |
| 29 | use futures::future::poll_fn; | ||
| 25 | 30 | ||
| 26 | pub struct Pins { | 31 | pub struct Pins { |
| 27 | pub sck: GpioPin<Output<PushPull>>, | 32 | pub sck: GpioPin<Output<PushPull>>, |
| @@ -46,8 +51,13 @@ pub struct Config { | |||
| 46 | pub deep_power_down: Option<DeepPowerDownConfig>, | 51 | pub deep_power_down: Option<DeepPowerDownConfig>, |
| 47 | } | 52 | } |
| 48 | 53 | ||
| 49 | pub struct Qspi { | 54 | struct State { |
| 50 | inner: QSPI, | 55 | inner: QSPI, |
| 56 | waker: WakerRegistration, | ||
| 57 | } | ||
| 58 | |||
| 59 | pub struct Qspi { | ||
| 60 | inner: PeripheralMutex<State>, | ||
| 51 | } | 61 | } |
| 52 | 62 | ||
| 53 | fn port_bit(port: GpioPort) -> bool { | 63 | fn port_bit(port: GpioPort) -> bool { |
| @@ -142,32 +152,34 @@ impl Qspi { | |||
| 142 | while qspi.events_ready.read().bits() == 0 {} | 152 | while qspi.events_ready.read().bits() == 0 {} |
| 143 | qspi.events_ready.reset(); | 153 | qspi.events_ready.reset(); |
| 144 | 154 | ||
| 145 | // Enable READY interrupt | 155 | Self { |
| 146 | SIGNAL.reset(); | 156 | inner: PeripheralMutex::new( |
| 147 | qspi.intenset.write(|w| w.ready().set()); | 157 | State { |
| 148 | 158 | inner: qspi, | |
| 149 | irq.set_handler(irq_handler); | 159 | waker: WakerRegistration::new(), |
| 150 | irq.unpend(); | 160 | }, |
| 151 | irq.enable(); | 161 | irq, |
| 152 | 162 | ), | |
| 153 | Self { inner: qspi } | 163 | } |
| 154 | } | 164 | } |
| 155 | 165 | ||
| 156 | pub fn sleep(&mut self) { | 166 | pub fn sleep(self: Pin<&mut Self>) { |
| 157 | info!("flash: sleeping"); | 167 | self.inner().with(|s, _| { |
| 158 | info!("flash: state = {:?}", self.inner.status.read().bits()); | 168 | info!("flash: sleeping"); |
| 159 | self.inner.ifconfig1.modify(|_, w| w.dpmen().enter()); | 169 | info!("flash: state = {:?}", s.inner.status.read().bits()); |
| 160 | info!("flash: state = {:?}", self.inner.status.read().bits()); | 170 | s.inner.ifconfig1.modify(|_, w| w.dpmen().enter()); |
| 161 | cortex_m::asm::delay(1000000); | 171 | info!("flash: state = {:?}", s.inner.status.read().bits()); |
| 162 | info!("flash: state = {:?}", self.inner.status.read().bits()); | 172 | cortex_m::asm::delay(1000000); |
| 163 | 173 | info!("flash: state = {:?}", s.inner.status.read().bits()); | |
| 164 | self.inner | 174 | |
| 165 | .tasks_deactivate | 175 | s.inner |
| 166 | .write(|w| w.tasks_deactivate().set_bit()); | 176 | .tasks_deactivate |
| 177 | .write(|w| w.tasks_deactivate().set_bit()); | ||
| 178 | }); | ||
| 167 | } | 179 | } |
| 168 | 180 | ||
| 169 | pub async fn custom_instruction<'a>( | 181 | pub async fn custom_instruction<'a>( |
| 170 | &'a mut self, | 182 | mut self: Pin<&'a mut Self>, |
| 171 | opcode: u8, | 183 | opcode: u8, |
| 172 | req: &'a [u8], | 184 | req: &'a [u8], |
| 173 | resp: &'a mut [u8], | 185 | resp: &'a mut [u8], |
| @@ -193,40 +205,68 @@ impl Qspi { | |||
| 193 | 205 | ||
| 194 | let len = core::cmp::max(req.len(), resp.len()) as u8; | 206 | let len = core::cmp::max(req.len(), resp.len()) as u8; |
| 195 | 207 | ||
| 196 | self.inner.cinstrdat0.write(|w| unsafe { w.bits(dat0) }); | 208 | self.as_mut().inner().with(|s, _| { |
| 197 | self.inner.cinstrdat1.write(|w| unsafe { w.bits(dat1) }); | 209 | s.inner.cinstrdat0.write(|w| unsafe { w.bits(dat0) }); |
| 198 | self.inner.events_ready.reset(); | 210 | s.inner.cinstrdat1.write(|w| unsafe { w.bits(dat1) }); |
| 199 | self.inner.cinstrconf.write(|w| { | 211 | |
| 200 | let w = unsafe { w.opcode().bits(opcode) }; | 212 | s.inner.events_ready.reset(); |
| 201 | let w = unsafe { w.length().bits(len + 1) }; | 213 | s.inner.intenset.write(|w| w.ready().set()); |
| 202 | let w = w.lio2().bit(true); | 214 | |
| 203 | let w = w.lio3().bit(true); | 215 | s.inner.cinstrconf.write(|w| { |
| 204 | let w = w.wipwait().bit(true); | 216 | let w = unsafe { w.opcode().bits(opcode) }; |
| 205 | let w = w.wren().bit(true); | 217 | let w = unsafe { w.length().bits(len + 1) }; |
| 206 | let w = w.lfen().bit(false); | 218 | let w = w.lio2().bit(true); |
| 207 | let w = w.lfstop().bit(false); | 219 | let w = w.lio3().bit(true); |
| 208 | w | 220 | let w = w.wipwait().bit(true); |
| 221 | let w = w.wren().bit(true); | ||
| 222 | let w = w.lfen().bit(false); | ||
| 223 | let w = w.lfstop().bit(false); | ||
| 224 | w | ||
| 225 | }); | ||
| 209 | }); | 226 | }); |
| 210 | 227 | ||
| 211 | SIGNAL.wait().await; | 228 | self.as_mut().wait_ready().await; |
| 212 | 229 | ||
| 213 | let dat0 = self.inner.cinstrdat0.read().bits(); | 230 | self.as_mut().inner().with(|s, _| { |
| 214 | let dat1 = self.inner.cinstrdat1.read().bits(); | 231 | let dat0 = s.inner.cinstrdat0.read().bits(); |
| 215 | for i in 0..4 { | 232 | let dat1 = s.inner.cinstrdat1.read().bits(); |
| 216 | if i < resp.len() { | 233 | for i in 0..4 { |
| 217 | resp[i] = (dat0 >> (i * 8)) as u8; | 234 | if i < resp.len() { |
| 235 | resp[i] = (dat0 >> (i * 8)) as u8; | ||
| 236 | } | ||
| 218 | } | 237 | } |
| 219 | } | 238 | for i in 0..4 { |
| 220 | for i in 0..4 { | 239 | if i + 4 < resp.len() { |
| 221 | if i + 4 < resp.len() { | 240 | resp[i] = (dat1 >> (i * 8)) as u8; |
| 222 | resp[i] = (dat1 >> (i * 8)) as u8; | 241 | } |
| 223 | } | 242 | } |
| 224 | } | 243 | }); |
| 225 | 244 | ||
| 226 | bomb.defuse(); | 245 | bomb.defuse(); |
| 227 | 246 | ||
| 228 | Ok(()) | 247 | Ok(()) |
| 229 | } | 248 | } |
| 249 | |||
| 250 | fn inner(self: Pin<&mut Self>) -> Pin<&mut PeripheralMutex<State>> { | ||
| 251 | unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) } | ||
| 252 | } | ||
| 253 | |||
| 254 | pub fn free(self: Pin<&mut Self>) -> (QSPI, interrupt::QSPI) { | ||
| 255 | let (state, irq) = self.inner().free(); | ||
| 256 | (state.inner, irq) | ||
| 257 | } | ||
| 258 | |||
| 259 | fn wait_ready<'a>(mut self: Pin<&'a mut Self>) -> impl Future<Output = ()> + 'a { | ||
| 260 | poll_fn(move |cx| { | ||
| 261 | self.as_mut().inner().with(|s, irq| { | ||
| 262 | if s.inner.events_ready.read().bits() != 0 { | ||
| 263 | return Poll::Ready(()); | ||
| 264 | } | ||
| 265 | s.waker.register(cx.waker()); | ||
| 266 | Poll::Pending | ||
| 267 | }) | ||
| 268 | }) | ||
| 269 | } | ||
| 230 | } | 270 | } |
| 231 | 271 | ||
| 232 | impl Flash for Qspi { | 272 | impl Flash for Qspi { |
| @@ -234,7 +274,11 @@ impl Flash for Qspi { | |||
| 234 | type WriteFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; | 274 | type WriteFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; |
| 235 | type ErasePageFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; | 275 | type ErasePageFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; |
| 236 | 276 | ||
| 237 | fn read<'a>(&'a mut self, address: usize, data: &'a mut [u8]) -> Self::ReadFuture<'a> { | 277 | fn read<'a>( |
| 278 | mut self: Pin<&'a mut Self>, | ||
| 279 | address: usize, | ||
| 280 | data: &'a mut [u8], | ||
| 281 | ) -> Self::ReadFuture<'a> { | ||
| 238 | async move { | 282 | async move { |
| 239 | let bomb = DropBomb::new(); | 283 | let bomb = DropBomb::new(); |
| 240 | 284 | ||
| @@ -242,25 +286,28 @@ impl Flash for Qspi { | |||
| 242 | assert_eq!(data.len() as u32 % 4, 0); | 286 | assert_eq!(data.len() as u32 % 4, 0); |
| 243 | assert_eq!(address as u32 % 4, 0); | 287 | assert_eq!(address as u32 % 4, 0); |
| 244 | 288 | ||
| 245 | self.inner | 289 | self.as_mut().inner().with(|s, _| { |
| 246 | .read | 290 | s.inner |
| 247 | .src | 291 | .read |
| 248 | .write(|w| unsafe { w.src().bits(address as u32) }); | 292 | .src |
| 249 | self.inner | 293 | .write(|w| unsafe { w.src().bits(address as u32) }); |
| 250 | .read | 294 | s.inner |
| 251 | .dst | 295 | .read |
| 252 | .write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) }); | 296 | .dst |
| 253 | self.inner | 297 | .write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) }); |
| 254 | .read | 298 | s.inner |
| 255 | .cnt | 299 | .read |
| 256 | .write(|w| unsafe { w.cnt().bits(data.len() as u32) }); | 300 | .cnt |
| 257 | 301 | .write(|w| unsafe { w.cnt().bits(data.len() as u32) }); | |
| 258 | self.inner.events_ready.reset(); | 302 | |
| 259 | self.inner | 303 | s.inner.events_ready.reset(); |
| 260 | .tasks_readstart | 304 | s.inner.intenset.write(|w| w.ready().set()); |
| 261 | .write(|w| w.tasks_readstart().bit(true)); | 305 | s.inner |
| 262 | 306 | .tasks_readstart | |
| 263 | SIGNAL.wait().await; | 307 | .write(|w| w.tasks_readstart().bit(true)); |
| 308 | }); | ||
| 309 | |||
| 310 | self.as_mut().wait_ready().await; | ||
| 264 | 311 | ||
| 265 | bomb.defuse(); | 312 | bomb.defuse(); |
| 266 | 313 | ||
| @@ -268,7 +315,11 @@ impl Flash for Qspi { | |||
| 268 | } | 315 | } |
| 269 | } | 316 | } |
| 270 | 317 | ||
| 271 | fn write<'a>(&'a mut self, address: usize, data: &'a [u8]) -> Self::WriteFuture<'a> { | 318 | fn write<'a>( |
| 319 | mut self: Pin<&'a mut Self>, | ||
| 320 | address: usize, | ||
| 321 | data: &'a [u8], | ||
| 322 | ) -> Self::WriteFuture<'a> { | ||
| 272 | async move { | 323 | async move { |
| 273 | let bomb = DropBomb::new(); | 324 | let bomb = DropBomb::new(); |
| 274 | 325 | ||
| @@ -276,25 +327,28 @@ impl Flash for Qspi { | |||
| 276 | assert_eq!(data.len() as u32 % 4, 0); | 327 | assert_eq!(data.len() as u32 % 4, 0); |
| 277 | assert_eq!(address as u32 % 4, 0); | 328 | assert_eq!(address as u32 % 4, 0); |
| 278 | 329 | ||
| 279 | self.inner | 330 | self.as_mut().inner().with(|s, _| { |
| 280 | .write | 331 | s.inner |
| 281 | .src | 332 | .write |
| 282 | .write(|w| unsafe { w.src().bits(data.as_ptr() as u32) }); | 333 | .src |
| 283 | self.inner | 334 | .write(|w| unsafe { w.src().bits(data.as_ptr() as u32) }); |
| 284 | .write | 335 | s.inner |
| 285 | .dst | 336 | .write |
| 286 | .write(|w| unsafe { w.dst().bits(address as u32) }); | 337 | .dst |
| 287 | self.inner | 338 | .write(|w| unsafe { w.dst().bits(address as u32) }); |
| 288 | .write | 339 | s.inner |
| 289 | .cnt | 340 | .write |
| 290 | .write(|w| unsafe { w.cnt().bits(data.len() as u32) }); | 341 | .cnt |
| 291 | 342 | .write(|w| unsafe { w.cnt().bits(data.len() as u32) }); | |
| 292 | self.inner.events_ready.reset(); | 343 | |
| 293 | self.inner | 344 | s.inner.events_ready.reset(); |
| 294 | .tasks_writestart | 345 | s.inner.intenset.write(|w| w.ready().set()); |
| 295 | .write(|w| w.tasks_writestart().bit(true)); | 346 | s.inner |
| 296 | 347 | .tasks_writestart | |
| 297 | SIGNAL.wait().await; | 348 | .write(|w| w.tasks_writestart().bit(true)); |
| 349 | }); | ||
| 350 | |||
| 351 | self.as_mut().wait_ready().await; | ||
| 298 | 352 | ||
| 299 | bomb.defuse(); | 353 | bomb.defuse(); |
| 300 | 354 | ||
| @@ -302,23 +356,27 @@ impl Flash for Qspi { | |||
| 302 | } | 356 | } |
| 303 | } | 357 | } |
| 304 | 358 | ||
| 305 | fn erase<'a>(&'a mut self, address: usize) -> Self::ErasePageFuture<'a> { | 359 | fn erase<'a>(mut self: Pin<&'a mut Self>, address: usize) -> Self::ErasePageFuture<'a> { |
| 306 | async move { | 360 | async move { |
| 307 | let bomb = DropBomb::new(); | 361 | let bomb = DropBomb::new(); |
| 308 | 362 | ||
| 309 | assert_eq!(address as u32 % 4096, 0); | 363 | assert_eq!(address as u32 % 4096, 0); |
| 310 | 364 | ||
| 311 | self.inner | 365 | self.as_mut().inner().with(|s, _| { |
| 312 | .erase | 366 | s.inner |
| 313 | .ptr | 367 | .erase |
| 314 | .write(|w| unsafe { w.ptr().bits(address as u32) }); | 368 | .ptr |
| 315 | self.inner.erase.len.write(|w| w.len()._4kb()); | 369 | .write(|w| unsafe { w.ptr().bits(address as u32) }); |
| 316 | self.inner.events_ready.reset(); | 370 | s.inner.erase.len.write(|w| w.len()._4kb()); |
| 317 | self.inner | 371 | |
| 318 | .tasks_erasestart | 372 | s.inner.events_ready.reset(); |
| 319 | .write(|w| w.tasks_erasestart().bit(true)); | 373 | s.inner.intenset.write(|w| w.ready().set()); |
| 374 | s.inner | ||
| 375 | .tasks_erasestart | ||
| 376 | .write(|w| w.tasks_erasestart().bit(true)); | ||
| 377 | }); | ||
| 320 | 378 | ||
| 321 | SIGNAL.wait().await; | 379 | self.as_mut().wait_ready().await; |
| 322 | 380 | ||
| 323 | bomb.defuse(); | 381 | bomb.defuse(); |
| 324 | 382 | ||
| @@ -343,13 +401,13 @@ impl Flash for Qspi { | |||
| 343 | } | 401 | } |
| 344 | } | 402 | } |
| 345 | 403 | ||
| 346 | static SIGNAL: Signal<()> = Signal::new(); | 404 | impl PeripheralState for State { |
| 405 | type Interrupt = interrupt::QSPI; | ||
| 347 | 406 | ||
| 348 | unsafe fn irq_handler(_ctx: *mut ()) { | 407 | fn on_interrupt(&mut self) { |
| 349 | let p = crate::pac::Peripherals::steal().QSPI; | 408 | if self.inner.events_ready.read().bits() != 0 { |
| 350 | if p.events_ready.read().events_ready().bit_is_set() { | 409 | self.inner.intenclr.write(|w| w.ready().clear()); |
| 351 | p.events_ready.reset(); | 410 | self.waker.wake() |
| 352 | info!("qspi ready"); | 411 | } |
| 353 | SIGNAL.signal(()); | ||
| 354 | } | 412 | } |
| 355 | } | 413 | } |
diff --git a/embassy/src/flash.rs b/embassy/src/flash.rs index 5866fdf05..145cc7684 100644 --- a/embassy/src/flash.rs +++ b/embassy/src/flash.rs | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | use core::future::Future; | 1 | use core::future::Future; |
| 2 | use core::pin::Pin; | ||
| 2 | 3 | ||
| 3 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] | 4 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] |
| 4 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 5 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| @@ -18,18 +19,19 @@ pub trait Flash { | |||
| 18 | /// | 19 | /// |
| 19 | /// address must be a multiple of self.read_size(). | 20 | /// address must be a multiple of self.read_size(). |
| 20 | /// buf.len() must be a multiple of self.read_size(). | 21 | /// buf.len() must be a multiple of self.read_size(). |
| 21 | fn read<'a>(&'a mut self, address: usize, buf: &'a mut [u8]) -> Self::ReadFuture<'a>; | 22 | fn read<'a>(self: Pin<&'a mut Self>, address: usize, buf: &'a mut [u8]) |
| 23 | -> Self::ReadFuture<'a>; | ||
| 22 | 24 | ||
| 23 | /// Writes data to the flash device. | 25 | /// Writes data to the flash device. |
| 24 | /// | 26 | /// |
| 25 | /// address must be a multiple of self.write_size(). | 27 | /// address must be a multiple of self.write_size(). |
| 26 | /// buf.len() must be a multiple of self.write_size(). | 28 | /// buf.len() must be a multiple of self.write_size(). |
| 27 | fn write<'a>(&'a mut self, address: usize, buf: &'a [u8]) -> Self::WriteFuture<'a>; | 29 | fn write<'a>(self: Pin<&'a mut Self>, address: usize, buf: &'a [u8]) -> Self::WriteFuture<'a>; |
| 28 | 30 | ||
| 29 | /// Erases a single page from the flash device. | 31 | /// Erases a single page from the flash device. |
| 30 | /// | 32 | /// |
| 31 | /// address must be a multiple of self.erase_size(). | 33 | /// address must be a multiple of self.erase_size(). |
| 32 | fn erase<'a>(&'a mut self, address: usize) -> Self::ErasePageFuture<'a>; | 34 | fn erase<'a>(self: Pin<&'a mut Self>, address: usize) -> Self::ErasePageFuture<'a>; |
| 33 | 35 | ||
| 34 | /// Returns the total size, in bytes. | 36 | /// Returns the total size, in bytes. |
| 35 | /// This is not guaranteed to be a power of 2. | 37 | /// This is not guaranteed to be a power of 2. |
