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
  • some strange behaviour

    Would you care to be a little less vague?

    it does not work

    http://www.catb.org/esr/faqs/smart-questions.html#code

    What testing / debugging / investigation have you done to find the problem ?

    What have you found so far ?

    https://www.avrfreaks.net/comment/2418156#comment-2418156

    EDIT

    The #if 0 blocks should not be different from active ones

    Well, one key difference is that one uses 'buf' and the other 'buf+1' ...

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

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

  • With quite a long term testing, my current codes is proven to quite reliable/stable.

    Still massive transfer in single shot is not working, and it easily caused ENC28J60 chip to gone, and it makes hard to analyze the problem with logic analyzer.

    It seems to be happened whenever I tried to send/receive hundreds of bytes with nrfx_spim_xfer().

    Still, I have a interest in this issue, but have another higher priority problems to solve.

    I'll test with increasing the single transfer size, after I can make spare time.

Reply
  • With quite a long term testing, my current codes is proven to quite reliable/stable.

    Still massive transfer in single shot is not working, and it easily caused ENC28J60 chip to gone, and it makes hard to analyze the problem with logic analyzer.

    It seems to be happened whenever I tried to send/receive hundreds of bytes with nrfx_spim_xfer().

    Still, I have a interest in this issue, but have another higher priority problems to solve.

    I'll test with increasing the single transfer size, after I can make spare time.

Children
  • After I tried to change transfer size, found my mistake eventually.

    Because SPI transfer length is limited to uint8_t, every transfers should break into several ones less than 256.

    So, the following codes works fine. Thanks, Edvin.

        for (int i = 0; i < len; i += UINT8_MAX) {
            nrf_drv_spi_xfer_desc_t datadesc = NRF_DRV_SPI_XFER_RX(buf + i, len - i > UINT8_MAX ? UINT8_MAX : len - i);
            APP_ERROR_CHECK(nrf_drv_spi_xfer(&spi, &datadesc, 0));
        }
    ...
        for (int i = 0; i < len; i += UINT8_MAX) {
            nrf_drv_spi_xfer_desc_t datadesc = NRF_DRV_SPI_XFER_TX(buf + i, len - i > UINT8_MAX ? UINT8_MAX : len - i);
            APP_ERROR_CHECK(nrf_drv_spi_xfer(&spi, &datadesc, 0));
        }
    

Related