diff options
| author | Jeff Epler <jeff@adafruit.com> | 2020-08-10 16:06:57 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-08-10 16:06:57 -0500 |
| commit | 807f049dc3b2d41985534063e355c1ad0904fe3f (patch) | |
| tree | 88db17b90d5ae5a6c5773e52dab0330f3087d18a | |
| parent | 78f90db72f35ecab052c70411cb7d1d1a1980970 (diff) | |
| parent | af1291ec28a8d2881e820fc1ce9b938ab5a6f097 (diff) | |
Merge pull request #3244 from xiongyihui/main
add an option to turn off QSPI when sleep
| -rw-r--r-- | ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.h | 7 | ||||
| -rw-r--r-- | ports/nrf/supervisor/port.c | 8 | ||||
| -rw-r--r-- | ports/nrf/supervisor/qspi_flash.c | 42 |
3 files changed, 54 insertions, 3 deletions
diff --git a/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.h b/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.h index 086718089..4fb6049c5 100644 --- a/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.h +++ b/ports/nrf/boards/makerdiary_m60_keyboard/mpconfigboard.h @@ -30,9 +30,10 @@ #define MICROPY_HW_BOARD_NAME "Makerdiary M60 Keyboard" #define MICROPY_HW_MCU_NAME "nRF52840" -#define CP_RGB_STATUS_R (&pin_P0_30) -#define CP_RGB_STATUS_G (&pin_P0_29) -#define CP_RGB_STATUS_B (&pin_P0_31) +// RGB LEDs use PWM peripheral, avoid using them to save energy +// #define CP_RGB_STATUS_R (&pin_P0_30) +// #define CP_RGB_STATUS_G (&pin_P0_29) +// #define CP_RGB_STATUS_B (&pin_P0_31) #define MICROPY_QSPI_DATA0 NRF_GPIO_PIN_MAP(1, 10) #define MICROPY_QSPI_DATA1 NRF_GPIO_PIN_MAP(1, 14) diff --git a/ports/nrf/supervisor/port.c b/ports/nrf/supervisor/port.c index e681e6825..87a4d7396 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) +extern void qspi_disable(void); +#endif + static void power_warning_handler(void) { reset_into_safe_mode(BROWNOUT); } @@ -295,6 +299,10 @@ void port_interrupt_after_ticks(uint32_t ticks) { } void port_sleep_until_interrupt(void) { +#if defined(MICROPY_QSPI_CS) + qspi_disable(); +#endif + // Clear the FPU interrupt because it can prevent us from sleeping. if (NVIC_GetPendingIRQ(FPU_IRQn)) { __set_FPSCR(__get_FPSCR() & ~(0x9f)); diff --git a/ports/nrf/supervisor/qspi_flash.c b/ports/nrf/supervisor/qspi_flash.c index 90260b091..5ab56c6bc 100644 --- a/ports/nrf/supervisor/qspi_flash.c +++ b/ports/nrf/supervisor/qspi_flash.c @@ -38,7 +38,44 @@ #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 +void qspi_disable(void) +{ + // If VBUS is detected, no need to disable QSPI + 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; + } +} + +void qspi_enable(void) +{ + if (NRF_QSPI->ENABLE) { + return; + } + + nrf_qspi_enable(NRF_QSPI); + + nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY); + nrf_qspi_task_trigger(NRF_QSPI, NRF_QSPI_TASK_ACTIVATE); + + uint32_t remaining_attempts = 100; + do { + if (nrf_qspi_event_check(NRF_QSPI, NRF_QSPI_EVENT_READY)) { + break; + } + NRFX_DELAY_US(10); + } while (--remaining_attempts); +} + bool spi_flash_command(uint8_t command) { + qspi_enable(); nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode = command, .length = 1, @@ -51,6 +88,7 @@ bool spi_flash_command(uint8_t command) { } bool spi_flash_read_command(uint8_t command, uint8_t* response, uint32_t length) { + qspi_enable(); nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode = command, .length = length + 1, @@ -64,6 +102,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(); nrf_qspi_cinstr_conf_t cinstr_cfg = { .opcode = command, .length = length + 1, @@ -76,6 +115,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(); if (command != CMD_SECTOR_ERASE) { return false; } @@ -83,6 +123,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(); // 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) @@ -90,6 +131,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(); 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 |
