-
Notifications
You must be signed in to change notification settings - Fork 3k
TARGET_STM32F7: Refresh cache when erasing or programming flash #10248
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
| status = -1; | ||
| } | ||
|
|
||
| SCB_CleanInvalidateDCache(); |
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 ranged invalidate-only would be less disruptive than a full clean+invalidate.
The I cache invalidate should also be ranged too, but it seems that CMSIS doesn't have a ranged version of SCB_InvalidateICache for some reason, despite the M7 supporting it.
Feels like the lock should be reapplied first - as soon as 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.
For the D cache, I tried with this code :
{
int i = 0;
uint32_t address_sector = FLASH_BASE;
for(i=0;i<SectorId;i++){
address_sector += GetSectorSize(i);
}
SCB_CleanInvalidateDCache_by_Addr(&address_sector, GetSectorSize(SectorId));
SCB_InvalidateICache();
}
Unfortunately, this was not working.
Then, I think the time consumed by SCB_CleanInvalidateDCache() is not so important compared to the memory erase.
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.
You should just need to do SCB_CleanInvalidateDCache_by_Addr(data, size), except for the fact that the original parameters have been modified.
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.
Ah, that was for the program. I see what you mean now for the erase code - you needed to mess to try to find the sector start address.
Your code looks correct, except you have &address_sector in the invalidate where it should be address_sector.
It would make sense to package that as a GetSectorBase(SectorId) function.
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 insisting ! I pushed a new version including your remarks. I invalidate and clean only the concern sector. I have also added a function to get sector base address.
The rebase on master forced me to clean my code and the test is passed now...
|
@offirko can you please review? |
|
@VVESTM, thank you for your changes. |
|
|
||
| address_sector = GetSectorBase(SectorId); | ||
|
|
||
| SCB_CleanInvalidateDCache_by_Addr(&address_sector, GetSectorSize(SectorId)); |
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 still wants to be address_sector, not &address_sector. Not sure how that's working. Or even just
SCB_InvalidateDCache_by_Addr((uint32_t *) GetSectorBase(SectorId), GetSectorSize(SectorId));
(Invalidate vs CleanInvalidate doesn't matter - it's a write-through region that we're not writing to anyway)
Bit wonky that the function takes uint32_t *, it doesn't actually need a word-aligned address.
| } | ||
| } | ||
|
|
||
| SCB_CleanInvalidateDCache_by_Addr(&address, size); |
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.
Again, wants (uint32_t *) address, not &address.
Except the loop above has incremented/decremented them, so you'll need to do something to store the original values.
The cache must be refreshed when we erase or program flash memory.
It fix 2 issues :
Fix ARMmbed#9934
Fix ARMmbed#6380
This solution was initially proposed in ARMmbed#6380.
Signed-off-by: Vincent Veron <[email protected]>
kjbracey
left a comment
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 to me now.
I'm considering putting in a patch to CMSIS to give you SCB_InvalidateICache_by_Addr.
|
Thanks @kjbracey-arm. |
| } | ||
|
|
||
| SCB_CleanInvalidateDCache_by_Addr((uint32_t *)GetSectorBase(SectorId), GetSectorSize(SectorId)); | ||
| SCB_InvalidateICache(); |
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.
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.
Good point. In principle you could be intending to load code into that section of flash and execute it, but is that actually a supported use case for this API? Is it really just intended for storage?
If this is just for storage, then you wouldn't need the I-cache invalidate. Or if you knew you were going to reboot before executing whatever you were loading.
Seems better safe than sorry, although the unranged invalidate makes it a bit painful. If it was ranged would be no big deal.
In the #6380 example, the __IO macro is a volatile.
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.
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 believe the api is only used for storage and not for instructions execution..
Invalidating ICache would degrade performance, but if its minor then perhaps its better to be safe than sorry, as Kevin said..
@kjbracey-arm __IO is volatile, but I believe it was given as an example.
I'm not really sure if within "flash_erase_sector" there isn't a similar loop that doesn't use volatile.. checking.. "FLASH_WaitForLastOperation" for example
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.
Every single memory-mapped register, as used in the programming process, should be flagged with __IO or __I where it's defined, such as the FLASH->SR in that wait.
The programming process doesn't touch the actual ROM memory space, and there's no need for any further care with volatile or atomics there. If we invalidate after we've programmed, that also acts as the necessary compiler barrier, so from that point on we can just memcpy out like normal cached memory, as the default weak flash_read does - the ROM is stable and cacheable and compiler optimisable.
offirko
left a comment
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.
LGTM
|
I submitted a ranged I-cache invalidate PR to CMSIS: ARM-software/CMSIS_5#559 I also note that they've already changed the |
jeromecoutant
left a comment
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.
ST CI OK:
| target | platform_name | test suite | result | elapsed_time (sec) | copy_method |
|---|---|---|---|---|---|
| DISCO_F746NG-GCC_ARM | DISCO_F746NG | tests-mbed_drivers-flashiap | OK | 38.53 | default |
| DISCO_F746NG-GCC_ARM | DISCO_F746NG | tests-mbed_hal-flash | OK | 22.36 | default |
| DISCO_F746NG-IAR | DISCO_F746NG | tests-mbed_drivers-flashiap | OK | 37.97 | default |
| DISCO_F746NG-IAR | DISCO_F746NG | tests-mbed_hal-flash | OK | 21.12 | default |
| DISCO_F769NI-GCC_ARM | DISCO_F769NI | tests-mbed_drivers-flashiap | OK | 37.1 | default |
| DISCO_F769NI-GCC_ARM | DISCO_F769NI | tests-mbed_hal-flash | OK | 21.31 | default |
| DISCO_F769NI-IAR | DISCO_F769NI | tests-mbed_drivers-flashiap | OK | 36.13 | default |
| DISCO_F769NI-IAR | DISCO_F769NI | tests-mbed_hal-flash | OK | 20.56 | default |
| NUCLEO_F746ZG-GCC_ARM | NUCLEO_F746ZG | tests-mbed_drivers-flashiap | OK | 38.41 | default |
| NUCLEO_F746ZG-GCC_ARM | NUCLEO_F746ZG | tests-mbed_hal-flash | OK | 21.65 | default |
| NUCLEO_F746ZG-IAR | NUCLEO_F746ZG | tests-mbed_drivers-flashiap | OK | 38.02 | default |
| NUCLEO_F746ZG-IAR | NUCLEO_F746ZG | tests-mbed_hal-flash | OK | 20.84 | default |
| NUCLEO_F756ZG-GCC_ARM | NUCLEO_F756ZG | tests-mbed_drivers-flashiap | OK | 37.55 | default |
| NUCLEO_F756ZG-GCC_ARM | NUCLEO_F756ZG | tests-mbed_hal-flash | OK | 21.95 | default |
| NUCLEO_F756ZG-IAR | NUCLEO_F756ZG | tests-mbed_drivers-flashiap | OK | 37.32 | default |
| NUCLEO_F756ZG-IAR | NUCLEO_F756ZG | tests-mbed_hal-flash | OK | 20.73 | default |
| NUCLEO_F767ZI-GCC_ARM | NUCLEO_F767ZI | tests-mbed_drivers-flashiap | OK | 37.61 | default |
| NUCLEO_F767ZI-GCC_ARM | NUCLEO_F767ZI | tests-mbed_hal-flash | OK | 21.79 | default |
| NUCLEO_F767ZI-IAR | NUCLEO_F767ZI | tests-mbed_drivers-flashiap | OK | 36.66 | default |
| NUCLEO_F767ZI-IAR | NUCLEO_F767ZI | tests-mbed_hal-flash | OK | 20.83 | default |
|
@kjbracey-arm, so we can merge my PR now and then, once ARM-software/CMSIS_5#559 is available in mbed, we can make a new PR to invalidate only the requested Icache range. |
|
Progressing PR. |
|
CI started |
Test run: FAILEDSummary: 1 of 9 test jobs failed Failed test jobs:
|
|
failure seems to be some sort of timeout involving IAR. re-starting CI |
Test run: FAILEDSummary: 1 of 13 test jobs failed Failed test jobs:
|
|
restarted |
Test run: SUCCESSSummary: 13 of 13 test jobs passed |
|
ST_INTERNAL_REF 63073 |
This copies the approach of the STM32F7 flash driver submitted via PR ARMmbed#10248 With this change the board finally passes all of the device key tests 10/10 times correctly.
Seems the F4 family is also missing the cache cleanup fixes in the flash_api.c. Same fix as in original Mbed OS PR by Vincent Veron <[email protected]> ARMmbed#10248
Seems the F4 family is also missing the cache cleanup fixes in the flash_api.c. Same fix as in original Mbed OS PR by Vincent Veron <[email protected]> ARMmbed#10248 However, as the cache invalidation instructions are not available in CM4, we're trying to use the same ones as the flash_api.c is already using for this family.
Seems the F4 family is also missing the cache cleanup fixes in the flash_api.c. Same fix as in original Mbed OS PR by Vincent Veron <[email protected]> ARMmbed#10248 However, as the cache invalidation instructions are not available in CM4, we're trying to use the same ones as the flash_api.c is already using for this family.
Seems the F4 family is also missing the cache cleanup fixes in the flash_api.c. Same fix as in original Mbed OS PR by Vincent Veron <[email protected]> ARMmbed#10248 However, as the cache invalidation instructions are not available in CM4, we're trying to use the same ones as the flash_api.c is already using for this family.
Seems the F4 family is also missing the cache cleanup fixes in the flash_api.c. Same fix as in original Mbed OS PR by Vincent Veron <[email protected]> ARMmbed#10248 However, as the cache invalidation instructions are not available in CM4, we're trying to use the same ones as the flash_api.c is already using for this family.
Seems the F4 family is also missing the cache cleanup fixes in the flash_api.c. Same fix as in original Mbed OS PR by Vincent Veron <[email protected]> ARMmbed#10248 However, as the cache invalidation instructions are not available in CM4, we're trying to use the same ones as the flash_api.c is already using for this family.
Seems the F4 family is also missing the cache cleanup fixes in the flash_api.c. Same fix as in original Mbed OS PR by Vincent Veron <[email protected]> ARMmbed#10248 However, as the cache invalidation instructions are not available in CM4, we're trying to use the FLASH_FlushCaches available in stm32f4xx_hal_flash. (STM has implemented their own flash cache). In case of programming the flash we should also flush the caches, as it is theoretically possible the programming failed but a readback test would not find it, if it gets that readback from the cache, instead of the flash. Thus a potential write failure could go unnoticed.
This copies the approach of the STM32F7 flash driver submitted via PR #10248 With this change the board finally passes all of the device key tests 10/10 times correctly.
TARGET_STM32F7: Refresh cache when erasing or programming flash
The cache must be refreshed when we erase or program flash memory.
It fix 2 issues :
Fix #9934
Fix #6380
This solution was initially proposed in #6380.
Solution tested on mbed-os-5.12.0 and STM32F746 Disco board with this command:
mbed test -t ARM -m DISCO_F746NG -v -n features-storage-tests-blockdevice-general_block_device -v