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

SPI slave behavior

I had a couple of questions regarding the SPI slave peripheral on NRF52:

  1. What is the behavior of the peripheral if a transaction completes (NSS goes high) and another one starts before the receive buffer has been read? Is the buffer overwritten starting from the beginning again? On the transmit side I assume it's sending SPIS_DEFAULT_DEF?

  2. What happens in the case that the master is in the middle of a transaction and a call is made to nrf_drv_spis_buffers_set? What does clocked out data look like and what happens to the buffer on the receive side? Does transmit immediately go from SPIS_DEFAULT_DEF to the new valid transmit data?

  3. I'm a bit confused about when SPIS_DEFAULT_DEF and SPIS_DEFAULT_ORC are sent.

Parents
  • Hi,

    All these questions should be answered in the SPI slave operation section in the SPIS peripheral documentation. The peripheral implements a semaphore mechanism to enable safe shared access to the RAM buffers for both SPIS and CPU.

    1. As long as the semaphore is available the SPI slave can be granted multiple transactions one after the other. If the CPU is not able to reconfigure the TXD.PTR and RXD.PTR between granted transactions, the same TX data will be clocked out and the RX buffers will be overwritten. To prevent this from happening, the END_ACQUIRE shortcut can be used. With this shortcut enabled the semaphore will be handed over to the CPU automatically after the granted transaction has completed, giving the CPU the ability to update the TXPTR and RXPTR between every granted transaction.

    2. If the CPU tries to acquire the semaphore while it is assigned to the SPI slave, an immediate handover will not be granted. However, the semaphore will be handed over to the CPU as soon as the SPI slave has released the semaphore after the granted transaction is completed. If the END_ACQUIRE shortcut is enabled and the CPU has triggered the ACQUIRE task during a granted transaction, only one ACQUIRE request will be served following the END event.

      The function nrf_drv_spis_buffers_set can only be called when the semaphore is granted to the CPU. The SPIS driver will setup the the peripheral to make sure the semaphore is granted to the CPU after every transfer end. New buffers must be set by calling nrf_drv_spis_buffers_set after every finished transaction (in the callback handler on a NRF_DRV_SPIS_XFER_DONE event). Otherwise, the transaction is ignored, and the default character is clocked out.
    3. The SPI slave will try to acquire the semaphore when CSN goes low. If the SPI slave does not manage to acquire the semaphore at this point, the transaction will be ignored. This means that all incoming data on MOSI will be discarded, and the DEF (default) character will be clocked out on the MISO line throughout the whole transaction. This will also be the case even if the semaphore is released by the CPU during the transaction.

      The MAXTX parameter specifies the maximum number of bytes the SPI slave can transmit in one granted transaction. If the SPI slave is forced to transmit more than MAXTX number of bytes, an OVERREAD will be indicated in the STATUS register and the ORC character will be clocked out.

    Best regards,

    Jørgen

Reply
  • Hi,

    All these questions should be answered in the SPI slave operation section in the SPIS peripheral documentation. The peripheral implements a semaphore mechanism to enable safe shared access to the RAM buffers for both SPIS and CPU.

    1. As long as the semaphore is available the SPI slave can be granted multiple transactions one after the other. If the CPU is not able to reconfigure the TXD.PTR and RXD.PTR between granted transactions, the same TX data will be clocked out and the RX buffers will be overwritten. To prevent this from happening, the END_ACQUIRE shortcut can be used. With this shortcut enabled the semaphore will be handed over to the CPU automatically after the granted transaction has completed, giving the CPU the ability to update the TXPTR and RXPTR between every granted transaction.

    2. If the CPU tries to acquire the semaphore while it is assigned to the SPI slave, an immediate handover will not be granted. However, the semaphore will be handed over to the CPU as soon as the SPI slave has released the semaphore after the granted transaction is completed. If the END_ACQUIRE shortcut is enabled and the CPU has triggered the ACQUIRE task during a granted transaction, only one ACQUIRE request will be served following the END event.

      The function nrf_drv_spis_buffers_set can only be called when the semaphore is granted to the CPU. The SPIS driver will setup the the peripheral to make sure the semaphore is granted to the CPU after every transfer end. New buffers must be set by calling nrf_drv_spis_buffers_set after every finished transaction (in the callback handler on a NRF_DRV_SPIS_XFER_DONE event). Otherwise, the transaction is ignored, and the default character is clocked out.
    3. The SPI slave will try to acquire the semaphore when CSN goes low. If the SPI slave does not manage to acquire the semaphore at this point, the transaction will be ignored. This means that all incoming data on MOSI will be discarded, and the DEF (default) character will be clocked out on the MISO line throughout the whole transaction. This will also be the case even if the semaphore is released by the CPU during the transaction.

      The MAXTX parameter specifies the maximum number of bytes the SPI slave can transmit in one granted transaction. If the SPI slave is forced to transmit more than MAXTX number of bytes, an OVERREAD will be indicated in the STATUS register and the ORC character will be clocked out.

    Best regards,

    Jørgen

Children
  • Hi Jorgen,

    I'm struggling a bit with how to let my SPI slave code know that there is new data to send to the host processor.  Would this be a recommended way to do it from non-interrupt code? I also call nrf_driv_spis_buffers_set in my XFER_DONE handler. Is there any issue with multiple calls to nrf_drv_spis_buffers_set without an XFER_DONE in between?

    The idea here is I'd kick off a null transfer, and after that is done my XFER_DONE handler would see that it should queue more transfers with valid data.  The tx_st.tx_in_progress just lets me know that something valid has already been set up with a call to nrf_drv_spis_buffers_set, so I don't need to trigger this transfer.

    void rnet_host_spi_start_xfer() {
      CRITICAL_REGION_ENTER();
      if (!tx_st.tx_in_progress) {
          make_null_xfer(spis_tx_buf);
          APP_ERROR_CHECK(nrf_drv_spis_buffers_set(&spis, spis_tx_buf, SPIS_XFER_SZ, spis_rx_buf, SPIS_XFER_SZ));

          interrup_host();

      }
      CRITICAL_REGION_EXIT();
    }

    Also I was thumbing through the SPIS driver in sdk 15.0 and see that the END_ACQUIRE shortcut looks like it's being enabled by the driver.  I guess I can assume that the CPU has the semaphore as soon as I'm in my XFER_DONE handler and it's released with the call to nrf_drv_spis_buffers_set?  I'm seeing multiple transfers of the same data right now, so just wanted to make sure this shortcut was enabled.

    Thanks,

    Rob

Related