summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Epler <jeff@adafruit.com>2020-08-10 16:06:57 -0500
committerGitHub <noreply@github.com>2020-08-10 16:06:57 -0500
commit807f049dc3b2d41985534063e355c1ad0904fe3f (patch)
tree88db17b90d5ae5a6c5773e52dab0330f3087d18a
parent78f90db72f35ecab052c70411cb7d1d1a1980970 (diff)
parentaf1291ec28a8d2881e820fc1ce9b938ab5a6f097 (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.h7
-rw-r--r--ports/nrf/supervisor/port.c8
-rw-r--r--ports/nrf/supervisor/qspi_flash.c42
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