aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias <[email protected]>2022-09-16 12:40:39 +0200
committerMathias <[email protected]>2022-09-23 07:59:10 +0200
commit9d674f0212bf2a51fccd192632a16f104ba9629c (patch)
tree2b8a81bae97545ce5b2f928260bcab80a0b883e8
parent816778e3fadf31772413ac7bd78a3eeaead66cad (diff)
First iteration attempt on implementing generic flash mutation access for RP2040
-rw-r--r--embassy-rp/Cargo.toml1
-rw-r--r--embassy-rp/src/flash.rs100
-rw-r--r--embassy-rp/src/lib.rs1
3 files changed, 102 insertions, 0 deletions
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index df0af8dfb..ce78acd3c 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -52,6 +52,7 @@ cortex-m = "0.7.6"
52critical-section = "1.1" 52critical-section = "1.1"
53futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 53futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
54chrono = { version = "0.4", default-features = false, optional = true } 54chrono = { version = "0.4", default-features = false, optional = true }
55embedded-storage = { version = "0.3" }
55 56
56rp2040-pac2 = { git = "https://github.com/embassy-rs/rp2040-pac2", rev="017e3c9007b2d3b6965f0d85b5bf8ce3fa6d7364", features = ["rt"] } 57rp2040-pac2 = { git = "https://github.com/embassy-rs/rp2040-pac2", rev="017e3c9007b2d3b6965f0d85b5bf8ce3fa6d7364", features = ["rt"] }
57#rp2040-pac2 = { path = "../../rp2040-pac2", features = ["rt"] } 58#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 9ac98d226..ce013b09c 100644
--- a/embassy-rp/src/lib.rs
+++ b/embassy-rp/src/lib.rs
@@ -19,6 +19,7 @@ pub mod uart;
19pub mod usb; 19pub mod usb;
20 20
21mod clocks; 21mod clocks;
22pub mod flash;
22mod reset; 23mod reset;
23 24
24// Reexports 25// Reexports