aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMathias <[email protected]>2022-10-24 12:17:22 +0200
committerMathias <[email protected]>2022-10-24 12:17:22 +0200
commitad0eb3f4bd2b124fcb7cda6d6bd88e2b12632ea7 (patch)
tree3bb6d54ab6b3af80e34486904cf4dd8f3acee173
parent8d809c96ecf2fabf77f0fb72f2a59acd18306bf2 (diff)
Implement flash padding to 256 under assumption that all QSPI NOR flashes are MultiwriteNorFlashes
-rw-r--r--embassy-rp/src/flash.rs56
1 files changed, 53 insertions, 3 deletions
diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs
index 1ff2fd195..7a26085b6 100644
--- a/embassy-rp/src/flash.rs
+++ b/embassy-rp/src/flash.rs
@@ -1,5 +1,6 @@
1use embedded_storage::nor_flash::{ 1use embedded_storage::nor_flash::{
2 check_erase, check_read, check_write, ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash, 2 check_erase, check_read, check_write, ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, NorFlashErrorKind,
3 ReadNorFlash,
3}; 4};
4 5
5pub const FLASH_BASE: usize = 0x10000000; 6pub const FLASH_BASE: usize = 0x10000000;
@@ -9,7 +10,8 @@ pub const FLASH_BASE: usize = 0x10000000;
9// These limitations are currently enforced because of using the 10// These limitations are currently enforced because of using the
10// RP2040 boot-rom flash functions, that are optimized for flash compatibility 11// RP2040 boot-rom flash functions, that are optimized for flash compatibility
11// rather than performance. 12// rather than performance.
12pub const WRITE_SIZE: usize = 256; 13pub const PAGE_SIZE: usize = 256;
14pub const WRITE_SIZE: usize = 1;
13pub const READ_SIZE: usize = 1; 15pub const READ_SIZE: usize = 1;
14pub const ERASE_SIZE: usize = 4096; 16pub const ERASE_SIZE: usize = 4096;
15 17
@@ -100,6 +102,8 @@ impl<const FLASH_SIZE: usize> ReadNorFlash for Flash<FLASH_SIZE> {
100 } 102 }
101} 103}
102 104
105impl<const FLASH_SIZE: usize> MultiwriteNorFlash for Flash<FLASH_SIZE> {}
106
103impl<const FLASH_SIZE: usize> NorFlash for Flash<FLASH_SIZE> { 107impl<const FLASH_SIZE: usize> NorFlash for Flash<FLASH_SIZE> {
104 const WRITE_SIZE: usize = WRITE_SIZE; 108 const WRITE_SIZE: usize = WRITE_SIZE;
105 109
@@ -120,12 +124,58 @@ impl<const FLASH_SIZE: usize> NorFlash for Flash<FLASH_SIZE> {
120 124
121 trace!("Writing {:?} bytes to 0x{:x}", bytes.len(), offset); 125 trace!("Writing {:?} bytes to 0x{:x}", bytes.len(), offset);
122 126
123 unsafe { self.in_ram(|| ram_helpers::flash_range_program(offset, bytes, true)) }; 127 let end_offset = offset as usize + bytes.len();
128
129 let padded_offset = (offset as *const u8).align_offset(PAGE_SIZE);
130 let start_padding = core::cmp::min(padded_offset, bytes.len());
131
132 // Pad in the beginning
133 if start_padding > 0 {
134 let start = PAGE_SIZE - padded_offset;
135 let end = start + start_padding;
136
137 let mut pad_buf = [0xFF_u8; PAGE_SIZE];
138 pad_buf[start..end].copy_from_slice(&bytes[..start_padding]);
139
140 let unaligned_offset = offset as usize - start;
141
142 unsafe { self.in_ram(|| ram_helpers::flash_range_program(unaligned_offset as u32, &pad_buf, true)) }
143 }
144
145 let remaining_len = bytes.len() - start_padding;
146 let end_padding = start_padding + PAGE_SIZE * (remaining_len / PAGE_SIZE);
147
148 // Write aligned slice of length in multiples of 256 bytes
149 // If the remaining bytes to be written is more than a full page.
150 if remaining_len >= PAGE_SIZE {
151 let aligned_data = &bytes[start_padding..end_padding];
152
153 let aligned_offset = if start_padding > 0 {
154 offset as usize + padded_offset
155 } else {
156 offset as usize
157 };
158
159 unsafe { self.in_ram(|| ram_helpers::flash_range_program(aligned_offset as u32, aligned_data, true)) }
160 }
161
162 // Pad in the end
163 let rem_offset = (end_offset as *const u8).align_offset(PAGE_SIZE);
164 let rem_padding = remaining_len % PAGE_SIZE;
165 if rem_padding > 0 {
166 let mut pad_buf = [0xFF_u8; PAGE_SIZE];
167 pad_buf[..rem_padding].copy_from_slice(&bytes[end_padding..]);
168
169 let unaligned_offset = end_offset - (PAGE_SIZE - rem_offset);
170
171 unsafe { self.in_ram(|| ram_helpers::flash_range_program(unaligned_offset as u32, &pad_buf, true)) }
172 }
124 173
125 Ok(()) 174 Ok(())
126 } 175 }
127} 176}
128 177
178#[allow(dead_code)]
129mod ram_helpers { 179mod ram_helpers {
130 use core::marker::PhantomData; 180 use core::marker::PhantomData;
131 181