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

long SPI communication unreliable

Hi teams,

I have build custom board connected to ethernet via ENC28J60 ethernet controller.

It uses SPI communication with ENC28J60, but some strange behaviour during bulk TX/RX.

Please see the following codes.

#if 0
    nrf_drv_spi_xfer_desc_t datadesc = NRF_DRV_SPI_XFER_RX(buf, len);
    APP_ERROR_CHECK(nrf_drv_spi_xfer(&spi, &datadesc, 0));
#else
    for (int i = 0; i < len; i++) {
        nrf_drv_spi_xfer_desc_t datadesc = NRF_DRV_SPI_XFER_RX(buf + i, sizeof(uint8_t));
        APP_ERROR_CHECK(nrf_drv_spi_xfer(&spi, &datadesc, 0));
    }
#endif
...
...
#if 0
    nrf_drv_spi_xfer_desc_t datadesc = NRF_DRV_SPI_XFER_TX(buf, len);
    APP_ERROR_CHECK(nrf_drv_spi_xfer(&spi, &datadesc, 0));
#else
    for (int i = 0; i < len; i++) {
        nrf_drv_spi_xfer_desc_t datadesc = NRF_DRV_SPI_XFER_TX(buf + i, sizeof(uint8_t));
        APP_ERROR_CHECK(nrf_drv_spi_xfer(&spi, &datadesc, 0));
    }
#endif

These codes are extracted my data tx/rx functions.

The #if 0 blocks should not be different from active ones, but in real, it does not work.

Why this happens?

Parents Reply
  • The above codes are extracted from my actual driver code.

    The disabled block fails with various errors. Maybe incorrect data sent/received.

    In the other hands, the active block is working fine.

    This is why I am asking, and why the single bulk transfer is working differently with multiple single transfers.

    I cannot understand what you mean. Which one is sending/receiving (buf + 1) numbers of data?

    Give your great answer for me.

Children
  • The disabled block fails with various errors

    You need to quantify that!

    A key part of debugging is getting a proper handle of what is actually going wrong!

    Have you used a scope of analyser to see what's happening on the wire?

    the active block is working fine

    So why not just do that?

    The obvious difference at first sight is that one does it as a single transaction, but the other as individual bytes - so the timing is clearly going to be different. And, perhaps, the use of the Slave Select ... ?

    Which one is sending/receiving (buf + 1) numbers of data

    That's not what I said.

    But I misread the code anyhow: I thought it said '1' - not 'i' - so ignore that comment!

    Sorry.

    But maybe avoid the use of single-letter variable names.

  • First, I admit that I missed one thing to explain.

    This SPI connection is made with spi_config.ss_pin   = NRF_DRV_SPI_PIN_NOT_USED;.

    It is because transmitting single byte command and transmitting multple bytes immediately cannot be expressed with single nrf_drv_spi_xfer() call.

    So, I first lower SS pin as GPIO output, and after transfer, up it.

    With this condition, the two codes SHOULD BE EXACTLY THE SAME, AFAIK.

    The extra delay with for{} loop may caused difference, but normally it should not, if the nrf_drv_spi_xfer() is properly made.

    So, does it mean nrf_drv_spi_xfer() for multiple bytes has timing bug?

  • Hello,

    You say that the #if 0 block doesn't work. Does nrf_drv_spi_xfer() return something other than 0 (NRF_SUCCESS) when you use this block? Have you tried analyzing the SPI wires when using this block? What does it look like compared to the other block?

  • The extra delay with for{} loop may caused difference, but normally it should not

    Shouldn't it?

    If removing the extra delays makes it too fast - that would explain it ...

    Again:

    Have you used a scope or analyser to see what's happening on the wire?

    and

    Have you tried analyzing the SPI wires when using this block? What does it look like compared to the other block

    we don't have access to your hardware - so only you can do that!

  • It returns NRF_SUCCESS. Otherwise, the code would block because of APP_ERROR_CHECK().

    I checked SPI signals at the early stage of development for simple register access and found nothing strange. (My scope is not so fully capable for triggering/capturing this burst read/write, because this transfer will be started after several small register accesses. Anyway, I'll try to check whether some different pattern shows between good/bad cases.)

    And nRF52 DK and my custom board shows the same behavior, and changing SPI frequency to lower/lowest also shows no difference.

    Again, my functions send/receive hundreds of bytes on SPI line in single transfer.

    Isn't it suitable using single nrf_drv_spi_xfer() on this purpose?

    I haven't never suffered from this kind of problem in different platform.

Related