NRF5340 SPIS is it possible to update tx data during a transceive operation based on received data?

I'm working with Zephyr using NCS 2.3.0.  The boards include nrf5340 and nrf9160.  

Project lead has specified that the nrt5340 shall operate as a SPI slave to the nrf9160.  The communication protocol calls for validating the received data on the fly as its received.  The received data starts with a length field.  The design specifies that after the indicated length of data is transceived, the spi master will clock out an additional byte and the slave should send a value  indicating whether the data received was found to be valid... essentially an ACK/NACK based on the received data.  The goal is to operate the SPI bus at up to 1 MHz.

For the UARTE interface I see there is an RXDY event after each byte is received, which allows simple byte-by-byte operation. I don't see anything similar in the SPIS peripheral.

Is this design feasible using the SPIS peripheral without an RXRDY event? 

Is it possible to return control to the caller of spi_tranceive after each byte without losing any data in the overall SPI transmission?  Given the 1 microsecond clock time, it seems like a very tight timing constraint to initiate another spi_transceive before the next byte starts clocking out.

  • Hello Anthony,

    Thank you for contacting DevZone at NordicSemi.
    I am not fully sure about your requirements, and whether it could be done or not, but let us start by looking at the documentation.

    Some SoC support legacy mode spi and some only use the Spi with EasyDma.
    As you are using nrf5340, we see that this SoC (App core) only supports SPI M/S with EasyDma (upto 5 instances).
    Next, yes, the UARTE reception generates RXDRDY (receiver ready) event for each byte received. But that is not the case for SPIS. However, SPIS uses RXD.PRT (receive buffer pointer) and generates ENDRX event when RX buffer is filled. We have RXD.MAXCNT register that specifies the maximum number of bytes the SPI slave can receive in one granted transaction.
    Maximum SPIS clock frequency can be 8MHz.

    I am not sure what suits you, but one thing can be that you configure receiver buffer of size 1, and then after reception of each byte, you will get the ENDRX event as you were looking to have something similar like the UARTE receiver ready event.
    Another way can be that, as the received data starts with length field (a number n) and then n-Bytes of data, and another byte; if we consider number n (like 64, or 128) to be 1-byte, then you are actually transmitting n+2 bytes of data. After you receive n+2 byte of data, you can analyze the last byte and then validate the transmission.

    In the Zephyr SPI Driver API, the spi_transceive function uses rx_bufs pointer that is of type spi_buf_set. You can set the count variable of this structure to 1 to say that you want 1 byte register buffer.

    Best regards,
    Naeem

  • It would be helpful to start, if you could provide a working example for the nrf5340 operating as a SPI Slave within zephyr on NCS 2.3.0.  The examples I have found are very old and don't use the pinctrl setup.  So far I have not even seen the build attempt to compile the nrfx_spis code.

  • Read the SPIS chapter in the PS that describes how the SPI slave peripherial works. It is impossible for the CPU to change bytes in a running SPIS transaction, you can only change the next one.

    Your protocol design won't work with an MCU as SPI slave. These need noteworthy processing time in order to decide if a packed was valid or not. 

    This SPI slave protocol would require an asic or FPGA in order to meet the <1µs timing.

  • Yes, but not quite as you may be thinking. Use a single SPI transaction thus:

    <CS low><Tx: Length byte><Tx: Length Data Bytes><Twiddle Thumbs with no clocks or data><Tx: Dummy Byte to read Ack/Nack><CS High>

    The Master actually uses two transactions, length bytes and a single byte, separated by a long enough interval to allow the Slave to calculate the Ack/Nak and all within a single CS such that the slave only sees a single SPI transaction with a pause in clocking, perfectly acceptable. The Slave can change any byte in the queue for response up until the receive clock edge changes.

  • The NRF SPIS peripherial does not allow changing bytes during a transaction (CS=low). Read the PS for details, but this is a basic requirement that allows the SPIS to run at a relatively high speed.

    I strongly recommend a protocol redesign with this hardware limitation in mind.

Related