-
Notifications
You must be signed in to change notification settings - Fork 48
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
Changes to Flash.rs #83
Conversation
amcelroy
commented
Sep 14, 2023
- FlashWriter for certain chips requires the PAGE_SIZE_KB to be passed in. Some chips are single bank with 4096kB page size and some chips are dual bank with 2048kB page size. It seems this should be an option easily configured by the user.
- Can unlock the Options register (at your own risk)
- Changed Flash write to write 2 32-bit words as per the manual.
- Can write arbitrary array lengths to flash. If data is < 8 bytes (2 32-bit words), the data is padded with 0xFF.
- page_erase was fixed. Writing to the pnb() register was wiping the per() bit. Changed register access from write -> modify
- Verify now checks the 2 32-bit words.
- FlashWriter for certain chips requires the PAGE_SIZE_KB to be passed in. Some chips are single bank with 4096kB page size and some chips are dual bank with 2048kB page size. It seems this should be an option easily configured by the user. - Can unlock the Options register (at your own risk) - Changed Flash write to write 2 32-bit words as per the manual. - Can write arbitrary array lengths to flash. If data is < 8 bytes (2 32-bit words), the data is padded with 0xFF. - page_erase was fixed. Writing to the pnb() register was wiping the per() bit. Changed register access from write -> modify - Verify now checks the 2 32-bit words.
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 have tested the implementation with my stm32g491re
and it works fine.
The only issue I had is attributable to a problem in the PAC.
The stm32g491re
is a category 4 device with 512 Kbytes flash and a page size of 2048.
Consequently, 256 pages must addressable but according to the svd-file/PAC
the page number (pnb
) bits of the FLASH_CR
is 7 bit width.
The 7 bit width is correct for category 3 and category 2 devices, but not for category 4 devices where 8 bits would be proper (see RM0440 Rev 7 P. 180 (Embedded Flash memory (FLASH) for category 4 devices) FLASH_CR
register).
This shouldn't be an issue of your implementation, and should be resolved when this is fixed in svd2rust.
Btw. thanks and in my opinion it would be nice to have your example simplified and linked/included in the docs.
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.
Thank you for the review!
- Linter fixes - Added code comment that clarifies the need to write double words - Added an example called flash_with_rtic.rs to show flash memory use case.
Thanks, for the quick response ;). I have added a note from my colleague. |
src/flash.rs
Outdated
// Check if there is enough data to make 2 words, if there isn't, pad the data with 0xFF | ||
if idx + 8 > data.len() { | ||
let mut tmp_buffer = [255 as u8; 8]; | ||
for jdx in idx..data.len() { | ||
tmp_buffer[jdx] = data[idx + jdx]; | ||
} | ||
let tmp_dword = u64::from_le_bytes(tmp_buffer); | ||
word1 = tmp_dword as u32; | ||
word2 = (tmp_dword >> 32) as 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.
A note from my colleague:
For me this is a bit to much intelligence/"magic" within the driver. In my opinion we should check whether the user passes data to us whose length is a multiple of 8 and return an error, if this is not the case.
Background:
Imagine, a user doesn't know, that we only can write multiples of 8. This user passes blocks of 4 bytes (this is valid for a lot of MCUs). The first write succeeds, because you added the missing 4 bytes. The next write will fail, because writing 0xFF is internally another state than a deleted flash block and the MCU's flash routine will return an error, if the user tries to write his next block of 4 bytes.
We should inform the user that he does not fulfill the boundary conditions as soon as he writes the first time (via an error). This is because the error in the second write is de facto only a subsequent error.
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.
Yes, I see y'alls perspective. On a previous MCU I worked with, as long as the alignment was fine, a flash bits could go from 1 -> 0, so padding with 0xFF didn't cause an issue and made writing data easier since the user didn't need to worry about data length, only alignment of the start address and that the flash block was already empty.
Let me write some test cases to cover this and see what happens. If there are any issues with this test I will add a check to ensure incoming arrays are divisible by 8 and return an error (or add a new one) that makes this condition clear.
Thank you for the feedback.
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 did a bit more testing and recognize your colleagues complaint. However, I still would like writing data to be easy in most cases. A hopeful solution is adding a flag to FlashWriter.write
called force_data_padding
, along with function comments, that makes it clear that data padding is going on.
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 have no objections in this respect, since the padding with 0xFF
is then at least obvious.
Maybe, instead of a Boolean flag, two methods would be more suitable, just an idea.
- 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
examples/flash_with_rtic.rs
Outdated
match i { | ||
0 => { | ||
// This test should fail, as the data needs to be divisible by 8 and force padding is false | ||
let result = flash_writer.write(0x1FC00 + i * FLASH_SPACING, &one_byte, false); |
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.
Use constant instead magic numbers
src/flash.rs
Outdated
|
||
// Check if there is enough data to make 2 words, if there isn't, pad the data with 0xFF | ||
if idx + 8 > data.len() { | ||
let mut tmp_buffer = [255 as u8; 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.
should be 255u8
?
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.
also, why this buffer length use?
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.
That buffer is used to pad non-divisible-by-8 data if the user wants an "easy" way to write data to flash. The STM32G4 requires 8 bytes to be written at a time. The user can use the force_data_padding
flag so that data that isn't divisible by 8 is buffered into tmp_buffer
and appropriately padded on the fly.
I can change it to 255u8 if that is preferred.
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.
Great, also don't forget remove TODO for flash register structure.
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.
Ok, I think it is complete, thank you for reviewing!
- Added logging and const test address location to flash_with_rtic.rs - Changed type formatting on a buffer array in flash.rs - Removed //TODO and #[allow(dead_code)] from flash register structure Parts.