disable QSPI while system ON idle loop.
This commit is contained in:
parent
cd5c0e99f7
commit
2795c002ad
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
2
ports/nrf/supervisor/qspi_flash.h
Normal file
2
ports/nrf/supervisor/qspi_flash.h
Normal file
@ -0,0 +1,2 @@
|
||||
extern void qspi_flash_enter_sleep(void);
|
||||
extern void qspi_flash_exit_sleep(void);
|
Loading…
x
Reference in New Issue
Block a user