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

SPI rx problem

Hi guys,

I'm having some trouble with an spi flash memory (AT45DB081D) I interfaced on my nrf51 DK.

I used the spi master code of nRF5 v.12 SDK as base. I'm using gcc on a linux environment.

I can send commands and receive the proper answer from the flash memory. The problem is that the answer on the rx packet always comes preceded by some extra bytes or 0xFF or 0x00. And for each command comes a different amount of bytes, also I can't assure that the memory is programmed correctly.

I've tried many different configurations (changing the mode 0,1,2,3, changing the frequency, doing the cs independently) but nothing helped.

#include "nrf_drv_spi.h"
#include "app_util_platform.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"
#include "boards.h"
#include "app_error.h"
#include <string.h>
#define NRF_LOG_MODULE_NAME "APP"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_drv_gpiote.h"

#define SPI_INSTANCE  0 /**< SPI instance index. */
static const nrf_drv_spi_t spi = NRF_DRV_SPI_INSTANCE(SPI_INSTANCE);  /**< SPI instance. */
static volatile bool spi_xfer_done;  /**< Flag used to indicate that SPI instance completed the transfer. */

#define TEST_STRING "Nordic"
static uint8_t       m_tx_buf[15];           /**< TX buffer. */
static uint8_t       m_rx_buf[15];    /**< RX buffer. */
static const uint8_t m_length = sizeof(m_rx_buf);        /**< Transfer length. */

bool spimem_read_device_id(void);

/**
 * @brief SPI user event handler.
 * @param event
 */
void spi_event_handler(nrf_drv_spi_evt_t const * p_event)
{
	spi_xfer_done = true;
	NRF_LOG_INFO("Transfer completed.\r\n");
}



void spimem_send_command(uint8_t sizetx, uint8_t sizerx)
{
  memset(m_rx_buf, 0xAA, m_length);
  spi_xfer_done = false;

  APP_ERROR_CHECK(nrf_drv_spi_transfer(&spi, m_tx_buf, sizetx, m_rx_buf, sizerx));

  while (!spi_xfer_done)
  {
	  __WFE();
  }

  if(sizerx!=0)
  {
	NRF_LOG_INFO("Received[0]: %x %x %x %x %x %x \n\r",m_rx_buf[0],m_rx_buf[1],m_rx_buf[2],m_rx_buf[3],m_rx_buf[4],m_rx_buf[5]);
	NRF_LOG_INFO("Received[1]: %x %x %x %x %x %x \n\r",m_rx_buf[6],m_rx_buf[7],m_rx_buf[8],m_rx_buf[9],m_rx_buf[10],m_rx_buf[11]);
  }

  NRF_LOG_FLUSH();
}


bool spimem_read_device_id(void)
{
  m_tx_buf[0]=0x9F;
  spimem_send_command(1,4);

  return true;
}


bool spimem_read_status_register(void)
{
  m_tx_buf[0]=0xD7;
  spimem_send_command(1,4);
  return true;
}


bool spimem_ready(void)
{
  NRF_LOG_INFO("Reading status:");
  spimem_read_status_register();
  if(m_rx_buf[1]&0x80)
  {
	NRF_LOG_INFO("Mem ready\r\n");
	return true;
  }
  else
	NRF_LOG_INFO("Mem busy\r\n");

  return false;
}

void spimem_read_flash(uint8_t *strtoread, uint8_t addr, uint8_t strsize)
{
  m_tx_buf[0]=0xD2; //Main memory read page
  m_tx_buf[1]=0x00;
  m_tx_buf[2]=0x00;
  m_tx_buf[3]=0x00; 
  m_tx_buf[4]=0x00; 
  m_tx_buf[5]=0x00; 
  m_tx_buf[6]=0x00; 
  m_tx_buf[7]=0x00; 

  spimem_send_command(8,10);
  while(spimem_ready()==false);


}

void spimem_write_buffer(void)
{
  m_tx_buf[0]=0x84;
  m_tx_buf[1]=0x00; //dummy byte
  m_tx_buf[2]=0x00; //dummy byte
  m_tx_buf[3]=0x00; //addr byte on buffer

  m_tx_buf[4]=0xAC;
  m_tx_buf[5]=0x0C;
  m_tx_buf[6]=0x03;
  m_tx_buf[7]=0x04;
  m_tx_buf[8]=0x05;

  spimem_send_command(9,0);
  while(spimem_ready()==false);
}


void spimem_read_buffer(void)
{
  m_tx_buf[0]=0xD4;
  m_tx_buf[1]=0x00;
  m_tx_buf[2]=0x00;
  m_tx_buf[3]=0x00;
  m_tx_buf[4]=0x00;

  spimem_send_command(5,10);
}


int main(void)
{
	LEDS_CONFIGURE(BSP_LED_0_MASK);
	LEDS_OFF(BSP_LED_0_MASK);

	APP_ERROR_CHECK(NRF_LOG_INIT(NULL));

	NRF_LOG_INFO("SPI example\r\n");

	nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
	spi_config.ss_pin   = SPI_SS_PIN;
	spi_config.miso_pin = SPI_MISO_PIN;
	spi_config.mosi_pin = SPI_MOSI_PIN;
	spi_config.sck_pin  = SPI_SCK_PIN;
	spi_config.frequency= NRF_DRV_SPI_FREQ_125K;
	spi_config.mode= NRF_DRV_SPI_MODE_0;

	APP_ERROR_CHECK(nrf_drv_spi_init(&spi, &spi_config, spi_event_handler));

	NRF_LOG_INFO("\n\r\n\rRead Device ID\r\n");
	spimem_read_device_id();

	NRF_LOG_INFO("\n\r\n\rWrite Buffer\r\n");
	spimem_write_buffer();

	NRF_LOG_INFO("\n\r\n\rRead Buffer\r\n");
	spimem_read_buffer();

}

The return for that code is:

APP:INFO:SPI example
APP:INFO:

Read Device ID
APP:INFO:Transfer completed.
APP:INFO:Received[0]: ff 1f 25 0 aa aa 
APP:INFO:Received[1]: aa aa aa aa aa aa 
APP:INFO:

Write Buffer
APP:INFO:Transfer completed.
APP:INFO:Reading status:APP:INFO:Transfer completed.
APP:INFO:Received[0]: 0 a4 88 a4 aa aa 
APP:INFO:Received[1]: aa aa aa aa aa aa 
APP:INFO:Mem ready
APP:INFO:

Read Buffer
APP:INFO:Transfer completed.
APP:INFO:Received[0]: ff ff ff ff ff ac 
APP:INFO:Received[1]: c 3 4 5 aa aa 

On the command Device ID the first received byte (0xff) wasn't suppose to be there.

On the command Write Buffer, the verification of the buffer status also return a first strange byte (0x00), the following is all right.

On the command Read Buffer the first 5 bytes (0xff) weren't suppose to be there.

If anyone could help here I'd appreciate. Thank you all.

  • That's how SPI works, it's a synchronous read-write protocol, one byte goes out and another byte comes in at the same time. So of course you are going to get extra bytes on the start of the received data because something has to come in whilst the command is going out and only at the next clock can the chip respond with the answer, once it's seen the command.

    Did you notice that the number of dummy bytes you get at the start of the received message is the same as the number of bytes on the command you clocked out? That should have given you a clue what is going on.

    I suggest you find a description of the SPI protocol online and read it to understand what it's doing.

  • Hi RK, thank you very much for answering. I still think that there's something strange about it because I had implemented the same memory on another platform (ARM cortex-M3) and I didn't receive those dummy packages on my rx buffer. Besides I've checked on the forum here for other users examples and from the ones who printed the received buffer I couldn't find the dummy bytes. It seems that the rx buffer is also reading while the bytes are being send.

    Thank you for your help.

  • That's the whole point, the RX buffer IS receiving whilst the bytes are being sent. So you get dummy bytes in the buffer. SPI is a bi-directional protocol, one byte in for every byte out.

    You haven't checked well enough on the forum, this has been discussed a number of times.

  • It seems that sdk11 and sdk12 runs in a little bit different way. Getting flash id in sdk11

    
    static uint8_t flash_get_id(uint8_t *manufacturer_id, uint16_t *device_id)
    {
      uint8_t tx_buf[5], rx_buf[5];
      tx_buf[0] = W25Q_JEDEC_ID;
      ACCESS_FLASH_DATA(tx_buf, rx_buf, 5); 
      app_trace_log("[FLASH]%x %x %x %x %x\r\n", rx_buf[0], rx_buf[1], rx_buf[2],rx_buf[3], rx_buf[4]);
      *manufacturer_id = rx_buf[1];
      *device_id = ((uint16_t)rx_buf[2] <

    The output of rx_buf is "[FLASH]ff ef 40 14 0"

    But in SDK12

    
    static uint8_t flash_get_id(uint8_t *manufacturer_id, uint16_t *device_id)
    {
      uint8_t tx_buf[5], rx_buf[5];
      tx_buf[0] = W25Q_JEDEC_ID;
      ACCESS_FLASH_DATA(tx_buf, rx_buf, 5); 
      *manufacturer_id = rx_buf[2];
      *device_id = ((uint16_t)rx_buf[3] <

    The output of rx_buf is "INFO:[FLASH]ff ff ef 40 14"

Related