aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias <[email protected]>2022-09-16 12:40:39 +0200
committerMathias <[email protected]>2022-09-16 13:20:22 +0200
commitfeb840c503a7110db5d12c0f49eea10ac92aa1c1 (patch)
treeb8d46c0d6b813925fca6ed125e2549dfa2ca2601
parent9794bc59cc74598f5131f502153d4288c3261274 (diff)
First iteration attempt on implementing generic flash mutation access for RP2040
-rw-r--r--embassy-rp/Cargo.toml2
-rw-r--r--embassy-rp/src/flash.rs100
-rw-r--r--embassy-rp/src/lib.rs1
3 files changed, 103 insertions, 0 deletions
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index ccb2f6525..51cdda7b1 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -44,6 +44,8 @@ cortex-m-rt = ">=0.6.15,<0.8"
44cortex-m = "0.7.6" 44cortex-m = "0.7.6"
45critical-section = "1.1" 45critical-section = "1.1"
46futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 46futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
47rp2040-flash = { version = "0.1" }
48embedded-storage = { version = "0.3" }
47 49
48rp2040-pac2 = { git = "https://github.com/embassy-rs/rp2040-pac2", rev="017e3c9007b2d3b6965f0d85b5bf8ce3fa6d7364", features = ["rt"] } 50rp2040-pac2 = { git = "https://github.com/embassy-rs/rp2040-pac2", rev="017e3c9007b2d3b6965f0d85b5bf8ce3fa6d7364", features = ["rt"] }
49#rp2040-pac2 = { path = "../../rp2040-pac2", features = ["rt"] } 51#rp2040-pac2 = { path = "../../rp2040-pac2", features = ["rt"] }
diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs
new file mode 100644
index 000000000..3b6405090
--- /dev/null
+++ b/embassy-rp/src/flash.rs
@@ -0,0 +1,100 @@
1use embedded_storage::nor_flash::{
2 ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash,
3};
4
5/// Error type for NVMC operations.
6#[derive(Debug, Copy, Clone, PartialEq, Eq)]
7#[cfg_attr(feature = "defmt", derive(defmt::Format))]
8pub enum Error {
9 /// Opration using a location not in flash.
10 OutOfBounds,
11 /// Unaligned operation or using unaligned buffers.
12 Unaligned,
13}
14
15impl NorFlashError for Error {
16 fn kind(&self) -> NorFlashErrorKind {
17 match self {
18 Self::OutOfBounds => NorFlashErrorKind::OutOfBounds,
19 Self::Unaligned => NorFlashErrorKind::NotAligned,
20 }
21 }
22}
23
24pub struct Flash<const FLASH_SIZE: usize>;
25
26impl<const FLASH_SIZE: usize> ErrorType for Flash<FLASH_SIZE> {
27 type Error = Error;
28}
29
30impl<const FLASH_SIZE: usize> MultiwriteNorFlash for Flash<FLASH_SIZE> {}
31
32impl<const FLASH_SIZE: usize> ReadNorFlash for Flash<FLASH_SIZE> {
33 const READ_SIZE: usize = 1;
34
35 fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> {
36 if offset as usize >= FLASH_SIZE || offset as usize + bytes.len() > FLASH_SIZE {
37 return Err(Error::OutOfBounds);
38 }
39
40 let flash_data = unsafe { core::slice::from_raw_parts(offset as *const u8, bytes.len()) };
41 bytes.copy_from_slice(flash_data);
42 Ok(())
43 }
44
45 fn capacity(&self) -> usize {
46 FLASH_SIZE
47 }
48}
49
50impl<const FLASH_SIZE: usize> NorFlash for Flash<FLASH_SIZE> {
51 const WRITE_SIZE: usize = 4;
52
53 const ERASE_SIZE: usize = 4096;
54
55 fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> {
56 if to < from || to as usize > FLASH_SIZE {
57 return Err(Error::OutOfBounds);
58 }
59 if from as usize % Self::ERASE_SIZE != 0 || to as usize % Self::ERASE_SIZE != 0 {
60 return Err(Error::Unaligned);
61 }
62
63 let len = to - from;
64
65 // Make sure to uphold the contract point with rp2040-flash.
66 // - interrupts must be disabled
67 // - DMA must not access flash memory
68 // FIXME: Pause all DMA channels for the duration of the flash_write?
69
70 critical_section::with(|_| {
71 unsafe { rp2040_flash::flash::flash_range_erase(from, len, true) };
72 });
73
74 // Re-enable DMA channels
75
76 Ok(())
77 }
78
79 fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> {
80 if offset as usize + bytes.len() > FLASH_SIZE {
81 return Err(Error::OutOfBounds);
82 }
83 if offset as usize % 4 != 0 || bytes.len() as usize % 4 != 0 {
84 return Err(Error::Unaligned);
85 }
86
87 // Make sure to uphold the contract point with rp2040-flash.
88 // - interrupts must be disabled
89 // - DMA must not access flash memory
90 // FIXME: Pause all DMA channels for the duration of the flash_write?
91
92 critical_section::with(|_| {
93 unsafe { rp2040_flash::flash::flash_range_program(offset, bytes, true) };
94 });
95
96 // Re-enable DMA channels
97
98 Ok(())
99 }
100}
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs
index aebbbf567..d86162fb2 100644
--- a/embassy-rp/src/lib.rs
+++ b/embassy-rp/src/lib.rs
@@ -14,6 +14,7 @@ pub mod uart;
14pub mod usb; 14pub mod usb;
15 15
16mod clocks; 16mod clocks;
17pub mod flash;
17mod reset; 18mod reset;
18 19
19// Reexports 20// Reexports