diff --git a/ports/atmel-samd/peripherals b/ports/atmel-samd/peripherals index 57133eefeb..baca4c0843 160000 --- a/ports/atmel-samd/peripherals +++ b/ports/atmel-samd/peripherals @@ -1 +1 @@ -Subproject commit 57133eefeb077f73b5ac17ee044d9feaf566da8e +Subproject commit baca4c084334aa8625f525a4032d66a397199ea6 diff --git a/ports/nrf/peripherals/nrf/cache.c b/ports/nrf/peripherals/nrf/cache.c index 6eb590d770..54bb77980b 100644 --- a/ports/nrf/peripherals/nrf/cache.c +++ b/ports/nrf/peripherals/nrf/cache.c @@ -29,8 +29,18 @@ // Turn off cache and invalidate all data in it. 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. NRF_NVMC->ICACHECNF &= ~(1 << NVMC_ICACHECNF_CACHEEN_Pos); + + // Memory fence for hardware and compiler reasons. + __sync_synchronize(); } // Enable cache diff --git a/supervisor/shared/external_flash/external_flash.c b/supervisor/shared/external_flash/external_flash.c index 7da45fdc99..141ad7e5f8 100644 --- a/supervisor/shared/external_flash/external_flash.c +++ b/supervisor/shared/external_flash/external_flash.c @@ -58,6 +58,9 @@ static supervisor_allocation *supervisor_cache = NULL; // Wait until both the write enable and write in progress bits have cleared. static bool wait_for_flash_ready(void) { + if (flash_device == NULL) { + return false; + } bool ok = true; // Both the write enable and write in progress bits should be low. if (flash_device->no_ready_bit) { @@ -192,6 +195,9 @@ static bool copy_block(uint32_t src_address, uint32_t dest_address) { return true; } +#define READ_JEDEC_ID_RETRY_COUNT (100) + +// If this fails, flash_device will remain NULL. void supervisor_flash_init(void) { if (flash_device != NULL) { return; @@ -220,7 +226,11 @@ void supervisor_flash_init(void) { #else // The response will be 0xff if the flash needs more time to start up. 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); } for (uint8_t i = 0; i < EXTERNAL_FLASH_DEVICE_COUNT; i++) { @@ -234,6 +244,7 @@ void supervisor_flash_init(void) { } #endif if (flash_device == NULL) { + // Flash did not respond. Give up. return; } @@ -293,6 +304,9 @@ uint32_t supervisor_flash_get_block_size(void) { // The total number of available blocks. 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 // for writes. return (flash_device->total_size - SPI_FLASH_ERASE_SIZE) / FILESYSTEM_BLOCK_SIZE;