-
Notifications
You must be signed in to change notification settings - Fork 3k
Fix erase type determination for [Q/O/]BlockDevice::erase() #13947
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
Conversation
64cbaca
to
986318f
Compare
986318f
to
d43e3c9
Compare
… is checked [Q/O/SPIFBlockDevice::erase() begin with an alignment check, after which unaligned erases should not happen or be allowed. If the erase address is not aligned to the value returned by sfdp_iterate_next_largest_erase_type(), it indicates an internal error in erase table parsing which should not be hidden.
d43e3c9
to
7525134
Compare
@LDong-Arm, thank you for your changes. |
Hi @LDong-Arm, thanks for working on this issue.
|
Hi @boraozgen, thanks for the feedback.
The algorithm is expected to choose the largest block that satisfies alignment (and size) requirements. In the example you gave in #13528,
I completely agree. This an a few other SFDP and BlockDevice algorithm issues would've been caught with unit tests, but we can raise a separate issue.
That would be a good refactoring, we can create raise a separate issue. |
Okay, I think I isolated the issue further. When the I use this chip. See page 5 for memory map. When I call
However, when I call
Removing the following line seems to fix it. I think that line is meant to optimize for speed by avoiding checking the same types again. I could not think of a side-effect. Any thoughts? mbed-os/drivers/source/SFDP.cpp Line 419 in 7525134
|
How about starting with a unit test for this algorithm? I'm not familiar with the Mbed unit test infrastructure, otherwise I would suggest one. It would also be easier for others like me to extend the tests. |
I agree. Let's implement a unit test for this algorithm in this PR. |
Very good finding. I believe the originally implementation didn't take into account our scenario. The speed improvement (which is not functionally correct) here is rather minimal. |
The supported erase types of a given flash region are indicated in bitfields of the variable `type_mask`. Even if an erase type is unused for the current chunk (e.g. size too large, unaligned, etc.), its bitfield should NOT be cleared - the same erase type might actually be useful for the next chunk. The function argument is now a value instead of a reference.
Now it works correctly on my target. |
if (idx == -1) { | ||
tr_error("No erase type was found for current region addr"); | ||
} | ||
return largest_erase_type; |
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.
The old implementation incorrectly returned the last erase type it checked, instead of an error.
@boraozgen @evedon I've added a unit test as requested, and fixed another issue in To run all unit tests (I'm not aware of any way to run only one test, but all tests are extremely quick to run),
more info here. I recommend using Linux to run it if possible to avoid dependency issues. |
750c8f7
to
8cc8ce3
Compare
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.
Looks good. Excellent work.
As a starting point, only sfdp_iterate_next_largest_erase_type(), which the pull request is intended to fix, is tested. More test cases shall be added in the future.
8cc8ce3
to
c41f7cb
Compare
Thanks @evedon. I've just pushed final changes, fixing a few compiler warning around integers and chrono. |
CI started |
Jenkins CI Test : ✔️ SUCCESSBuild Number: 1 | 🔒 Jenkins CI Job | 🌐 Logs & ArtifactsCLICK for Detailed Summary
|
Summary of changes
Fixes: #13528
[Q/O/]BlockDevice::erase()
usesfdp_iterate_next_largest_erase_type()
to determine the largest erase size suitable for the requested address and size, as it means better erase performance than smaller chunks. But there are several issues:sfdp_iterate_next_largest_erase_type()
;bd->erase(addr, bd->get_erase_size(addr));
results in the following on all[Q/O/]BlockDevice
targets:[Q/O/]BlockDevice::erase()
: It first checks the address and size, and only continues if they are aligned. But after that, it tries to "handle" unaligned erase by erasing whole block. Such "handling" is not only unnecessary, but hides the error insfdp_iterate_next_largest_erase_type()
's return value mentioned above, results in data being wrongly erased. (Part of the cause of SPIFBlockDevice: erase block calculation issue #13528)Huge thanks to @boraozgen for identifying several of them.
This PR fixes those issues. A unit test for the optimal erase type determination algorithm is added too.
Impact of changes
[Q/O/]BlockDevice::erase()
's erase type determination now works, and it correctly erases requested address ranges.Migration actions required
None.
Documentation
None.
Pull request type
Test results
Reviewers
@ARMmbed/mbed-os-core @boraozgen