Skip to content
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

Closed
wants to merge 2 commits into from
Closed

Conversation

luctius
Copy link

@luctius luctius commented Nov 22, 2019

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.

Copy link
Member

@thalesfragoso thalesfragoso left a 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,
Copy link
Member

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 {
Copy link
Member

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.

Copy link
Member

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 {
Copy link
Member

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 {
Copy link
Member

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;
Copy link
Member

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
Copy link
Member

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
Copy link
Member

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() {
Copy link
Member

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() {
Copy link
Member

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) };
Copy link
Member

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 ?

@luctius
Copy link
Author

luctius commented Nov 22, 2019

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.

Copy link
Member

@TheZoq2 TheZoq2 left a 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 {
Copy link
Member

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 {
Copy link
Member

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)]
Copy link
Member

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?

Copy link
Author

@luctius luctius Nov 29, 2019

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
@luctius
Copy link
Author

luctius commented Nov 29, 2019

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.

Copy link
Member

@TheZoq2 TheZoq2 left a 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
Copy link
Member

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

Comment on lines +221 to +223
let hword: u16 =
(data[idx] as u16)
| (data[idx+1] as u16) << 8;
Copy link
Member

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

Copy link
Member

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

@irwineffect
Copy link
Contributor

@luctius, @TheZoq2, if the remaining comments are addressed, would this be ready to merge in?

@TheZoq2
Copy link
Member

TheZoq2 commented Mar 31, 2020

It has been a while since I looked at it, but IIRC, yes

@DerFetzer
Copy link

@luctius Any news on this? Is there help needed somewhere?

@irwineffect
Copy link
Contributor

irwineffect commented Jul 9, 2020

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).
It's been a while since I had looked at it, but I'll dig up what I had been working on and post more details.

@irwineffect
Copy link
Contributor

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.

@irwineffect
Copy link
Contributor

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.

@TheZoq2
Copy link
Member

TheZoq2 commented Aug 12, 2020

Sorry for the late reply.

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.

I'd say you should, it's pointless to have a stale PR waiting when one that can make progress is available :)

@irwineffect
Copy link
Contributor

This PR can now be continued on #257

@TheZoq2
Copy link
Member

TheZoq2 commented Aug 22, 2020

I'll go ahead and close this then :)

@TheZoq2 TheZoq2 closed this Aug 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants