diff options
| -rw-r--r-- | ports/nrf/supervisor/port.c | 16 | ||||
| -rw-r--r-- | ports/nrf/supervisor/qspi_flash.c | 39 |
2 files changed, 34 insertions, 21 deletions
diff --git a/ports/nrf/supervisor/port.c b/ports/nrf/supervisor/port.c index 05970a3ed..36c9f836e 100644 --- a/ports/nrf/supervisor/port.c +++ b/ports/nrf/supervisor/port.c @@ -65,6 +65,10 @@ #include "common-hal/audiopwmio/PWMAudioOut.h" #endif +#if defined(MICROPY_QSPI_CS) && defined(MICROPY_QSPI_OFF_WHEN_SLEEP) +extern void qspi_disable(void); +#endif + static void power_warning_handler(void) { reset_into_safe_mode(BROWNOUT); } @@ -296,17 +300,7 @@ void port_interrupt_after_ticks(uint32_t ticks) { void port_sleep_until_interrupt(void) { #if defined(MICROPY_QSPI_CS) && defined(MICROPY_QSPI_OFF_WHEN_SLEEP) - // Turn off QSPI when USB is disconnected - if (NRF_QSPI->ENABLE && !(NRF_POWER->USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk)) { - // Keep CS high when QSPI is diabled - nrf_gpio_cfg_output(MICROPY_QSPI_CS); - nrf_gpio_pin_write(MICROPY_QSPI_CS, 1); - - // Workaround to disable QSPI according to nRF52840 Revision 1 Errata V1.4 - 3.8 - NRF_QSPI->TASKS_DEACTIVATE = 1; - *(volatile uint32_t *)0x40029054 = 1; - NRF_QSPI->ENABLE = 0; - } + qspi_disable(); #endif // Clear the FPU interrupt because it can prevent us from sleeping. diff --git a/ports/nrf/supervisor/qspi_flash.c b/ports/nrf/supervisor/qspi_flash.c index d5c60ac9e..852f0c44a 100644 --- a/ports/nrf/supervisor/qspi_flash.c +++ b/ports/nrf/supervisor/qspi_flash.c @@ -38,10 +38,9 @@ #include "supervisor/shared/external_flash/common_commands.h" #include "supervisor/shared/external_flash/qspi_flash.h" +// When USB is disconnected, disable QSPI in sleep mode to save energy #if defined(MICROPY_QSPI_OFF_WHEN_SLEEP) -#define QSPI_ENABLE() qspi_enable() - -static void qspi_enable(void) +void qspi_enable(void) { if (NRF_QSPI->ENABLE) { return; @@ -61,12 +60,32 @@ static void qspi_enable(void) } while (--remaining_attempts); } +void qspi_disable(void) +{ + // Turn off QSPI when USB is disconnected + if (NRF_QSPI->ENABLE && !(NRF_POWER->USBREGSTATUS & POWER_USBREGSTATUS_VBUSDETECT_Msk)) { + // Keep CS high when QSPI is diabled + nrf_gpio_cfg_output(MICROPY_QSPI_CS); + nrf_gpio_pin_write(MICROPY_QSPI_CS, 1); + + // Workaround to disable QSPI according to nRF52840 Revision 1 Errata V1.4 - 3.8 + NRF_QSPI->TASKS_DEACTIVATE = 1; + *(volatile uint32_t *)0x40029054 = 1; + NRF_QSPI->ENABLE = 0; + } +} #else -#define QSPI_ENABLE() ((void)0) +void qspi_enable(void) +{ +} + +void qspi_disable(void) +{ +} #endif bool spi_flash_command(uint8_t command) { - QSPI_ENABLE(); + qspi_enable(); nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode = command, .length = 1, @@ -79,7 +98,7 @@ bool spi_flash_command(uint8_t command) { } bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length) { - QSPI_ENABLE(); + qspi_enable(); nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode = command, .length = length + 1, @@ -93,7 +112,7 @@ bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length) } bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) { - QSPI_ENABLE(); + qspi_enable(); nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode = command, .length = length + 1, @@ -106,7 +125,7 @@ bool spi_flash_write_command(uint8_t command, uint8_t* data, uint32_t length) { } bool spi_flash_sector_command(uint8_t command, uint32_t address) { - QSPI_ENABLE(); + qspi_enable(); if (command != CMD_SECTOR_ERASE) { return false; } @@ -114,7 +133,7 @@ bool spi_flash_sector_command(uint8_t command, uint32_t address) { } bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) { - QSPI_ENABLE(); + qspi_enable(); // TODO: In theory, this also needs to handle unaligned data and // non-multiple-of-4 length. (in practice, I don't think the fat layer // generates such writes) @@ -122,7 +141,7 @@ bool spi_flash_write_data(uint32_t address, uint8_t* data, uint32_t length) { } bool spi_flash_read_data(uint32_t address, uint8_t* data, uint32_t length) { - QSPI_ENABLE(); + qspi_enable(); int misaligned = ((intptr_t)data) & 3; // If the data is misaligned, we need to read 4 bytes // into an aligned buffer, and then copy 1, 2, or 3 bytes from the aligned |
