Skip to content

Commit b6466d7

Browse files
committed
FlashWriter.write requires additional user input
- FlashWriter.write used to automatically pad incoming data such that is was divisible by 8, a requirement of the STM32 flash hardware. A colleague suggested this could cause confusion during subsequent writes. FlashWriter.write now forces the user to acknowledge this with the `force_data_padding` flag. If true, the data will be padded automatically to be divisible by 8. If false and the data is not divisible by 8, an error is thrown. - Added new error ArrayMustBeDivisibleBy8 - Modified the flash example based on the above updates
1 parent 9b31810 commit b6466d7

File tree

2 files changed

+76
-23
lines changed

2 files changed

+76
-23
lines changed

examples/flash_with_rtic.rs

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -87,29 +87,72 @@ mod app {
8787
];
8888
let mut flash = dp.FLASH.constrain();
8989
let mut flash_writer = flash.writer::<2048>(FlashSize::Sz256K);
90-
const FLASH_SPACING: usize = 16; // Separate flash writes by 16 bytes
90+
const FLASH_SPACING: u32 = 16; // Separate flash writes by 16 bytes
9191

9292
flash_writer.erase(0x1FC00, 128).unwrap(); // Erase entire page
9393

9494
for i in 0..6 {
9595
match i {
96-
0 => flash_writer
97-
.write(0x1FC00 + i * FLASH_SPACING, &one_byte)
98-
.unwrap(),
99-
1 => flash_writer
100-
.write(0x1FC00 + i * FLASH_SPACING, &two_bytes)
101-
.unwrap(),
102-
2 => flash_writer
103-
.write(0x1FC00 + i * FLASH_SPACING, &three_bytes)
104-
.unwrap(),
105-
3 => flash_writer
106-
.write(0x1FC00 + i * FLASH_SPACING, &four_bytes)
107-
.unwrap(),
96+
0 => {
97+
// This test should fail, as the data needs to be divisible by 8 and force padding is false
98+
let result = flash_writer.write(0x1FC00 + i * FLASH_SPACING, &one_byte, false);
99+
assert!(result.is_err());
100+
assert_eq!(
101+
result.err().unwrap(),
102+
stm32g4xx_hal::flash::Error::ArrayMustBeDivisibleBy8
103+
);
104+
105+
// This test should pass, as the data needs to be divisible by 8 and force padding is true, so the one_byte array will be padded with 7 bytes of 0xFF
106+
let result = flash_writer.write(0x1FC00 + i * FLASH_SPACING, &one_byte, true);
107+
assert!(result.is_ok());
108+
}
109+
1 => {
110+
// This test should fail, as the data needs to be divisible by 8 and force padding is false
111+
let result = flash_writer.write(0x1FC00 + i * FLASH_SPACING, &two_bytes, false);
112+
assert!(result.is_err());
113+
assert_eq!(
114+
result.err().unwrap(),
115+
stm32g4xx_hal::flash::Error::ArrayMustBeDivisibleBy8
116+
);
117+
118+
// This test should pass, as the data needs to be divisible by 8 and force padding is true, so the one_byte array will be padded with 7 bytes of 0xFF
119+
let result = flash_writer.write(0x1FC00 + i * FLASH_SPACING, &two_bytes, true);
120+
assert!(result.is_ok());
121+
}
122+
2 => {
123+
// This test should fail, as the data needs to be divisible by 8 and force padding is false
124+
let result =
125+
flash_writer.write(0x1FC00 + i * FLASH_SPACING, &three_bytes, false);
126+
assert!(result.is_err());
127+
assert_eq!(
128+
result.err().unwrap(),
129+
stm32g4xx_hal::flash::Error::ArrayMustBeDivisibleBy8
130+
);
131+
132+
// This test should pass, as the data needs to be divisible by 8 and force padding is true, so the one_byte array will be padded with 7 bytes of 0xFF
133+
let result =
134+
flash_writer.write(0x1FC00 + i * FLASH_SPACING, &three_bytes, true);
135+
assert!(result.is_ok());
136+
}
137+
3 => {
138+
// This test should fail, as the data needs to be divisible by 8 and force padding is false
139+
let result =
140+
flash_writer.write(0x1FC00 + i * FLASH_SPACING, &four_bytes, false);
141+
assert!(result.is_err());
142+
assert_eq!(
143+
result.err().unwrap(),
144+
stm32g4xx_hal::flash::Error::ArrayMustBeDivisibleBy8
145+
);
146+
147+
// This test should pass, as the data needs to be divisible by 8 and force padding is true, so the one_byte array will be padded with 7 bytes of 0xFF
148+
let result = flash_writer.write(0x1FC00 + i * FLASH_SPACING, &four_bytes, true);
149+
assert!(result.is_ok());
150+
}
108151
4 => flash_writer
109-
.write(0x1FC00 + i * FLASH_SPACING, &eight_bytes)
152+
.write(0x1FC00 + i * FLASH_SPACING, &eight_bytes, false)
110153
.unwrap(),
111154
5 => flash_writer
112-
.write(0x1FC00 + i * 16, &sixteen_bytes)
155+
.write(0x1FC00 + i * 16, &sixteen_bytes, false)
113156
.unwrap(),
114157
_ => (),
115158
}

src/flash.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ pub enum Error {
3232
OptUnlockError,
3333
LockError,
3434
OptLockError,
35+
ArrayMustBeDivisibleBy8,
3536
}
3637

3738
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)]
@@ -137,16 +138,20 @@ impl<'a, const SECTOR_SZ_KB: u32> FlashWriter<'a, SECTOR_SZ_KB> {
137138
}
138139
}
139140

140-
fn valid_length(&self, offset: u32, length: usize) -> Result<()> {
141+
fn valid_length(&self, offset: u32, length: usize, force_padding: bool) -> Result<()> {
141142
if offset
142143
.checked_add(length as u32)
143144
.ok_or(Error::LengthTooLong)?
144145
> self.flash_sz.kbytes() as u32
145146
{
146-
Err(Error::LengthTooLong)
147-
} else {
148-
Ok(())
147+
return Err(Error::LengthTooLong);
148+
}
149+
150+
if force_padding == false && length % 8 != 0 {
151+
return Err(Error::ArrayMustBeDivisibleBy8);
149152
}
153+
154+
Ok(())
150155
}
151156

152157
/// Erase sector which contains `start_offset`
@@ -215,7 +220,7 @@ impl<'a, const SECTOR_SZ_KB: u32> FlashWriter<'a, SECTOR_SZ_KB> {
215220

216221
/// Erase the Flash Sectors from `FLASH_START + start_offset` to `length`
217222
pub fn erase(&mut self, start_offset: u32, length: usize) -> Result<()> {
218-
self.valid_length(start_offset, length)?;
223+
self.valid_length(start_offset, length, true)?;
219224

220225
// Erase every sector touched by start_offset + length
221226
for offset in
@@ -248,9 +253,14 @@ impl<'a, const SECTOR_SZ_KB: u32> FlashWriter<'a, SECTOR_SZ_KB> {
248253
)
249254
}
250255

251-
/// Write data to `FLASH_START + offset`
252-
pub fn write(&mut self, offset: u32, data: &[u8]) -> Result<()> {
253-
self.valid_length(offset, data.len())?;
256+
/// Write data to `FLASH_START + offset`.
257+
///
258+
/// If `force_data_padding` is true, the incoming data will be padded with 0xFF
259+
/// to satisfy the requirement that 2 words (8 bytes) must be written at a time.
260+
/// If `force_data_padding` is false and `data.len()` is not divisible by 8,
261+
/// the error `ArrayMustBeDivisibleBy8` will be returned.
262+
pub fn write(&mut self, offset: u32, data: &[u8], force_data_padding: bool) -> Result<()> {
263+
self.valid_length(offset, data.len(), force_data_padding)?;
254264

255265
// Unlock Flash
256266
self.unlock()?;

0 commit comments

Comments
 (0)