-
Notifications
You must be signed in to change notification settings - Fork 181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Flash Read/Write Support #141
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the work, I was actually thinking about this yesterday, heh. I just have some questions and suggestions. Also, I think the NOTE(unsafe)
should be used to explain why the operation is correct.
src/flash.rs
Outdated
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd)] | ||
pub enum Error { | ||
Success, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this used ?
src/flash.rs
Outdated
if FLASH_START + offset > FLASH_END { | ||
Err(Error::AddressLargedThanFlash) | ||
} | ||
else if offset % 2 != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if the compiler will always do the right thing and change this to offset & 1
, otherwise it might be better if we use bitwise AND instead of mod.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a look at the LLVM-IR produced by rustc, and it looks like it doesn't change it to an and
in debug mode, but does in release mode. That is without LLVM optimizations though
src/flash.rs
Outdated
if length > self.sector_sz.size() as u32 { | ||
Err(Error::LengthTooLong) | ||
} | ||
else if length % 2 != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
src/flash.rs
Outdated
// Re-lock flash | ||
self.lock()?; | ||
|
||
for idx in 0..self.sector_sz.size() -1 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be good to add a way to ignore verification, like a verify: bool
argument.
src/flash.rs
Outdated
self.lock()?; | ||
|
||
for idx in 0..self.sector_sz.size() -1 { | ||
let write_address = (FLASH_START + start_offset + idx as u32) as *mut u16; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you have to correct this to not go pass a section boundary ? i.e start_offset
might be in the middle of a sector. Also I don't think it needs to be mut
.
src/flash.rs
Outdated
Ok(()) | ||
} | ||
|
||
/// Retrieve an slice of at most 1 sector of data from FLASH_START +offset |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why have this limitation ?
src/flash.rs
Outdated
} | ||
} | ||
|
||
/// Write at most 1 sector of data to FLASH_START +offset |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why have this limitation ?
|
||
// Check for errors | ||
let sr = self.flash.sr.sr().read(); | ||
if self.flash.sr.sr().read().pgerr().bit_is_set() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reset bit if set ?
self.lock()?; | ||
return Err(Error::ProgrammingError); | ||
} | ||
else if self.flash.sr.sr().read().wrprterr().bit_is_set() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above
src/flash.rs
Outdated
} | ||
|
||
// Verify written word | ||
let verify: u16 = unsafe { core::ptr::read_volatile(write_address) }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add option to avoid verification ?
You make excellent points. It was a while since I really worked on the code and although I gave it a final look-over I apparently missed quite a bit. Thanks for the thorough check. Most of it is easily fixed which I will probably do in the coming week. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! I had a quick read through, and the code looks very nice over all. I added a few nitpicks. which would be nice if you could fix. I also agree with the comments @thalesfragoso, especially about the unsafe
comments
src/flash.rs
Outdated
Sz1M = 1024, | ||
} | ||
impl FlashSize { | ||
fn size(self) -> u32 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer a more descriptive name for this, perhaps as kbytes
src/flash.rs
Outdated
if FLASH_START + offset > FLASH_END { | ||
Err(Error::AddressLargedThanFlash) | ||
} | ||
else if offset % 2 != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a look at the LLVM-IR produced by rustc, and it looks like it doesn't change it to an and
in debug mode, but does in release mode. That is without LLVM optimizations though
_0: (), | ||
} | ||
|
||
#[allow(dead_code)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are these allow(dead_code) needed? Is rustc missing the usages, or are they currently unused?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those entries are currently unused; I added them for completeness.
- Added FlashReaderGuard - Removed modulo operations - Added option to avoid verify operations - Cleanup
7f55672
to
b34c111
Compare
The comments made should have been fixed, though perhaps some unsafe code comments could still be better. I have verified that single byte read operations from flash are possible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some minor nitpicks, but other than this I think it looks good
// Wait for any ongoing operations | ||
while self.flash.sr.sr().read().bsy().bit_is_set() {} | ||
|
||
// NOTE(unsafe) write Keys to the key register |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still doesn't explain why unsafe is safe
self.flash.cr.cr().modify(|_, w| w.per().set_bit() ); | ||
|
||
// Write address bits | ||
// NOTE(unsafe) This sets the sector address in the Address Register |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
let hword: u16 = | ||
(data[idx] as u16) | ||
| (data[idx+1] as u16) << 8; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Weird formatting. Though I'm not sure what the best way to format it is
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's better to use copy_from_slice
and u16::from_be/le_bytes
for such manipulations
It has been a while since I looked at it, but IIRC, yes |
@luctius Any news on this? Is there help needed somewhere? |
I had been working on addressing the comments for the unsafe blocks (irwineffect@0a997b0), although when I started to do more testing of the branch I had noticed some occasional issues when erasing the flash. It mostly worked, but occasionally I think the hardware was getting stuck in a weird state, I think the erase logic as it exists right now isn't quite correct (the reference manual PM0075 also is somewhat ambiguous). |
Well, I've been testing and I haven't been able to replicate the issues I had seen earlier, everything seems ok...perhaps my hardware was just wigging out? Sorry for the doubt, @luctius. |
It seems that @luctius hasn't signed on in a long time...should I create a pull request for irwineffect/stm32f1xx-hal@0a997b0? This is based on @luctius's branch, plus I've tried to address the comments. |
Sorry for the late reply.
I'd say you should, it's pointless to have a stale PR waiting when one that can make progress is available :) |
This PR can now be continued on #257 |
I'll go ahead and close this then :) |
This pr adds support for flash reading and writing.
I think the API can be improved and I am open for suggestions on that front.