disable QSPI while system ON idle loop.

This commit is contained in:
jun2sak 2021-03-07 19:14:04 +09:00
parent cd5c0e99f7
commit 2795c002ad
3 changed files with 98 additions and 11 deletions

View File

@ -45,6 +45,7 @@
#include "supervisor/serial.h" // dbg_printf()
extern int dbg_check_RTCprescaler(void);
#endif
#include "supervisor/qspi_flash.h"
#include "nrf.h"
#include "nrf_power.h"
@ -170,6 +171,10 @@ nrf_sleep_source_t system_on_idle_until_alarm(int64_t timediff_ms, uint32_t pres
bool have_timeout = false;
uint64_t start_tick = 0, end_tick = 0;
#if defined(MICROPY_QSPI_CS)
qspi_flash_enter_sleep();
#endif
if (timediff_ms != -1) {
have_timeout = true;
#if 0
@ -254,6 +259,11 @@ nrf_sleep_source_t system_on_idle_until_alarm(int64_t timediff_ms, uint32_t pres
#ifdef NRF_DEBUG_PRINT
dbg_printf("%c\r\n", reason);
#endif
#if defined(MICROPY_QSPI_CS)
qspi_flash_exit_sleep();
#endif
return wakeup_cause;
}
@ -293,29 +303,18 @@ void common_hal_alarm_set_deep_sleep_alarms(size_t n_alarms, const mp_obj_t *ala
_setup_sleep_alarms(true, n_alarms, alarms);
}
#if defined(MICROPY_QSPI_CS)
extern void qspi_disable(void);
#endif
#define PRESCALER_VALUE_IN_DEEP_SLEEP (1024)
extern void _debug_uart_init(void);
extern void _debug_uart_uninit(void);
void NORETURN alarm_enter_deep_sleep(void) {
alarm_pin_pinalarm_prepare_for_deep_sleep();
alarm_time_timealarm_prepare_for_deep_sleep();
#if defined(MICROPY_QSPI_CS)
qspi_disable();
#endif
#ifdef NRF_DEBUG_PRINT
dbg_printf("\r\ndeep sleep...");
#endif
int64_t timediff_ms = alarm_time_timealarm_get_wakeup_timediff_ms();
tick_set_prescaler(PRESCALER_VALUE_IN_DEEP_SLEEP -1);
#ifdef NRF_DEBUG_PRINT
dbg_dump_RTCreg(); //XXX
dbg_check_RTCprescaler(); //XXX
#endif
nrf_sleep_source_t cause;

View File

@ -37,6 +37,9 @@
#include "supervisor/shared/external_flash/common_commands.h"
#include "supervisor/shared/external_flash/qspi_flash.h"
#ifdef NRF_DEBUG_PRINT
#include "supervisor/serial.h" // dbg_printf()
#endif
// When USB is disconnected, disable QSPI in sleep mode to save energy
void qspi_disable(void)
@ -190,7 +193,11 @@ void spi_flash_init(void) {
.readoc = NRF_QSPI_READOC_FASTREAD,
.writeoc = NRF_QSPI_WRITEOC_PP,
.addrmode = NRF_QSPI_ADDRMODE_24BIT,
#ifdef QSPI_FLASH_POWERDOWN
.dpmconfig = true
#else
.dpmconfig = false
#endif
},
.phy_if = {
.sck_freq = NRF_QSPI_FREQ_32MDIV16, // Start at a slow 2MHz and speed up once we know what we're talking to.
@ -238,3 +245,82 @@ void spi_flash_init_device(const external_flash_device* device) {
NRF_QSPI->IFCONFIG1 &= ~QSPI_IFCONFIG1_SCKFREQ_Msk;
NRF_QSPI->IFCONFIG1 |= sckfreq << QSPI_IFCONFIG1_SCKFREQ_Pos;
}
#ifdef QSPI_FLASH_POWERDOWN
// Parameters for external QSPI Flash power-down
// for W25Q128FV,
// tDP (nCS high to Power-down mode) = 3us
// tRES (nCS high to Standby mode) = 3us
// sck_delay = max(tDP, tRES) / 62.5ns = 48 -> 50 (w/ margin)
#define DUR_DPM_ENTER 1 // tDP in (256*62.5ns) units
#define DUR_DPM_EXIT 1 // tRES in (256*62.5ns) units
#define SCK_DELAY 50 // max(tDP, tRES) in (62.5ns) units
// wait necessary just after DPM enter/exit (cut and try)
#define WAIT_AFTER_DPM_ENTER 10 // usec
#define WAIT_AFTER_DPM_EXIT 50 // usec
#endif
static int sck_delay_saved = 0;
#ifdef NRF_DEBUG_PRINT
extern void dbg_dumpQSPIreg(void);
#else
#define dbg_dumpQSPIreg(...)
#endif
void qspi_flash_enter_sleep(void) {
#ifdef QSPI_FLASH_POWERDOWN
uint32_t r;
NRF_QSPI->DPMDUR =
((DUR_DPM_ENTER & 0xFFFF) << 16) | (DUR_DPM_EXIT & 0xFFFF);
// set sck_delay tempolarily
r = NRF_QSPI->IFCONFIG1;
sck_delay_saved = (r & QSPI_IFCONFIG1_SCKDELAY_Msk)
>> QSPI_IFCONFIG1_SCKDELAY_Pos;
NRF_QSPI->IFCONFIG1
= (NRF_QSPI->IFCONFIG1 & ~QSPI_IFCONFIG1_SCKDELAY_Msk)
| (SCK_DELAY << QSPI_IFCONFIG1_SCKDELAY_Pos);
// enabling IFCONFIG0.DPMENABLE here won't work.
// -> do it in spi_flash_init()
//NRF_QSPI->IFCONFIG0 |= QSPI_IFCONFIG0_DPMENABLE_Msk;
//dbg_dumpQSPIreg();
// enter deep power-down mode (DPM)
NRF_QSPI->IFCONFIG1 |= QSPI_IFCONFIG1_DPMEN_Msk;
NRFX_DELAY_US(WAIT_AFTER_DPM_ENTER);
if (!(NRF_QSPI->STATUS & QSPI_STATUS_DPM_Msk)) {
#ifdef NRF_DEBUG_PRINT
dbg_printf("qspi flash: DPM failed\r\n");
#endif
}
#endif
qspi_disable();
//dbg_dumpQSPIreg();
}
void qspi_flash_exit_sleep(void) {
qspi_enable();
#ifdef QSPI_FLASH_POWERDOWN
if (NRF_QSPI->STATUS & QSPI_STATUS_DPM_Msk) {
// exit deep power-down mode
NRF_QSPI->IFCONFIG1 &= ~QSPI_IFCONFIG1_DPMEN_Msk;
NRFX_DELAY_US(WAIT_AFTER_DPM_EXIT);
if (NRF_QSPI->STATUS & QSPI_STATUS_DPM_Msk) {
#ifdef NRF_DEBUG_PRINT
dbg_printf("qspi flash: exiting DPM failed\r\n");
#endif
}
// restore sck_delay
if (sck_delay_saved == 0) {
sck_delay_saved = 10; // default
}
NRF_QSPI->IFCONFIG1
= (NRF_QSPI->IFCONFIG1 & ~QSPI_IFCONFIG1_SCKDELAY_Msk)
| (sck_delay_saved << QSPI_IFCONFIG1_SCKDELAY_Pos);
}
//dbg_dumpQSPIreg();
#endif
}

View File

@ -0,0 +1,2 @@
extern void qspi_flash_enter_sleep(void);
extern void qspi_flash_exit_sleep(void);