This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF52840 Zephyr dual QSPI MX25R64 flash example

I am trying to modify the nRF52840dk_nrf52840 spi_flash sample, ncs/zephyr/samples/drivers/spi_flash, to use dual QSPI. 

Following is my device tree configuration:

&spi1 {
	compatible = "nordic,nrf-spi";
	status = "okay";
	sck-pin = <31>;
	mosi-pin = <30>;
	miso-pin = <45>;
};

&qspi {
	status = "okay";
	sck-pin = <31>;
	io-pins = <30 45>;
	csn-pins = <29>;
	mx25r64: mx25r6435f@0 {
		compatible = "nordic,qspi-nor";
		reg = <0>;
		quad-enable-requirements = "NONE";
		/* MX24R64 supports only pp and pp4io */
		writeoc = "pp";
		/* MX24R64 supports all readoc options */
		readoc = "fastread";
		sck-frequency = <8000000>;
		label = "MX25R64";
		jedec-id = [c2 28 17];
		sfdp-bfp = [
			e5 20 f1 ff  ff ff ff 03  44 eb 08 6b  08 3b 04 bb
			ee ff ff ff  ff ff 00 ff  ff ff 00 ff  0c 20 0f 52
			10 d8 00 ff  23 72 f5 00  82 ed 04 cc  44 83 68 44
			30 b0 30 b0  f7 c4 d5 5c  00 be 29 ff  f0 d0 ff ff
		];
		size = <67108864>;
		has-dpd;
		t-enter-dpd = <10000>;
		t-exit-dpd = <35000>;
	};
};

I am using the main.c from the ncs/zephyr/samples/drivers/spi_flash example code.

JEDEC QSPI-NOR SPI flash testing
==========================
SPI flash driver MX25R64 was not found!

If I debug it and step into "device_get_binding()" and go down to '*z_impl_device_get_binding()" it will find the device with the following details.

dev->name = "MX25R64"
dev->config = 0x15884 <flash_id>
dev->api = 0x158d4 <qspi_nor_api>
dev->data = 0x200000e4 <qspi_nor_memory_data>

However, "sys_bitfield_test_bit()", in "z_device_ready()", indicates that the device failed initialization.

I am running this code on a custom board that is known good. I have existing code using the nRF_SDK v15.3.0 that successfully uses the MX25R64 with SPI.

What am I missing to get the MX25R64 to work with dual QSPI in Zephyr?

  • Hello,

    have you tried debugging the driver initialization? Have you checked qspi_nor_init() and qspi_nor_configure() for any errors?

  • I just debugged the driver initialization and I get a "NRFX_ERROR_TIMEOUT" in qspi_ready_wait() 

    From:    qspi_nor_init() -> qspi_nor_configure() -> qspi_nrfx_configure() -> nrfx_qspi_init()

    Following are the values of the nrfx qspi variables before entering this function:

    p_config->xip_offset = 0
    
    p_config->pins.sck_pin = 31
    p_config->pins.csn_pin = 29
    p_config->pins.io0_pin = 30
    p_config->pins.io1_pin = 45
    p_config->pins.io2_pin = 255
    p_config->pins.io3_pin = 255
    
    p_config->prot_if.readoc  = NRF_QSPI_READOC_FASTREAD
    p_config->prot_if.writeof = NRP_QSPI_WRITEOC_PP
    p_config->prot_if.addrmode = NRF_QSPI_ADDRMODE_24BIT
    p_config->prot_if.dpmconfig = false
    
    p_config->phy_if.sck_delay = 0
    p_config->phy_if.dpmen = false
    p_config->phy_if.spi_mode = NRF_QSPI_MODE_0
    p_config->phy_if.sck_freq = NRF_QSPI_FREQ_DIV4
    
    p_config->irq_priority = 1
    
    handler = qspi_handler
    
    p_context = qspi_nor_memory_data

  • Using the nRF52840DK I was able to get dual-SPI to work using the following overlay.

    nrf52840dk_nrf52840.overlay

    However, I am still not able to get the dual-SPI to work on my custom board.

    The only difference I see is that the version of the MX25R64 on the nRF52840DK has the the function HOLD# as a dual function on SIO3 and the version of the MX25R64 that I am using has RESET# as the dual function on SIO3. 

    To address this I soldered a wire to always pull the RESET# high, but this did not work and I get the same error.


    I had been setting RESET# high in the following board.c file that is enabled before the kernel, like I have done successfully with pins used for I2C power and pull-up, but this did not fix the flash problem. 

    #include "board.h"
    
    #include <hal/nrf_gpio.h>
    #include <init.h>
    
    static int custom_board_nRF52840_init(struct device *dev) {
        ARG_UNUSED(dev);
    
        /// Enable the I2C power.
        nrf_gpio_cfg_output(BOARD_I2C_ENABLE_POWER_PIN_MAP);
    
        nrf_gpio_pin_set(BOARD_I2C_ENABLE_POWER_PIN_MAP);
    
        /// Enable the I2C pullup.
        nrf_gpio_cfg_output(BOARD_I2C_PULLUP_PIN_MAP);
    
        nrf_gpio_pin_set(BOARD_I2C_PULLUP_PIN_MAP);
    
        /// Turn off the active low pin reset for the mx25r64 NOR flash.
        nrf_gpio_cfg_output(BOARD_NOR_FLASH_RESET_PIN_MAP);
    
        nrf_gpio_pin_set(BOARD_NOR_FLASH_RESET_PIN_MAP);
    
        return 0;
    }
    
    SYS_INIT(custom_board_nRF52840_init, PRE_KERNEL_1,
             CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
     

    and using the following CMakeLists.txt file in my custom board folder.

    # SPDX-License-Identifier: Apache-2.0
    
    zephyr_library()
    
    zephyr_library_sources(board.c)
    
    zephyr_library_include_directories(${ZEPHYR_BASE}/drivers)
    

  •  does my RESET# pin need to be defined in the qspi portion of my device tree (*.dts), or is there something else I need to do for dual QSPI to work?

  • I will ask about this internally. I'm not sure if what you are trying to do is supposed to work.

Related