Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

SPIM buffer lengths -- how to calculate and specify

I am trying to use SPIM2 on an NRF52840 based board. The SDK is 17.0.2.

For the life of me I cannot understand how to 'consistently' determine the values to be specified as 'tx_length' and 'rx_length' to be provided to the calls to the transfer function.
My SPI slave device is the MCP2515 which uses a protocol where the first byte of the transfer represents the command and subsequent bytes are either input or output data bytes.

Take for example a command to read 10 bytes. The command itself takes 1 byte, and therefore the total transaction spans 11 bytes (1 + 10).

So far, the only way I have been able to get this transaction to happen correctly is if I set the tx_length and rx_length input parameters BOTH to 11.
Intuitively that makes sense since the channel has to transfer 11 bytes in each direction.

BUT --- WHY BOTHER ASKING THE USERS TO SPECIFY BOTH PARAMETERS.

Why not use a single parameter and use it -- or conversely when (if at all in the case of SPI interactions) would the driver require and leverage different values for TX and RX length?

Parents
  • Hi,

    Although your SPI slave works this way, does not mean every SPI slave will work the same way. I'm quite confident that your code will work equally well if you set the tx_length to 1 and rx length to 11, as mentioned by , the SPI peripheral will clock out the ORC byte when the tx_length have been reached. The typical SPI protocol will output the RX data after receiving the command, but this is not always the case.

    SPI works as a shift register, bits are clocked in and out of the register on each clock cycle. The SPI protocol does not care how the data in the registers are used, but it will always clock in and out data at the same time (given that the MISO/MOSI pins are connected of course). In the typical case described above, you need to set the rx_length to the expected read length + the length of the command, as the SPI peripheral will start filling the RX buffer when the command is clocked out. However, some SPI slave may implement a protocol where you do not need to send a command byte with each read, the slave may be configured to only clock out a preconfigured value on each read. Or the SPI slave can for instance clock out data for the previous command on MISO line while receiving a new command on the MOSI line.

    As you can understand, it is much more flexible to allow the user to specify both tx_length and rx_length as separate parameters, as the lengths will not always be the same.

    Best regards,
    Jørgen

Reply
  • Hi,

    Although your SPI slave works this way, does not mean every SPI slave will work the same way. I'm quite confident that your code will work equally well if you set the tx_length to 1 and rx length to 11, as mentioned by , the SPI peripheral will clock out the ORC byte when the tx_length have been reached. The typical SPI protocol will output the RX data after receiving the command, but this is not always the case.

    SPI works as a shift register, bits are clocked in and out of the register on each clock cycle. The SPI protocol does not care how the data in the registers are used, but it will always clock in and out data at the same time (given that the MISO/MOSI pins are connected of course). In the typical case described above, you need to set the rx_length to the expected read length + the length of the command, as the SPI peripheral will start filling the RX buffer when the command is clocked out. However, some SPI slave may implement a protocol where you do not need to send a command byte with each read, the slave may be configured to only clock out a preconfigured value on each read. Or the SPI slave can for instance clock out data for the previous command on MISO line while receiving a new command on the MOSI line.

    As you can understand, it is much more flexible to allow the user to specify both tx_length and rx_length as separate parameters, as the lengths will not always be the same.

    Best regards,
    Jørgen

Children
  • Perhaps it will help if I paraphrase my original observations.

    It is not the SPIM hardware that is the issue but rather Nordic SDK's firmware design of the spin lock in the SPIM driver that manages the transfer.

    Going back to my original example of 1 command byte and 10 receive bytes.... I get receive buffer underrun UNLESS I set both the RXLENGTH and TXLENGTH to be (10+1).

    I was expecting that setting TXLENGTH to 1 and RXLENGTH to 10 'should work' (as suggested by both mrono and Jorgen) but it did not -- regardless of the ORC byte.

Related