External flash to sleep

My board (nrf52840 sense) has flash memory P25Q16H. When I put everything off, the board consumes 25uA. To save the last bit of current I would like to put the flash memory to deep sleep.

	spi_flash_dev = DEVICE_DT_GET(DT_ALIAS(spi_flash0));	
	if (!device_is_ready(spi_flash_dev)) {
		LOG_ERR("%s: device not ready.\n", spi_flash_dev->name);
		return ENODEV;
	}
	
	if(pm_device_action_run(spi_flash_dev, PM_DEVICE_ACTION_SUSPEND)) { //only consumes more power, 3mA ?!
		LOG_ERR("could not suspend qspi flash device %s", spi_flash_dev->name);
	}

In the debugger, eventually this function in file nrf_qspi_nor.c is executed:

#ifdef CONFIG_PM_DEVICE
static int enter_dpd(const struct device *const dev)
{
	if (IS_ENABLED(DT_INST_PROP(0, has_dpd))) {
		struct qspi_cmd cmd = {
			.op_code = SPI_NOR_CMD_DPD,
		};
		uint32_t t_enter_dpd = DT_INST_PROP_OR(0, t_enter_dpd, 0);
		int rc;

		rc = qspi_send_cmd(dev, &cmd, false);
		if (rc < 0) {
			return rc;
		}

		if (t_enter_dpd) {
			uint32_t t_enter_dpd_us =
				DIV_ROUND_UP(t_enter_dpd, NSEC_PER_USEC);

			k_busy_wait(t_enter_dpd_us);
		}
	}

	return 0;
}
#endif /* CONFIG_PM_DEVICE */

SPI_NOR_CMD_DPD is indeed to 0xB9, which is consistent with the datasheet.

Problem: after executing this command, the power rises to 3.94mA. I have no idea what is causing this.

I'm running zephyr 3.5.99 ncs 2.6.1

Parents
  • Hi,

    I am very interested in a fix for this issue as well.

    My situation is the same except I am using a non-Sense Xiao BLE: approximately 20uA if I do not do anything to power off the external flash, and 2mA if I use pm_device_action_run.

    I did stumble upon a partial solution in this message: https://forum.seeedstudio.com/t/low-power-with-xiao-nrf52840-on-zephyr-rtos/270491/6. By adding flash.* from the zip-file linked to in the message  to my project and executing da_flash_init(); da_flash_command(0xB9); da_flash_uninit();, the power consumption gets down to 2.5uA, which is in line with my expectations.

    So it is possible to get there, and I can use this solution in the short run since I do not need the external flash for my current project, but I would very much prefer a solution that uses Zephyr's power management module.

    Best Regards,

    Peder

  • I read that too, I'll post his code for convenience.

    flash.c

    #include <nrfx_qspi.h>
    #include <zephyr/drivers/gpio.h>
    
    #define QSPI_SCK_PIN    21
    #define QSPI_CS_PIN     25
    #define QSPI_IO0_PIN   20
    #define QSPI_IO1_PIN    24
    #define QSPI_IO2_PIN    22
    #define QSPI_IO3_PIN    23
    
    int da_flash_init()
    {
        const struct device * dev = DEVICE_DT_GET(DT_NODELABEL(gpio0));
        if (!device_is_ready(dev))
        {
            return -ENODEV;
        }
        gpio_pin_configure(dev, QSPI_CS_PIN, GPIO_OUTPUT_HIGH);
    
        nrfx_qspi_config_t qspi_cfg =
        {
            .xip_offset = 0,
            .pins =
            {
                .sck_pin = QSPI_SCK_PIN,
                .csn_pin = QSPI_CS_PIN,
                .io0_pin = QSPI_IO0_PIN,
                .io1_pin = QSPI_IO1_PIN,
                .io2_pin = QSPI_IO2_PIN,
                .io3_pin = QSPI_IO3_PIN,
            },
            .prot_if = 
            {
                .readoc = NRF_QSPI_READOC_READ4O, // 0x6B read command
                .writeoc = NRF_QSPI_WRITEOC_PP4O, // 0x32 write command
                .addrmode = NRF_QSPI_ADDRMODE_24BIT,
                .dpmconfig = false
            },
            .phy_if =
            {
                .sck_delay = 10,
                .dpmen = false,
                .spi_mode = NRF_QSPI_MODE_0,
                .sck_freq = NRF_QSPI_FREQ_32MDIV16, // start with low 2 Mhz speed
            },
            .irq_priority = 7,
            .skip_gpio_cfg = true,
            .skip_psel_cfg = false
        };
    
        // No callback for blocking API
        nrfx_err_t err = nrfx_qspi_init(&qspi_cfg, NULL, NULL);
        if (err != NRFX_SUCCESS)
        {
            return -err;
        }
    
        return 0;
    } 
    
    void da_flash_uninit()
    {
        nrfx_qspi_uninit();
    }
    
    int da_flash_command(uint8_t command)
    {
        nrf_qspi_cinstr_conf_t cinstr_cfg = {.opcode = command,
                                             .length = NRF_QSPI_CINSTR_LEN_1B,
                                             .io2_level = true,
                                             .io3_level = true,
                                             .wipwait = false,
                                             .wren = false};
    
        nrfx_err_t err = nrfx_qspi_cinstr_xfer(&cinstr_cfg, NULL, NULL);
        if (err != NRFX_SUCCESS)
        {
            return -err;
        }
    
        return 0;
    }
    main.c

    da_flash_init();
    da_flash_command(0xB9);
    da_flash_uninit();
    

  • I looked at the devicetree for the XIAO BLE board and noticed that it disconnects all the QSPI pins, including CS, when the 'sleep' state is applied: https://github.com/zephyrproject-rtos/zephyr/blob/d32d4af935484b4de247a9f857dc90fb281f565e/boards/arm/xiao_ble/xiao_ble-pinctrl.dtsi#L99. This will leave the CS input on the P25Q16H floating, which I suspect may explain why it fails to enter/stay in power down mode.

    Please try to apply the DT overlay included the zip below to your build and see if it helps:

    3302.xiao_ble_sense.zip

  • Yes thank you so much, I can confirm this works.

  • Hi Vidar,

    I can confirm that this also works on a non-Sense board using ncs 2.7.0. Thank you so much for looking into this issue to both of you.

    Best regards,

    Peder

Reply Children
No Data
Related