nRF5340 QSPI flash

Hi:

SW: NCS v2.5.0

HW: nRF5340 + flash gd25q256e 

To reduce the power consumption of the QSPI flash, we have two approaches.

1. cut off the QSPI flash's power when the product is in sleep mode (the power can be turned on/off by an LDO)

2. always keep the power of the QSPI flash, and put the flash into deep power down mode when the product is in sleep mode.

unfortunately, both of these two approaches have problems.

for approach 1, when turning on the power again, and initiating the QSPI and XIP again, the XIP doesn't work.

e.g 

 printk("#2Address of %x value %x\n", 0x10000008, *(uint32_t *)0x10000008);
 printk("#2Address of %x value %x\n", 0x10000040, *(uint32_t *)0x10000040);
 the values are wrong. 
for approach 2,
put the QSPI flash into deep power down mode by calling pm_device_action_run(flash_dev, PM_DEVICE_ACTION_SUSPEND);
this works, we can see the power consumption is reduced.
wake up the flash from deep power down mode by calling pm_device_action_run(flash_dev, PM_DEVICE_ACTION_RESUME);
but this function return -EIO, and it is caused by the nrfx_qspi_init return NRFX_ERROR_TIMEOUT.
if we don't put the flash into deep power-down mode, every thing is OK.

below is the QSPI configuration 

&qspi {
	status = "okay";
	pinctrl-0 = <&qspi_default>;
	pinctrl-1 = <&qspi_sleep>;
	pinctrl-names = "default", "sleep";
	gd25q256: gd25q256e@0 {
		compatible = "nordic,qspi-nor";
		reg = <0>;
		/* GD25Q256 supports only pp(cmd 02H) and pp4o(cmd 32H) */
		writeoc = "pp4o";
		/* GD25Q256 supports all readoc options */
		readoc = "read4io";
		sck-frequency = <8000000>;
		jedec-id = [c8 40 19];
		sfdp-bfp = [/*read the sfdp-bfp by jesd216 sample(zephyr\samples\drivers\jesd216)*/
			e5 20 f3 ff  ff ff ff 0f  44 eb 08 6b  08 3b 42 bb
			ee ff ff ff  ff ff 00 ff  ff ff 00 ff  0c 20 0f 52
			10 d8 00 ff  d6 39 a5 fe  83 1f 15 51  ec 62 16 33
			7a 75 7a 75  04 bd d5 5c  00 06 64 00  08 50 00 01
		];
		size = <268435456>;
		has-dpd;
		t-enter-dpd = <40000>;
		t-exit-dpd = <45000>;
		enter-4byte-addr = <0x01>;
		address-size-32;
	};
};

Do you have any ideas on this issue?

Thanks!

Parents
  • Hi,

    I recommend you have a look at this modified version of the code relocation sample you're using. In this sample XiP is disabled after use and enabled before use. The same API is called to enable and disable XIP.

    The sample loops with a 10 sec sleep. The test write/read/erase code runs from XIP. A thread runs XIP code continuously.

    xip_write_run_disable_feat_xip_thread.zip

    Kind regards,
    Andreas

  • Hi,

    Thanks for your sample code.

    I simplified this sample code as below 

    #include <zephyr/kernel.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/pm/device.h>
    #include <stdint.h>
    #include <zephyr/kernel.h>
    #include <soc.h>
    #include <zephyr/pm/device.h>
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <stdio.h>
    #include <string.h>
    #include <nrfx_qspi.h>
    #include <zephyr/drivers/flash/nrf_qspi_nor.h>
    #include <hal/nrf_gpio.h>
    #include <nrfx_gpiote.h>
    
    #define LDO_3V0_EN_PIN (32 + 12)
    
    #define TEST_DEEP_SLEEP_MODE 0
    int main(void)
    {
    	static const struct device *flash_dev;
    
    	printk("Hello World! %s\n", CONFIG_BOARD);
    	nrf_gpio_cfg_output(LDO_3V0_EN_PIN);
    	nrf_gpio_pin_set(LDO_3V0_EN_PIN); // turn on the flash's VDD
    	flash_dev = DEVICE_DT_GET(DT_ALIAS(spi_flash0));
    
    	nrf_qspi_nor_xip_enable(flash_dev, true);
    	/*read QSPI data by XIP, no problem, the value is correct*/
    	printk("#0Address of %x value %x\n", 0x10000008, *(uint32_t *)0x10000008);
    	printk("#1Address of %x value %x\n", 0x10000030, *(uint32_t *)0x10000030);
    
    	int cnt = 0;
    #if TEST_DEEP_SLEEP_MODE
    	while (1)
    	{
    		printk("cnt %d\n", cnt++);
    		nrf_qspi_nor_xip_enable(flash_dev, false);
    		/*put QSPI flash into deep-power-down mode, no problem*/
    		ret = pm_device_action_run(flash_dev, PM_DEVICE_ACTION_SUSPEND);
    		printf("PM_DEVICE_ACTION_SUSPEND ret = %d\n", ret);
    
    		k_msleep(2000);
    
    		/*wake up QSPI flash from deep-power-down mode, has problem,
    		pm_device_action_run return -EIO, and it is caused by the nrfx_qspi_init return NRFX_ERROR_TIMEOUT.*/
    		ret = pm_device_action_run(flash_dev, PM_DEVICE_ACTION_RESUME);
    		printf("PM_DEVICE_ACTION_RESUME ret = %d\n", ret);
    		nrf_qspi_nor_xip_enable(flash_dev, true);
    
    		printk("#0Address of %x value %x\n", 0x10000008, *(uint32_t *)0x10000008);
    		printk("#1Address of %x value %x\n", 0x10000030, *(uint32_t *)0x10000030);
    
    		k_msleep(2000);
    	}
    #else
    	while (1)
    	{
    		printk("cnt %d\n", cnt++);
    		nrf_qspi_nor_xip_enable(flash_dev, false);
    		k_msleep(10);
    		nrf_gpio_pin_clear(LDO_3V0_EN_PIN); // turn off the flash's VDD
    
    		k_msleep(2000);
    
    		nrf_gpio_pin_set(LDO_3V0_EN_PIN); // turn on the flash's VDD
    		k_msleep(10);
    		nrf_qspi_nor_xip_enable(flash_dev, true);
    
    		/*read QSPI data by XIP, has problem, the value is wrong*/
    		printk("#0Address of %x value %x\n", 0x10000008, *(uint32_t *)0x10000008);
    		printk("#1Address of %x value %x\n", 0x10000030, *(uint32_t *)0x10000030);
    
    		k_msleep(2000);
    	}
    #endif
    	return 0;
    }

    this sample code works on the nrf5340-DK but still has the same problem on my custom board, please see the comments on the source code.

    the difference is that my custom board uses a different QSPI flash(gd25q256e).

    I have two questions.

    1. cut off the QSPI flash's power when the product is in sleep mode (the power can be turned on/off by an LDO)

    Why the XIP doesn't work correctly after turning on the flash's VDD again?

    2. always keep the power of the QSPI flash, and put the flash into deep power down mode when the product is in sleep mode.

    Why the the nrfx_qspi_init return NRFX_ERROR_TIMEOUT after the flash in deep-power-down mode?

  • Why the the nrfx_qspi_init return NRFX_ERROR_TIMEOUT after the flash in deep-power-down mode?

    update a finding.

    Some PCBAs can wake up from deep-power-down mode, some can not, and some have a chance to wake up from deep-power-down mode.

    Do you think this is a HW issue or a SW issue?

Reply Children
  • Hi,

    I've discussed this case with my colleagues and in general it is hard to pinpoint what could cause this

    Jason said:
    Why the XIP doesn't work correctly after turning on the flash's VDD again?

    It could be due to the flash device not properly setting itself up when you repower it. This is due to when you power of the external flash, it gets reset and you need to configure it once again to get it to the correct modus. To my understanding, through the driver at startup of the MCU

    1. cut off the QSPI flash's power when the product is in sleep mode (the power can be turned on/off by an LDO)

    AFAIK we don't have an LDO in our HW

    2. always keep the power of the QSPI flash, and put the flash into deep power down mode when the product is in sleep mode.

    The best solution would be alternative 2. The challenge here might be that the procedure differs from flash device to flash device so the procedure might differ from how it is done in the sample I provided. 

    Jason said:
    Why the the nrfx_qspi_init return NRFX_ERROR_TIMEOUT after the flash in deep-power-down mode?

    update a finding.

    Some PCBAs can wake up from deep-power-down mode, some can not, and some have a chance to wake up from deep-power-down mode.

    Do you think this is a HW issue or a SW issue?

    To be honest it could be either, but the best way to isolate it would be to reproduce it on other devices. Do you see the same thing if you port your sample to a 5340dk which uses the mx25 external flash? 

    How long does the device sleep for when you get that error? 

    Kind regards,
    Andreas

  • Hi,

    AFAIK we don't have an LDO in our HW

    I cut off the 'SB16' of 5340DK and connected/disconnected to the VDD manually to simulate the LDO of our customer board.

    The best solution would be alternative 2.

    we also prefer to approach 2 and make a decision to go for this. But we had to fix the deep-power-down mode issue.

    Do you see the same thing if you port your sample to a 5340dk which uses the mx25 external flash? 

    No, the sample code works on 5340dk with mx25, but I have only one 5240dk, I am not sure if it also works on other 5340dk, as I said, some of our customer board works and some do not work. 

    How long does the device sleep for when you get that error? 

    Two seconds in the sample code, and made no difference if increased the sleep time.

    let's go through the details of the source code. (we focus on the approach 2).

    		nrf_qspi_nor_xip_enable(flash_dev, false);
    		/*put QSPI flash into deep-power-down mode, no problem*/
    		ret = pm_device_action_run(flash_dev, PM_DEVICE_ACTION_SUSPEND);
    		printf("PM_DEVICE_ACTION_SUSPEND ret = %d\n", ret);
    
    		k_msleep(2000);
    
    		/*wake up QSPI flash from deep-power-down mode, has problem,
    		pm_device_action_run return -EIO, and it is caused by the nrfx_qspi_init return NRFX_ERROR_TIMEOUT.*/
    		ret = pm_device_action_run(flash_dev, PM_DEVICE_ACTION_RESUME);
    		printf("PM_DEVICE_ACTION_RESUME ret = %d\n", ret);
    		nrf_qspi_nor_xip_enable(flash_dev, true);

    'pm_device_action_run(flash_dev, PM_DEVICE_ACTION_RESUME)' return -EIO, and it is caused by the nrfx_qspi_init return NRFX_ERROR_TIMEOUT.

    let's have a look at the nrfx_qspi_init function.

    nrfx_err_t nrfx_qspi_init(nrfx_qspi_config_t const * p_config,
                              nrfx_qspi_handler_t        handler,
                              void *                     p_context)
    {
        NRFX_ASSERT(p_config);
        if (m_cb.state != NRFX_QSPI_STATE_UNINITIALIZED)
        {
            return NRFX_ERROR_INVALID_STATE;
        }
    
        m_cb.handler = handler;
        m_cb.p_context = p_context;
    
        /* QSPI interrupt is disabled because the device should be enabled in polling mode
          (wait for activate task event ready) */
        nrf_qspi_int_disable(NRF_QSPI, NRF_QSPI_INT_READY_MASK);
    
        if (p_config)
        {
            nrfx_err_t result = qspi_configure(p_config);
            if (result != NRFX_SUCCESS)
            {
                return result;
            }
        }
    
        m_cb.p_buffer_primary = NULL;
        m_cb.p_buffer_secondary = NULL;
        m_cb.state = NRFX_QSPI_STATE_IDLE;
    
        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);
    
        // Waiting for the peripheral to activate
    
        return qspi_ready_wait();
    }

    it is caused by the qspi_ready_wait() return NRFX_ERROR_TIMEOUT. 

    the qspi_ready_wait function is waiting for the  EVENTS_READY.

    According to the datasheet, this EVENTS_READY can be generated by setting TASKS_ACTIVATE.

    In nrfx_qspi_init(), this is done by nrf_qspi_task_trigger(NRF_QSPI, NRF_QSPI_TASK_ACTIVATE); 
    so the root cause is that the EVENTS_READY is not generated after  TASKS_ACTIVATE was activated.
    From what I understand, the peripheral initialization has nothing to do with an external device.
    e.g. I2C, or SPI, they can be initiated without an I2C or SPI device being connected. 

    one more detail. 

    Line 20 of nrfx_qspi_init :  result = qspi_configure(p_config);

    static nrfx_err_t qspi_configure(nrfx_qspi_config_t const * p_config)
    {
        if (!qspi_pins_configure(p_config))
        {
            return NRFX_ERROR_INVALID_PARAM;
        }
    
        m_cb.skip_gpio_cfg = p_config->skip_gpio_cfg;
    
        /* The code below accesses the IFTIMING and IFCONFIG1 registers what
         * may trigger anomaly 215 on nRF52840 or anomaly 43 on nRF5340. Use
         * the proper workaround then.
         */
        if (NRF52_ERRATA_215_ENABLE_WORKAROUND || NRF53_ERRATA_43_ENABLE_WORKAROUND)
        {
            nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
            nrf_qspi_task_trigger(NRF_QSPI, NRF_QSPI_TASK_ACTIVATE);
            if (qspi_ready_wait() == NRFX_ERROR_TIMEOUT)
            {
                return NRFX_ERROR_TIMEOUT;
            }
        }
    
        nrf_qspi_xip_offset_set(NRF_QSPI, p_config->xip_offset);
    
        nrf_qspi_ifconfig0_set(NRF_QSPI, &p_config->prot_if);
    #if NRFX_CHECK(USE_WORKAROUND_FOR_ANOMALY_121)
        uint32_t regval = nrf_qspi_ifconfig0_raw_get(NRF_QSPI);
        if (p_config->phy_if.sck_freq == NRF_QSPI_FREQ_DIV1)
        {
            regval |= ((1 << 16) | (1 << 17));
        }
        else
        {
            regval &= ~(1 << 17);
            regval |=  (1 << 16);
        }
        nrf_qspi_ifconfig0_raw_set(NRF_QSPI, regval);
        nrf_qspi_iftiming_set(NRF_QSPI, 6);
    #endif
        nrf_qspi_ifconfig1_set(NRF_QSPI, &p_config->phy_if);
    
        if (m_cb.handler)
        {
            NRFX_IRQ_PRIORITY_SET(QSPI_IRQn, p_config->irq_priority);
            NRFX_IRQ_ENABLE(QSPI_IRQn);
        }
    
        return NRFX_SUCCESS;
    }

    there are similar codes below, but the EVENTS_READY has no problem.

           nrf_qspi_event_clear(NRF_QSPI, NRF_QSPI_EVENT_READY);
            nrf_qspi_task_trigger(NRF_QSPI, NRF_QSPI_TASK_ACTIVATE);
            if (qspi_ready_wait() == NRFX_ERROR_TIMEOUT)
            {
                return NRFX_ERROR_TIMEOUT;
            }

    The difference in nrfx_qspi_init is that nrf_qspi_enable(NRF_QSPI) was called before
    nrf_qspi_task_trigger(NRF_QSPI, NRF_QSPI_TASK_ACTIVATE);
  • Hi,

    I've discussed this internally with my colleagues and this is what we suggest for now

    Since this is an issue causing some boards to fail and not all we need to some more information regarding the failure rate and more. 

    If you've not done so already could you make an estimate over how many boards this fails on and how many boards this error does not trigger on?

    I'm sure you've also considered this, but the most plausible thing causing the inconsistent fault is soldering issues. Have you verified if this is the cause? If not, we need to eliminate that reason before diving into software

    Could you perform measurements using a logic analyser or scope boards with and without the fault? 

    Let me know more about these items and I'll escalate it internally asap if the issue can't be pinned to hardware/faulty soldering

    Kind regards,
    Andreas

  • Hi,

    sorry for the delay

    because this product is just in the prototype phase, we just have 10 samples at this moment, two samples work, one works sometimes, and the others never work.

    Could you perform measurements using a logic analyser or scope boards with and without the fault? 

    As I said, the error already occurred before the nrf5340 sent the wakeup cmd to the QSPI flash. 

    According to the source code, line 50 'err = nrfx_qspi_init(&dev_config->nrfx_cfg,qspi_handler,dev_data);'

    return -EIO.

    static int qspi_nor_pm_action(const struct device *dev,
    			      enum pm_device_action action)
    {
    	struct qspi_nor_data *dev_data = dev->data;
    	const struct qspi_nor_config *dev_config = dev->config;
    	int ret;
    	nrfx_err_t err;
    
    	if (pm_device_is_busy(dev)) {
    		return -EBUSY;
    	}
    
    	switch (action) {
    	case PM_DEVICE_ACTION_SUSPEND:
    #ifndef CONFIG_PM_DEVICE_RUNTIME
    		/* If PM_DEVICE_RUNTIME, we don't uninit after RESUME */
    		ret = qspi_device_init(dev);
    		if (ret < 0) {
    			return ret;
    		}
    #endif
    
    		if (dev_data->xip_enabled) {
    			return -EBUSY;
    		}
    
    		if (nrfx_qspi_mem_busy_check() != NRFX_SUCCESS) {
    			return -EBUSY;
    		}
    
    		ret = enter_dpd(dev);
    		if (ret < 0) {
    			return ret;
    		}
    
    		nrfx_qspi_uninit();
    		ret = pinctrl_apply_state(dev_config->pcfg,
    					  PINCTRL_STATE_SLEEP);
    		if (ret < 0) {
    			return ret;
    		}
    		break;
    
    	case PM_DEVICE_ACTION_RESUME:
    		ret = pinctrl_apply_state(dev_config->pcfg,
    					  PINCTRL_STATE_DEFAULT);
    		if (ret < 0) {
    			return ret;
    		}
    		err = nrfx_qspi_init(&dev_config->nrfx_cfg,
    				     qspi_handler,
    				     dev_data);
    		if (err != NRFX_SUCCESS) {
    			return -EIO;
    		}
    
    		ret = exit_dpd(dev);
    		if (ret < 0) {
    			return ret;
    		}
    
    #ifndef CONFIG_PM_DEVICE_RUNTIME
    		/* If PM_DEVICE_RUNTIME, we're immediately going to use the device */
    		qspi_device_uninit(dev);
    #endif
    		break;
    
    	default:
    		return -ENOTSUP;
    	}
    
    	return 0;
    }

    Please have a look at my analysis below 

    it is caused by the qspi_ready_wait() return NRFX_ERROR_TIMEOUT. 

    the qspi_ready_wait function is waiting for the  EVENTS_READY.

    According to the datasheet, this EVENTS_READY can be generated by setting TASKS_ACTIVATE.

    In nrfx_qspi_init(), this is done by nrf_qspi_task_trigger(NRF_QSPI, NRF_QSPI_TASK_ACTIVATE); 
    so the root cause is that the EVENTS_READY is not generated after  TASKS_ACTIVATE was activated.

    I think we need to know what is the condition to generate the EVENTS_READY.

    I didn't find any available information about this in the datasheet 

  • Hi,

    Jason said:

    because this product is just in the prototype phase, we just have 10 samples at this moment, two samples work, one works sometimes, and the others never work.

    This further strengthens the theory that this is a hardware issue and not a software issue

    Jason said:
    As I said, the error already occurred before the nrf5340 sent the wakeup cmd to the QSPI flash. 

    This does not change the need for us to know more about the analysis requested as well as to look further into the hardware. 

    It could also be a design issue. Have you at any point had you designed reviewed? If not, I would recommend that you can create a new case and refer to the Devzone ID of this one (320224) as reference and request a design review from one of our hardware engineers so they can have a look as if there is any issues there.

    Kind regards,
    Andreas

Related