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?

  • Hi,

    Thank you for the trace. It looks like there is a difference between the mx25 that is on the nRF5340DK and the gd25q that you're using. As you state there are only a set of instructions (see table 118 in https://infocenter.nordicsemi.com/pdf/nRF5340_PS_v1.3.1.pdf) that wakes the gd25, but any instruction from the list wakes the mx25. The wakeup procedure for qspi_nor can be seen in github.com/.../nrf_qspi_nor.c

    Are you able to wake the external flash using one of the instructions that the gd25 datasheet states that will not be ignored?

    Kind regards,
    Andreas

  • Hi AHaug,

    I checked the mx25 data sheet , it can exit Deep Power-down mode if CS pulses. But I do not think all of the QSPI Flash has such a feature, and this should not be a standard.

    Are you able to wake the external flash using one of the instructions that the gd25 datasheet states that will not be ignored?

    I think it should be able to wake the external flash. but I can not confirm it with the NCS, because that's the problem this post describes

    I found the 05H cmd is sent by function nrfx_qspi_init.

    but I can not see any code related to 05H cmd inside the nrfx_qspi_init. 

    so where does the  05H cmd come from? how can I disable this 05H cmd and make nrfx_qspi_init  work correctly?

  • Hi

    Jason said:
    But I do not think all of the QSPI Flash has such a feature, and this should not be a standard.

    Yes, but the command to release DpD (instruction AB) is sent nonetheless0in https://github.com/nrfconnect/sdk-zephyr/blob/2e2523efe52a7ac89f0567b8798fd857b1e71ae3/drivers/flash/nrf_qspi_nor.c#L1339, so a generic solution should be implemented in the nrfx_qspi driver

    Jason said:

    I found the 05H cmd is sent by function nrfx_qspi_init.

    but I can not see any code related to 05H cmd inside the nrfx_qspi_init. 

    so where does the  05H cmd come from? how can I disable this 05H cmd and make nrfx_qspi_init  work correctly?

    I think that your device might be stuck in qspi_wait_while_writing https://github.com/nrfconnect/sdk-zephyr/blob/v3.4.99-ncs1/drivers/flash/nrf_qspi_nor.c#L535 since it keeps polling the status register and not releasing.

    Could you send me all of your overlays and dts files such as the zephyr.dts (generated dts located in build/zephyr folder)

    Heads up, I will be out of office for the next week and a half on vacation and will be back in office the 2nd of April. Unfortunately response time will be slow in this period

    Kind regards,
    Andreas

  • Yes, but the command to release DpD (instruction AB) is sent nonetheless0in https://github.com/nrfconnect/sdk-zephyr/blob/2e2523efe52a7ac89f0567b8798fd857b1e71ae3/drivers/flash/nrf_qspi_nor.c#L1339, so a generic solution should be implemented in the nrfx_qspi driver

    the DpD (instruction AB) will not be sent if nrfx_qspi_init returns an error.

    I think that your device might be stuck in qspi_wait_while_writing https://github.com/nrfconnect/sdk-zephyr/blob/v3.4.99-ncs1/drivers/flash/nrf_qspi_nor.c#L535 since it keeps polling the status register and not releasing.

    yes, this is the point, because the nrf5340 sends an RDSR(05H) in nrfx_qspi_init before the cmd release DpD (instruction AB) is sent. but for the gd25q256e , once the device has entered the Deep Power-Down Mode, all commands are ignored except the Release from Deep Power-Down.

    Could you send me all of your overlays and dts files such as the zephyr.dts (generated dts located in build/zephyr folder)

     

    4863.zephyr.dts

  • Let me chime into this thread. I was having the same issue, and a fix/hack was to pull down the MISO line (IO1) before nrfx_qspi_init. I think this would mimic data from the external flash, making the Nordic chip think there's connectivity. After that, I reconfigure it. I believe this is the fix detailed in https://github.com/zephyrproject-rtos/zephyr/pull/64782/files but for a higher version of NCS/Zephyr RTOS.

Reply Children
Related