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
  • 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?

Children
  • 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.

  • choehyunho said:
    The disabled block fails with various errors. Maybe incorrect data sent/received.

     Ok. You need to check using a logic analyzer whether the data that is sent is the same that is on the gpios. Perhaps you can give an example of an error. What are you trying to send, and what is being received?

    What SDK version do you use? And what modules do you use? What functions are being called inside nrf_drv_spi_xfer()? 

    nrfx_spim_xfer() or nrfx_spi_xfer()?

    What does NRFX_CHECK(NRFX_SPIM_EXTENDED_ENABLED) return?

    I would continue to dig into this, but there are quite a few options. Why don't you tell us what the function calls that are being called inside nrf_drv_spi_xfer()? This depends on your sdk_config.h settings.

    Is this a large problem? Why not just use the implementation that works?

    I don't really have a lot to work with here.

  • First, I'll explain the problem situation.

    The ENC28J60 is the ethernet controller communicated with SPI, and I made driver for it.

    It works fine, but sometimes (very rare, once per a day) the communcation causes problem.

    I made a small extra code to compare SPI sent data to re-read data, and it does not match.

    That is why I try to make sure the SPI communication is working perfectly.

    Second, the actual work function is nrfx_spim_xfer() and NRFX_CHECK(NRFX_SPIM_EXTENED_ENABLED) is false.

    Since I am using Mesh SDK, this setting may be default. SDK version is 16.0.0.0 & Mesh SDK is 4.0.0.

    I tested with 52833 DK, and now I also have custom board based on it.

    Third, currently I am on longivity test with my new custom board.

    At first glance, the error rate seems to be greatly reduced, but not sure yet.

    Still the single burst transfer is not working, and when I checked with analyzer, I couldn't find difference between the good/bad codes. I'll investigate further later.

Related