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

Reading JEDEC ID with SPI on nrf9160

Hello,

I have an external flash w25n01gv, I am using this simple spi loopback example to test the spi functionality of nrf9160. I want to read the jedec id of my device and my code is like:

/*
 * Copyright (c) 2012-2014 Wind River Systems, Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>

#include <sys/printk.h>

#include <drivers/spi.h>

//addition for combining blinky

static struct spi_config spi_cfg = {
  .operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB |
  SPI_MODE_CPOL | SPI_MODE_CPHA,
  .frequency = 4000000,
  .slave = 0,
};

struct device * spi_dev;

static void spi_init(void) {
    const char *
      const spiName = "SPI_3";
    spi_dev = device_get_binding(spiName);

    if (spi_dev == NULL) {
      printk("Could not get %s device\n", spiName);
      return;
    }
}

void spi_test_send(void) {
  int err;
  //static u8_t tx_buffer[1];
  //static u8_t rx_buffer[1];
  static u8_t tx_buffer[2] = {
	0X9F,
	0x00
  };
  static u8_t rx_buffer[3];

  const struct spi_buf tx_buf = {
	.buf = tx_buffer,
	.len = sizeof(tx_buffer)
  };
  const struct spi_buf_set tx = {
	.buffers = & tx_buf,
	.count = 1
  };

  struct spi_buf rx_buf = {
	.buf = rx_buffer,
	.len = sizeof(rx_buffer),
  };
  const struct spi_buf_set rx = {
	.buffers = & rx_buf,
	.count = 1
  };

  struct device * gpio_dev;
  struct spi_cs_control cs_control;

  gpio_dev = device_get_binding("GPIO_0");
  if (!gpio_dev) {
	printk("could not find GPIO device\n");
	return;
  }
  cs_control.delay = 0;
  cs_control.gpio_dev = gpio_dev;
  cs_control.gpio_pin = 13;
  spi_cfg.cs = & cs_control;

  err = spi_transceive(spi_dev, & spi_cfg, & tx, & rx);

  if (err) {
	printk("SPI error: %d\n", err);
  } else {
	/* Connect MISO to MOSI for loopback */

	for (int i = 0; i < 2; i++) {
	  printk("TX transmit: %x\n", tx_buffer[i]);
	}

	for (int i = 0; i < 3; i++) {
	  printk("RX recv: %x\n", rx_buffer[i]);
	}
  }
}

void main(void) {
  printk("SPIM Example\n");
  spi_init();
  printk("After init\n");
  while (1) {
	spi_test_send();
	k_sleep(K_MSEC(1000));
	printk(".");
  }
}

The dataset of my externaş flash says:

so I am expecting to get Ef,AA,2f however what I am receiving is 00 00 ef. I also connected the output pins to logic analyzer but the clk signal and miso also doesn't seems right. What am I doing wrong in the code can you provide me some feedback about it. In the original code before I just do simple modifications I was observing the loopback properly. I was receiving what I was sending so the code was working properly. 

To adjust the chip select I am only using this code:

struct device * gpio_dev;
struct spi_cs_control cs_control;

gpio_dev = device_get_binding("GPIO_0");
if (!gpio_dev) {
  printk("could not find GPIO device\n");
  return;
}
cs_control.delay = 0;
cs_control.gpio_dev = gpio_dev;
cs_control.gpio_pin = 13;
spi_cfg.cs = & cs_control;

does that code changes cs from 1 to 0 automatically? I am doing something wrong in that part?

My overlay file is :

&spi3 {
    compatible = "nordic,nrf-spim";
    status = "okay";
    sck-pin = <11>;
    mosi-pin = <10>;
    miso-pin = <12>;
};

My proj.config is:

# CONFIG_BOARD_ENABLE_CPUNET=n
CONFIG_SPI=y
CONFIG_MAIN_STACK_SIZE=4096
# CONFIG_SPI_0=y
# UART, SPIM, and I2C are shared peripherals on nrf9160
# therefore we choose SPI3
CONFIG_SPI_3=y
CONFIG_SPI_NRFX=y
CONFIG_DEPRECATED_ZEPHYR_INT_TYPES=y

#addition for combining blinky
CONFIG_GPIO=y

Thank you for the help.

Parents Reply Children
  • Check out this ticket, where a customer was able to read the JEDEC ID. The sample used is also attached in that ticket.

    Best regards,

    Simon

  • Hi Simon,

    I already found that and tried. The problem is that flash has an already existing driver I think thats the problem why it doesn't work for my case. What should I wrote these parts in the code:

    #if (CONFIG_SPI_FLASH_W25QXXDV - 0)
    /* NB: W25Q16DV is a JEDEC spi-nor device, but has a separate driver. */
    #define FLASH_DEVICE CONFIG_SPI_FLASH_W25QXXDV_DRV_NAME
    #define FLASH_NAME "W25QXXDV"
    

    the overlay that the sample used is:

    &spi3 {
            compatible = "nordic,nrf-spim";
            status = "okay";
            sck-pin = <10>;
            mosi-pin = <11>;
            miso-pin = <12>;
            cs-gpios = <&gpio0 13 0>;
    
            w25q32@0 {
                    compatible = "winbond,w25q32", "jedec,spi-nor";
                    label = "W25Q32";
                    reg = <0>;
                    jedec-id = [ef 40 16];
                    size = <0x4000000>;
                    spi-max-frequency = <1000000>;
            };
    };
    
    

    I tried to change the whole code acccording to my external flash which has very similar command set with spi_nor so I though that I can directly use it as my driver then I implemented the code in the following:

    main.c:

    /*
     * Copyright (c) 2016 Intel Corporation.
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr.h>
    #include <drivers/flash.h>
    #include <device.h>
    #include <devicetree.h>
    #include <stdio.h>
    #include <string.h>
    
    #if (CONFIG_SPI_FLASH_W25N01GV - 0)
    /* NB: W25Q16DV is a JEDEC spi-nor device, but has a separate driver. */
    #define FLASH_DEVICE CONFIG_SPI_FLASH_W25N01GV_DRV_NAME
    #define FLASH_NAME "W25N01GV"
    #elif (CONFIG_SPI_NOR - 0) ||				\
    	DT_NODE_HAS_STATUS(DT_INST(0, jedec_spi_nor), okay)
    #define FLASH_DEVICE DT_LABEL(DT_INST(0, jedec_spi_nor))
    #define FLASH_NAME "JEDEC SPI-NOR"
    #elif (CONFIG_NORDIC_QSPI_NOR - 0) || \
    	DT_NODE_HAS_STATUS(DT_INST(0, nordic_qspi_nor), okay)
    #define FLASH_DEVICE DT_LABEL(DT_INST(0, nordic_qspi_nor))
    #define FLASH_NAME "JEDEC QSPI-NOR"
    #else
    #error Unsupported flash driver
    #endif
    
    #if defined(CONFIG_BOARD_ADAFRUIT_FEATHER_STM32F405)
    #define FLASH_TEST_REGION_OFFSET 0xf000
    #else
    #define FLASH_TEST_REGION_OFFSET 0xff000
    #endif
    #define FLASH_SECTOR_SIZE        4096
    
    
    
    
    void main(void)
    {
    	const uint8_t expected[] = { 0x55, 0xaa, 0x66, 0x99 };
    	const size_t len = sizeof(expected);
    	uint8_t buf[sizeof(expected)];
    	const struct device *flash_dev;
    	int rc;
    
    	printf("\n" FLASH_NAME " SPI flash testing\n");
    	printf("==========================\n");
    
    	flash_dev = device_get_binding(FLASH_DEVICE);
    
    	if (!flash_dev) {
    		printf("SPI flash driver %s was not found!\n",
    		       FLASH_DEVICE);
    		return;
    	}
    
    	/* Write protection needs to be disabled before each write or
    	 * erase, since the flash component turns on write protection
    	 * automatically after completion of write and erase
    	 * operations.
    	 */
    	printf("\nTest 1: Flash erase\n");
    	flash_write_protection_set(flash_dev, false);
    
    	rc = flash_erase(flash_dev, FLASH_TEST_REGION_OFFSET,
    			 FLASH_SECTOR_SIZE);
    	if (rc != 0) {
    		printf("Flash erase failed! %d\n", rc);
    	} else {
    		printf("Flash erase succeeded!\n");
    	}
    
    	printf("\nTest 2: Flash write\n");
    	flash_write_protection_set(flash_dev, false);
    
    	printf("Attempting to write %u bytes\n", len);
    	rc = flash_write(flash_dev, FLASH_TEST_REGION_OFFSET, expected, len);
    	if (rc != 0) {
    		printf("Flash write failed! %d\n", rc);
    		return;
    	}
    
    	memset(buf, 0, len);
    	rc = flash_read(flash_dev, FLASH_TEST_REGION_OFFSET, buf, len);
    	if (rc != 0) {
    		printf("Flash read failed! %d\n", rc);
    		return;
    	}
    
    	if (memcmp(expected, buf, len) == 0) {
    		printf("Data read matches data written. Good!!\n");
    	} else {
    		const uint8_t *wp = expected;
    		const uint8_t *rp = buf;
    		const uint8_t *rpe = rp + len;
    
    		printf("Data read does not match data written!!\n");
    		while (rp < rpe) {
    			printf("%08x wrote %02x read %02x %s\n",
    			       (uint32_t)(FLASH_TEST_REGION_OFFSET + (rp - buf)),
    			       *wp, *rp, (*rp == *wp) ? "match" : "MISMATCH");
    			++rp;
    			++wp;
    		}
    	}
    }
    

    overlay:

    &spi3 {
    compatible = "nordic,nrf-spim";
    status = "okay";
    sck-pin = <10>;
    mosi-pin = <11>;
    miso-pin = <12>;
    cs-gpios = <&gpio0 13 0>;
    
    w25n01gv@0 {
    //compatible = "winbond,w25q32", "jedec,spi-nor";
    compatible = "jedec,spi-nor";
    label = "W25N01GV";
    reg = <0>;
    jedec-id = [ef AA 21];
    size = <0x4000000>;
    spi-max-frequency = <4000000>;
    };
    };
    
    

    proj.conf

    CONFIG_STDOUT_CONSOLE=y
    CONFIG_FLASH=y
    CONFIG_SPI=y
    CONFIG_SPI_NOR=y

    In the output it says that:

    Can you guide me please what I am missing?

    Thank you for the help so much

  • A huge part of the support team are currently on Christmas vacaction, and you may experience delayed answers. Most of the staff will be back by january 4th and you can expect an answer after then. My apologies for this.

    Best regards,

    Simon

  • Can you try to do some debugging (enable CONFIG_DEBUG_OPTIMIZATIONS) and check if the init function succeeds (spi_nor_init())? As mentioned in NCS Tutorial part-3 1.3. Pitfalls the call to device_get_binding() will fail (and "SPI flash driver %s was not found" is printed) if the init function fails.

    Try to check the function spi_nor_init()-->spi_nor_configure()-->spi_nor_read_jedec_id() and see if LOG_ERR("JEDEC ID read failed: %d", rc) is triggered.

    Best regards,

    Simon

  • Hi Simon,

    Thank you for your response. I could'nt figure out what you mean by "spi_nor_init()-->spi_nor_configure()-->spi_nor_read_jedec_id()" How should I check these ?I just opened the spi_nor.c and tried to do debugging in those fuction lines but what I realized is that in my main.c , the function doesn't even go inside the spi_nor.c, so in that case how can I do the debugging in spi_nor functions I could'nt understand it properly can you help me with that ?

    Best

Related