Merge pull request #7398 from dhalbert/cache-memory-fence
Use memory fence when disabling cache to avoid -O2 problems
This commit is contained in:
commit
e8ee4b220e
@ -1 +1 @@
|
|||||||
Subproject commit 57133eefeb077f73b5ac17ee044d9feaf566da8e
|
Subproject commit baca4c084334aa8625f525a4032d66a397199ea6
|
@ -29,8 +29,18 @@
|
|||||||
|
|
||||||
// Turn off cache and invalidate all data in it.
|
// Turn off cache and invalidate all data in it.
|
||||||
void nrf_peripherals_disable_and_clear_cache(void) {
|
void nrf_peripherals_disable_and_clear_cache(void) {
|
||||||
|
// Memory fence for hardware and compiler reasons. If this routine is inlined, the compiler
|
||||||
|
// needs to know that everything written out be stored before this is called.
|
||||||
|
// -O2 optimization needed this on SAMD51. Assuming nRF may have the same issue.
|
||||||
|
// __sync_synchronize() includes volatile asm(), which tells the compiler not to assume
|
||||||
|
// state across this call.
|
||||||
|
__sync_synchronize();
|
||||||
|
|
||||||
// Disabling cache also invalidates all cache entries.
|
// Disabling cache also invalidates all cache entries.
|
||||||
NRF_NVMC->ICACHECNF &= ~(1 << NVMC_ICACHECNF_CACHEEN_Pos);
|
NRF_NVMC->ICACHECNF &= ~(1 << NVMC_ICACHECNF_CACHEEN_Pos);
|
||||||
|
|
||||||
|
// Memory fence for hardware and compiler reasons.
|
||||||
|
__sync_synchronize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable cache
|
// Enable cache
|
||||||
|
@ -58,6 +58,9 @@ static supervisor_allocation *supervisor_cache = NULL;
|
|||||||
|
|
||||||
// Wait until both the write enable and write in progress bits have cleared.
|
// Wait until both the write enable and write in progress bits have cleared.
|
||||||
static bool wait_for_flash_ready(void) {
|
static bool wait_for_flash_ready(void) {
|
||||||
|
if (flash_device == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
// Both the write enable and write in progress bits should be low.
|
// Both the write enable and write in progress bits should be low.
|
||||||
if (flash_device->no_ready_bit) {
|
if (flash_device->no_ready_bit) {
|
||||||
@ -192,6 +195,9 @@ static bool copy_block(uint32_t src_address, uint32_t dest_address) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define READ_JEDEC_ID_RETRY_COUNT (100)
|
||||||
|
|
||||||
|
// If this fails, flash_device will remain NULL.
|
||||||
void supervisor_flash_init(void) {
|
void supervisor_flash_init(void) {
|
||||||
if (flash_device != NULL) {
|
if (flash_device != NULL) {
|
||||||
return;
|
return;
|
||||||
@ -220,7 +226,11 @@ void supervisor_flash_init(void) {
|
|||||||
#else
|
#else
|
||||||
// The response will be 0xff if the flash needs more time to start up.
|
// The response will be 0xff if the flash needs more time to start up.
|
||||||
uint8_t jedec_id_response[3] = {0xff, 0xff, 0xff};
|
uint8_t jedec_id_response[3] = {0xff, 0xff, 0xff};
|
||||||
while (jedec_id_response[0] == 0xff) {
|
// Response can also be 0x00 if reading before ready. When compiled with `-O2`, typically
|
||||||
|
// takes three tries to read on Grand Central M4.
|
||||||
|
|
||||||
|
size_t count = READ_JEDEC_ID_RETRY_COUNT;
|
||||||
|
while ((count-- > 0) && (jedec_id_response[0] == 0xff || jedec_id_response[2] == 0x00)) {
|
||||||
spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 3);
|
spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 3);
|
||||||
}
|
}
|
||||||
for (uint8_t i = 0; i < EXTERNAL_FLASH_DEVICE_COUNT; i++) {
|
for (uint8_t i = 0; i < EXTERNAL_FLASH_DEVICE_COUNT; i++) {
|
||||||
@ -234,6 +244,7 @@ void supervisor_flash_init(void) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (flash_device == NULL) {
|
if (flash_device == NULL) {
|
||||||
|
// Flash did not respond. Give up.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,6 +304,9 @@ uint32_t supervisor_flash_get_block_size(void) {
|
|||||||
|
|
||||||
// The total number of available blocks.
|
// The total number of available blocks.
|
||||||
uint32_t supervisor_flash_get_block_count(void) {
|
uint32_t supervisor_flash_get_block_count(void) {
|
||||||
|
if (flash_device == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
// We subtract one erase sector size because we may use it as a staging area
|
// We subtract one erase sector size because we may use it as a staging area
|
||||||
// for writes.
|
// for writes.
|
||||||
return (flash_device->total_size - SPI_FLASH_ERASE_SIZE) / FILESYSTEM_BLOCK_SIZE;
|
return (flash_device->total_size - SPI_FLASH_ERASE_SIZE) / FILESYSTEM_BLOCK_SIZE;
|
||||||
|
Loading…
Reference in New Issue
Block a user