nRF5340 and W25Q512NW Nor Flash R/W problem?

Hello,

I am using W25Q512NW (https://www.winbond.com/resource-files/W25Q512NW%20RevB%2007192021.pdf) in my custom board. I want to store the sensor data in this flash.

My custom board use the nRF5340 MCU and the version of the nrf connect sdk is V2.5.2.

the problem i am facing that i am not able to read the data from the flash.

 

*** Booting nRF Connect SDK v2.5.2 ***
[00:00:00.252,868] <inf> main: iMedrix External flash Application Started.

Device name: w25q512nw@0
Data written. Good!!
23 22 33 44 55 66 77 88 
Data read. Good!!
FF FF FF FF FF FF FF FF 
Data not matched..!!
JEDEC ID : EF  60  20 

In above log, i am writing 8 bytes and also read those 8 bytes. but when i read data from the flash i am getting only FF. 
And when i read the JEDEC id of the flash, i am getting right JEDEC id.

Here is the prj.conf file.

# Logger module
CONFIG_USE_SEGGER_RTT=y
CONFIG_RTT_CONSOLE=y
CONFIG_LOG_BACKEND_RTT=y
CONFIG_LOG=y
CONFIG_LOG_MODE_DEFERRED=y
CONFIG_LOG_SPEED=y
CONFIG_UART_CONSOLE=n

CONFIG_DEBUG=y


# spi Configuration
CONFIG_SPI=y

#External flash configuration
CONFIG_FLASH=y
CONFIG_FLASH_JESD216_API=y
CONFIG_FLASH_PAGE_LAYOUT=y


CONFIG_NEWLIB_LIBC=y

Here is the .overlay file below.

 

&qspi {
	status = "okay";
	pinctrl-0 = <&qspi_default>;
	pinctrl-1 = <&qspi_sleep>;
	pinctrl-names = "default", "sleep";
	w25q512: w25q512nw@0 {
		compatible = "nordic,qspi-nor";
		reg = <0>;
		/* MX25R64 supports only pp and pp4io */
		writeoc = "pp4io";
		// writeoc = "pp4o";
		/* MX25R64 supports all readoc options */
		readoc = "read4io";
		sck-frequency = <8000000>;
		// jedec-id = [c2 28 17];
		jedec-id = [EF 60 20];
		sfdp-bfp = [
  			e5 20 fb ff  ff ff ff 1f  44 eb 08 6b  08 3b 42 bb
  			fe ff ff ff  ff ff 00 00  ff ff 40 eb  0c 20 0f 52
  			10 d8 00 00  33 02 a6 00  81 e7 14 d9  e9 63 76 33
  			7a 75 7a 75  f7 bd d5 5c  19 f7 5d ff  e9 70 f9 a5
  		];
		size = <536870912>;
		// address-size-32;
		has-dpd;
		// t-enter-dpd = <10000>;
		// t-exit-dpd = <35000>;
		t-enter-dpd = <3000>;
		t-exit-dpd = <30000>;
	};
};

Please give me your suggestion in this.  

Let me know if any modification is required.

Thank you in advance.

Gautam.

Parents
  • Shouldn't be any issues as far as I'm aware in the driver setting write protection in the QSPI driver. Are you able to find what in your project is setting this bit on your end somehow? Or see where-ish this protection bit is set from.

    Best regards,

    Simon

  • Hi Simonr,

    Sorry for the late replay,

    Initially, the memory of my external flash (W25Q512NWEIQ) is write-protected because the BP3 and BP2 bits in the status register are 1, but they should be 0.

    I included the has-lock property in the device tree as shown in below, but I'm still unable to write to the flash memory.

    &qspi {
    	status = "okay";
    	pinctrl-0 = <&qspi_default>;
    	pinctrl-1 = <&qspi_sleep>;
    	pinctrl-names = "default", "sleep";
    	w25q512: w25q512@0 {
    		compatible = "nordic,qspi-nor";
    		reg = <0>;
    		sck-frequency = <DT_FREQ_M(8)>;
    		jedec-id = [ef 60 20];
    		address-size-32;
    		enter-4byte-addr = <0x01>;
    		writeoc = "pp4o";
    		readoc = "read4io";
    		quad-enable-requirements = "S2B1v4";
    		size = <536870912>;
    		status = "okay";
    		
    		has-lock = <0xb0>;
    	};
    };

    I tried manually writing 0 to status register 1 using qspi, but I couldn’t write to it because the status register is write-protected (the SRP bit in SR_1 is 1). To disable write protection for the status register, we need to pull the /WP pin high or drive it high before writing to status register 1.

    When I used the SPI protocol for the flash and added the has-lock property to the device tree, I was able to write data to the external flash memory. This is because the spi_nor driver includes logic to write 0 to status register 1 when the has-lock property is added. After that, I flashed the code using QSPI, and it worked fine as well.

    	/* Check for block protect bits that need to be cleared.  This
    	 * information cannot be determined from SFDP content, so the
    	 * devicetree node property must be set correctly for any device
    	 * that powers up with block protect enabled.
    	 */
    	if (cfg->has_lock != 0) {
    		acquire_device(dev);
    
    		rc = spi_nor_rdsr(dev);
    
    		/* Only clear if RDSR worked and something's set. */
    		if (rc > 0) {
    			rc = spi_nor_wrsr(dev, rc & ~cfg->has_lock);
    		}
    
    		if (rc != 0) {
    			LOG_ERR("BP clear failed: %d\n", rc);
    			return -ENODEV;
    		}
    
    		release_device(dev);
    	}

    The above logic is already present in spi_nor.c (spi_nor_configure() function) file but not present in the nrf_qspi_nor.c.

    To avoid flashing the SPI code first and then the QSPI code each time, I've decided on a single approach:

    1. Initialize QSPI and read status register 1.

    2. Check if bits [7:2] of the status register are greater than 0(That means memory is write protected).

      • If the value is greater than 0:

        • Uninitialize QSPI.
        • Initialize SPI.
        • Write 0 to status register 1.
        • Uninitialize SPI.
        • Reset the entire device (MCU) using software.
      • If the value is 0:

        • Do nothing.

    But when i use the above approach the device stuck in spi_nor driver and not able to do anything.

    Here's few question:

     1. Is there any way to pull the /wp pin high in qspi mode?

    NOTE(From Winbond support) :- Write SR command only support 1-1-1, when flash receive write SR command, pin3 is /WP pin.

    2. How can i do the pin internally pull up using software (device tree).

    3. What is the ideal state of the QSPI bus?

    4. Can i use the spi and qspi on single bus simultaneously? If yes please guide me.

    5. How can i get the configured qspi pin number from the device tree to my custom code.?  

    Thank you

    Your response is valuable to us.

Reply
  • Hi Simonr,

    Sorry for the late replay,

    Initially, the memory of my external flash (W25Q512NWEIQ) is write-protected because the BP3 and BP2 bits in the status register are 1, but they should be 0.

    I included the has-lock property in the device tree as shown in below, but I'm still unable to write to the flash memory.

    &qspi {
    	status = "okay";
    	pinctrl-0 = <&qspi_default>;
    	pinctrl-1 = <&qspi_sleep>;
    	pinctrl-names = "default", "sleep";
    	w25q512: w25q512@0 {
    		compatible = "nordic,qspi-nor";
    		reg = <0>;
    		sck-frequency = <DT_FREQ_M(8)>;
    		jedec-id = [ef 60 20];
    		address-size-32;
    		enter-4byte-addr = <0x01>;
    		writeoc = "pp4o";
    		readoc = "read4io";
    		quad-enable-requirements = "S2B1v4";
    		size = <536870912>;
    		status = "okay";
    		
    		has-lock = <0xb0>;
    	};
    };

    I tried manually writing 0 to status register 1 using qspi, but I couldn’t write to it because the status register is write-protected (the SRP bit in SR_1 is 1). To disable write protection for the status register, we need to pull the /WP pin high or drive it high before writing to status register 1.

    When I used the SPI protocol for the flash and added the has-lock property to the device tree, I was able to write data to the external flash memory. This is because the spi_nor driver includes logic to write 0 to status register 1 when the has-lock property is added. After that, I flashed the code using QSPI, and it worked fine as well.

    	/* Check for block protect bits that need to be cleared.  This
    	 * information cannot be determined from SFDP content, so the
    	 * devicetree node property must be set correctly for any device
    	 * that powers up with block protect enabled.
    	 */
    	if (cfg->has_lock != 0) {
    		acquire_device(dev);
    
    		rc = spi_nor_rdsr(dev);
    
    		/* Only clear if RDSR worked and something's set. */
    		if (rc > 0) {
    			rc = spi_nor_wrsr(dev, rc & ~cfg->has_lock);
    		}
    
    		if (rc != 0) {
    			LOG_ERR("BP clear failed: %d\n", rc);
    			return -ENODEV;
    		}
    
    		release_device(dev);
    	}

    The above logic is already present in spi_nor.c (spi_nor_configure() function) file but not present in the nrf_qspi_nor.c.

    To avoid flashing the SPI code first and then the QSPI code each time, I've decided on a single approach:

    1. Initialize QSPI and read status register 1.

    2. Check if bits [7:2] of the status register are greater than 0(That means memory is write protected).

      • If the value is greater than 0:

        • Uninitialize QSPI.
        • Initialize SPI.
        • Write 0 to status register 1.
        • Uninitialize SPI.
        • Reset the entire device (MCU) using software.
      • If the value is 0:

        • Do nothing.

    But when i use the above approach the device stuck in spi_nor driver and not able to do anything.

    Here's few question:

     1. Is there any way to pull the /wp pin high in qspi mode?

    NOTE(From Winbond support) :- Write SR command only support 1-1-1, when flash receive write SR command, pin3 is /WP pin.

    2. How can i do the pin internally pull up using software (device tree).

    3. What is the ideal state of the QSPI bus?

    4. Can i use the spi and qspi on single bus simultaneously? If yes please guide me.

    5. How can i get the configured qspi pin number from the device tree to my custom code.?  

    Thank you

    Your response is valuable to us.

Children
No Data
Related