Skip to content

Conversation

@VVESTM
Copy link
Contributor

@VVESTM VVESTM commented Mar 28, 2019

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

@VVESTM VVESTM closed this Mar 28, 2019
@VVESTM VVESTM reopened this Mar 28, 2019
status = -1;
}

SCB_CleanInvalidateDCache();
Copy link
Contributor

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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.

Copy link
Contributor

@kjbracey kjbracey Mar 28, 2019

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.

Copy link
Contributor Author

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...

@dannybenor
Copy link

@offirko can you please review?

@ciarmcom ciarmcom requested review from a team and screamerbg March 28, 2019 12:00
@ciarmcom
Copy link
Member

@VVESTM, thank you for your changes.
@screamerbg @ARMmbed/mbed-os-maintainers please review.


address_sector = GetSectorBase(SectorId);

SCB_CleanInvalidateDCache_by_Addr(&address_sector, GetSectorSize(SectorId));
Copy link
Contributor

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

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]>
Copy link
Contributor

@kjbracey kjbracey left a 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.

@VVESTM
Copy link
Contributor Author

VVESTM commented Mar 28, 2019

Thanks @kjbracey-arm.

}

SCB_CleanInvalidateDCache_by_Addr((uint32_t *)GetSectorBase(SectorId), GetSectorSize(SectorId));
SCB_InvalidateICache();
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is Instrcution Cache invalidated as well? (couldnt find the reason at #6380).
Also, I think the example in #6380 could potentially also fit a missing volatile .. did you try it?

Copy link
Contributor

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Originally, the patch concerns only DCache. Followings comments on #9934 , I added ICache. Do you see an issue invalidating ICache ?
Didn't try anything with volatile on #6380

Copy link
Contributor

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

Copy link
Contributor

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.

Copy link
Contributor

@offirko offirko left a comment

Choose a reason for hiding this comment

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

LGTM

@kjbracey
Copy link
Contributor

I submitted a ranged I-cache invalidate PR to CMSIS: ARM-software/CMSIS_5#559

I also note that they've already changed the uint32_t * to void * upstream.

Copy link
Collaborator

@jeromecoutant jeromecoutant left a 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

@VVESTM
Copy link
Contributor Author

VVESTM commented Mar 29, 2019

@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.

@cmonr
Copy link
Contributor

cmonr commented Mar 29, 2019

#10248 (comment)

Progressing PR.

@cmonr
Copy link
Contributor

cmonr commented Mar 29, 2019

CI started

@mbed-ci
Copy link

mbed-ci commented Mar 29, 2019

Test run: FAILED

Summary: 1 of 9 test jobs failed
Build number : 1
Build artifacts

Failed test jobs:

  • jenkins-ci/mbed-os-ci_build-IAR8

@NirSonnenschein
Copy link
Contributor

failure seems to be some sort of timeout involving IAR. re-starting CI

@mbed-ci
Copy link

mbed-ci commented Mar 31, 2019

Test run: FAILED

Summary: 1 of 13 test jobs failed
Build number : 2
Build artifacts

Failed test jobs:

  • jenkins-ci/mbed-os-ci_greentea-test

@alekla01
Copy link
Contributor

alekla01 commented Apr 1, 2019

restarted jenkins-ci/mbed-os-ci_greentea-test

@mbed-ci
Copy link

mbed-ci commented Apr 1, 2019

Test run: SUCCESS

Summary: 13 of 13 test jobs passed
Build number : 3
Build artifacts

@jeromecoutant
Copy link
Collaborator

ST_INTERNAL_REF 63073

@cmonr cmonr merged commit cdc2579 into ARMmbed:master Apr 1, 2019
JanneKiiskila pushed a commit to JanneKiiskila/mbed-os that referenced this pull request Oct 30, 2019
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.
JanneKiiskila pushed a commit to JanneKiiskila/mbed-os that referenced this pull request Nov 1, 2019
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
JanneKiiskila pushed a commit to JanneKiiskila/mbed-os that referenced this pull request Nov 1, 2019
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.
JanneKiiskila pushed a commit to JanneKiiskila/mbed-os that referenced this pull request Nov 1, 2019
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.
JanneKiiskila pushed a commit to JanneKiiskila/mbed-os that referenced this pull request Nov 1, 2019
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.
JanneKiiskila pushed a commit to JanneKiiskila/mbed-os that referenced this pull request Nov 1, 2019
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.
JanneKiiskila pushed a commit to JanneKiiskila/mbed-os that referenced this pull request Nov 2, 2019
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.
JanneKiiskila pushed a commit to JanneKiiskila/mbed-os that referenced this pull request Nov 4, 2019
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.
adbridge pushed a commit that referenced this pull request Nov 19, 2019
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NUCLEO_F767ZI FLASHIAP erase functionality error HAL Flash sector erase doesn't work consistently