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

SPIS communication corrupted

Hey,

I'm using nRF as a SPI slave with a Raspberry Pi. I'm seeing that even at ~3MHz SPI frequency, my first byte transferred gets corrupted. I have a test setup where I'm sending 10 bytes (data sent is 1-10). I see that the first byte is incorrect a lot of times. These different errors were seen:

  1. 0x81(129) as the first byte, which is one bit-flip away from the expected 0x01.

  2. 0xFE(254) as the first byte, which is the Over-Read Character. Tested by changing ORC to 0xBB (187) and saw 187 then.

  3. A shift in the sequence being sent and an additional 0x81 in the beginning.

image description

I also saw error #1 at frequencies lower than 3MHz.

I saw the Errata 109 but it seems that that is pertinent only if I'm using _WFE or PPI. I'm not using either one though.

Does anyone have any idea why this could be happening?

Thanks,

Vandita

I'm using nRF52832 with SDK 13.0.0. Using SPIS3.

The nrf code looks like this:

static uint32_t spis_send(uint8_t* rx_data, uint8_t rx_len,
                                  uint8_t* tx_data, uint8_t tx_len)
{
  uint32_t err_code = ERR_UNKNOWN;
  spis_xfer_done = false;
  err_code = nrf_drv_spis_buffers_set(&spis, tx_data, tx_len, rx_data, rx_len);
  if (ERR_SUCCESS == err_code)
  {
    err_code = ERR_FAILURE;
    uint32_t count = 0;
    while (!spis_xfer_done && (count < COUNT_MAX))
    {
      __WFE();
      count++;
    }
    if (spis_xfer_done)
    {
      err_code = ERR_SUCCESS;
    }
  }
  return err_code;
}

static void spis_event_handler(nrf_drv_spis_event_t event)
{
  if (event.evt_type == NRF_DRV_SPIS_XFER_DONE)
  {
    spis_xfer_done = true;
  }
}

void SPIS_send_fake_data()
{
  uint8_t rx_data = 0;
  uint8_t data_out[10] = {0};
  for (int i = 0; i < 10; ++i)
  {
    data_out[i] = i + 1;
  }
  spis_send(&rx_data, 0, data_out, 10);
}

void SPIS_init()
{
  printf("SPIS_init\r\n");
  nrf_drv_spis_config_t spis_config = NRF_DRV_SPIS_DEFAULT_CONFIG;
  spis_config.csn_pin = SCS_PIN;
  spis_config.miso_pin = MISO_PIN;
  spis_config.mosi_pin = MOSI_PIN;
  spis_config.sck_pin = SCK_PIN;
  spis_config.mode = NRF_DRV_SPIS_MODE_0;
  spis_config.bit_order = NRF_DRV_SPIS_BIT_ORDER_MSB_FIRST;
  spis_config.miso_drive = NRF_GPIO_PIN_H0H1;
  nrf_drv_spis_init(&spis, &spis_config, spis_event_handler);
}

On the pi side, my code looks like this:

bool init()
{
  bool ret_code = false;
  if (bcm2835_init())
  {
    if (bcm2835_spi_begin())
    {
      bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);  // The default
      bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);               // The default
      // FIXME: any way to match 8 MHz?
      //      bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_64);  // ~
      //      6.25 MHz
      bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_128);  // ~ 3 MHz
      bcm2835_spi_chipSelect(BCM2835_SPI_CS0);                  // The default
      bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);  // the default
      spdlog::get(APP_NAME)->info("Successfully initialized SPI!");
      ret_code = true;
      sleep(1);
    }
    else
      spdlog::get(APP_NAME)->error(
          "Failed to start SPI operations (ensure running as root)!");
  }
  else
    spdlog::get(APP_NAME)->error("Failed to initialize SPI!");

  return ret_code;
}

bool end()
{
  bool ret_code = false;
  bcm2835_spi_end();
  if (bcm2835_close() == 0) ret_code = true;

  return ret_code;
}

void spi_read_fake_data()
{
  char ouput_data[10] = {0};
  uint8_t data[10];
  bool error_seen = true;
  bcm2835_spi_transfernb(ouput_data, (char *)data, 10);
  for (int i = 0; i < 10; ++i)
  {
    if (data[i] == 0xFF || data[i] == 0)
    {
      error_seen = false;
    }
  }
  if (error_seen)
  {
    for (int i = 0; i < 10; ++i)
    {
      printf("%d ", data[i]);
    }
    printf("\r\n");
  }
}

Update dec 12: screenshots SPI Mode 0 Error#1. Seeing 0x81. 0x559us between CS going low and first rising edge of clock.

image description

SPI Mode 0 Error#2. Seeing 0xBB - ORC and also seeing 0x00 sent instead of 0x06. I've seen this at different places.

image description

SPI Mode 1. Seeing 0x81. image description

  • Have you enabled constant latency mode? I'm not sure how fast the RPi will start sending data, but note that the nRF52832 will need ~3.125 µs to wakeup from sleep if CONSTLAT is not enabled. You write that you do not use WFE(), but you seem to be doing this in spis_send() which is called by SPIS_send_fake_data(). I suppose you are calling SPIS_send_fake_data() from main() or something? To be sure this is not the issue, you can also try enabling workaround for PAN-109 by setting #define SPIS_NRF52_ANOMALY_109_WORKAROUND_ENABLED 1 in sdk_config.h, even though you are not using PPI.

  • I tried enabling the workaround but still see the same errors. What does this workaround do? From the document it seemed like the workaround for SPIS was to ignore the first byte and therefore, send extra cycles from the master.

    I did try removing the _WFE and saw the same performance. Forgot to remove it from the snippet I was sharing. Does the constant latency mode matter even if we do not have any _WFE? I tried enabling it through NRF_POWER->TASKS_CONSTLAT = 1; but still see the same errors.

    The first error seems to stem from the fact that the spis peripheral is not ready in time to drop the miso line down. The first byte is flipped and I see from logic analyzer outputs that as compared to a good transfer, the clock from Pi in the error state starts 0.2us earlier. That's why we see 0x81 instead of 0x01. But it doesn't explain any other errors.

  • I tried changing to Mode1 on both sides and it had similar errors. Still seeing 0x81 (see screenshot in the updated question). Seems like nrf52 wants to send 0x81. Also adding screenshots for Mode 0.

    Found another error where 0x00 is sent instead of the actual data byte.

    1 0 3 4 5 6 7 8 9 10
    1 2 3 4 0 6 7 8 9 10
    1 2 3 4 5 6 7 8 9 0
    1 2 3 4 5 6 0 8 9 10
    1 2 3 4 5 6 0 8 9 10
    1 2 3 4 5 6 0 8 9 10
    1 2 3 4 0 6 7 8 9 10
    1 0 3 4 5 6 7 8 9 10
    187 2 3 4 5 6 7 8 9 0
    187 2 3 4 5 6 7 8 9 0
    
  • Could you upload a minimal example showing this issue, for us to debug?

Related