Skip to content

Commit e8ee4b2

Browse files
authored
Merge pull request #7398 from dhalbert/cache-memory-fence
Use memory fence when disabling cache to avoid -O2 problems
2 parents a424fa0 + cc92ce4 commit e8ee4b2

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

ports/nrf/peripherals/nrf/cache.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,18 @@
2929

3030
// Turn off cache and invalidate all data in it.
3131
void nrf_peripherals_disable_and_clear_cache(void) {
32+
// Memory fence for hardware and compiler reasons. If this routine is inlined, the compiler
33+
// needs to know that everything written out be stored before this is called.
34+
// -O2 optimization needed this on SAMD51. Assuming nRF may have the same issue.
35+
// __sync_synchronize() includes volatile asm(), which tells the compiler not to assume
36+
// state across this call.
37+
__sync_synchronize();
38+
3239
// Disabling cache also invalidates all cache entries.
3340
NRF_NVMC->ICACHECNF &= ~(1 << NVMC_ICACHECNF_CACHEEN_Pos);
41+
42+
// Memory fence for hardware and compiler reasons.
43+
__sync_synchronize();
3444
}
3545

3646
// Enable cache

supervisor/shared/external_flash/external_flash.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ static supervisor_allocation *supervisor_cache = NULL;
5858

5959
// Wait until both the write enable and write in progress bits have cleared.
6060
static bool wait_for_flash_ready(void) {
61+
if (flash_device == NULL) {
62+
return false;
63+
}
6164
bool ok = true;
6265
// Both the write enable and write in progress bits should be low.
6366
if (flash_device->no_ready_bit) {
@@ -192,6 +195,9 @@ static bool copy_block(uint32_t src_address, uint32_t dest_address) {
192195
return true;
193196
}
194197

198+
#define READ_JEDEC_ID_RETRY_COUNT (100)
199+
200+
// If this fails, flash_device will remain NULL.
195201
void supervisor_flash_init(void) {
196202
if (flash_device != NULL) {
197203
return;
@@ -220,7 +226,11 @@ void supervisor_flash_init(void) {
220226
#else
221227
// The response will be 0xff if the flash needs more time to start up.
222228
uint8_t jedec_id_response[3] = {0xff, 0xff, 0xff};
223-
while (jedec_id_response[0] == 0xff) {
229+
// Response can also be 0x00 if reading before ready. When compiled with `-O2`, typically
230+
// takes three tries to read on Grand Central M4.
231+
232+
size_t count = READ_JEDEC_ID_RETRY_COUNT;
233+
while ((count-- > 0) && (jedec_id_response[0] == 0xff || jedec_id_response[2] == 0x00)) {
224234
spi_flash_read_command(CMD_READ_JEDEC_ID, jedec_id_response, 3);
225235
}
226236
for (uint8_t i = 0; i < EXTERNAL_FLASH_DEVICE_COUNT; i++) {
@@ -234,6 +244,7 @@ void supervisor_flash_init(void) {
234244
}
235245
#endif
236246
if (flash_device == NULL) {
247+
// Flash did not respond. Give up.
237248
return;
238249
}
239250

@@ -293,6 +304,9 @@ uint32_t supervisor_flash_get_block_size(void) {
293304

294305
// The total number of available blocks.
295306
uint32_t supervisor_flash_get_block_count(void) {
307+
if (flash_device == NULL) {
308+
return 0;
309+
}
296310
// We subtract one erase sector size because we may use it as a staging area
297311
// for writes.
298312
return (flash_device->total_size - SPI_FLASH_ERASE_SIZE) / FILESYSTEM_BLOCK_SIZE;

0 commit comments

Comments
 (0)