nRF Connect SDK - SPIS acquiring the semaphore

Hi,

I've been using the SDK shipped with a vendor product and a feature that I use is to acquire the SPIS semaphore as part of the SPIS handler.  The version of the SDK that comes with the vendor product has this snippet in nrfx_spis.h:

/** @brief SPI slave driver event types. */
typedef enum
{
    NRFX_SPIS_BUFFERS_SET_DONE, //!< Memory buffer set event. Memory buffers have been set successfully to the SPI slave device, and SPI transaction can be done.
    NRFX_SPIS_XFER_DONE,        //!< SPI transaction event. SPI transaction has been completed.
    NRFX_SPIS_BUFFER_END,       //!< SPI transaction event. SPI Rx Buffer has been filled.
    NRFX_SPIS_SPIS_ACQUIRED,    //!< SPI transaction event. SPI Semaphore has been acquired.
    NRFX_SPIS_EVT_TYPE_MAX      //!< Enumeration upper bound.
} nrfx_spis_evt_type_t;

Now the vendor has shipped an updated product with updated Nordic libraries and the same file now has this:

/** @brief SPI slave driver event types. */
typedef enum
{
    NRFX_SPIS_BUFFERS_SET_DONE, //!< Memory buffer set event. Memory buffers have been set successfully to the SPI slave device, and SPI transaction can be done.
    NRFX_SPIS_XFER_DONE,        //!< SPI transaction event. SPI transaction has been completed.
    NRFX_SPIS_EVT_TYPE_MAX      //!< Enumeration upper bound.
} nrfx_spis_evt_type_t;

Notably, no NRFX_SPIS_SPIS_ACQUIRED enumeration.

What is the recommended way to acquire the SPIS semaphore?

Regards,

AC

Parents
  • One thing I forgot to mention. With the current SPIS library, I get visibility over whether the semaphore has been acquired so I have code like this:

    static void palSpiCallback (nrfx_spis_evt_t const *pEvent, void *p_cb, NRF_SPIS_Type *p_spis)
    {
    
        if (pEvent->evt_type == NRFX_SPIS_SPIS_ACQUIRED)
        {
    
            if (isConnected == FALSE)
    

    In the callback, if the semaphore has been acquired, I manipulate the read and write buffers...

    With the latest library, I have no visibility over the semaphore acquisition so cannot reliably manipulate the buffers.

    Regards,

    AC

  • What kind of SDK are you using? nRF5 SDK, nRF Connect SDK or something else?

    I tried to search for NRFX_SPIS_SPIS_ACQUIRED in our entire database of cases/documentation/nRF Connect SDK folders, but could not find this anywhere.

    skajam66 said:
    With the latest library, I have no visibility over the semaphore acquisition so cannot reliably manipulate the buffers.

    I found the following types in th lower level HAL nrfx_spis.h

    https://github.com/nrfconnect/sdk-hal_nordic/blob/v1.5.2/nrfx/hal/nrf_spis.h#L56-L67

    https://github.com/nrfconnect/sdk-hal_nordic/blob/v1.5.2/nrfx/hal/nrf_spis.h#L99-L106

    https://github.com/nrfconnect/sdk-hal_nordic/blob/v1.5.2/nrfx/hal/nrf_spis.h#L274-L281

    https://github.com/nrfconnect/sdk-hal_nordic/blob/v1.5.2/nrfx/hal/nrf_spis.h#L553-L557

    Maybe those could be of help?

    However, the higher level driver nrfx_spis.c uses these types, so maybe take a look at that, to get a better understanding.

    https://github.com/nrfconnect/sdk-hal_nordic/blob/v1.5.2/nrfx/drivers/src/nrfx_spis.c

    I've worked mostly with high level APIs in Zephyr/nRF Connect SDK (I saw your title contained "nRF Connect SDK", so I took the case), so I don't have complete control over this. Let me know if my answer didn't help and I will investigate more.

    Best regards,

    Simon

  • Hi Simon,

    Thank you for your response.

    >> What kind of SDK are you using? nRF5 SDK, nRF Connect SDK or something else?

    It's nRF Connect SDK as far as I can tell. The drivers are all provided as part of the vendor package but it looks like nRF Connect SDK to me. I am aware that nRF5 SDK has been deprecated but I don't think these libraries are nRF5 SDK (is there any way I can confirm this?). The vendor file structure is: ../thirdparty/nordic/nrfx/drivers/src etc. The vendor also supplies what I think is the old nRF5 SDK as well under the file structure: /thirdparty/nordic-bsp/modules/nrfx/drivers etc. The nrfx_spis.c file that I am referring to is this one: ../thirdparty/nordic/nrfx/drivers/src/nrfx_spis.c.

    If I look at the interrupt handler in nrfx_spis.c for both the old and new libraries I see this:

    Old nrfx_spis.c:

    static void spis_irq_handler(NRF_SPIS_Type * p_spis, spis_cb_t * p_cb)
    {
        // @note: as multiple events can be pending for processing, the correct event processing order
        // is as follows:
        // - SPI semaphore acquired event.
        // - SPI transaction complete event.
    
        // Check for SPI Buffer Completion event. Do this first to minimise time in ISR
        if (nrf_spis_event_check(p_spis, NRF_SPIS_EVENT_ENDRX))
        {
            nrfx_spis_evt_t event;
    
            event.evt_type  = NRFX_SPIS_BUFFER_END;
            event.rx_amount = 0;
            event.tx_amount = 0;
    
            nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_ENDRX);
            p_spis->STATUS = 3;
            p_cb->spi_state = SPIS_BUFFER_END;
    
            NRFX_ASSERT(p_cb != NULL);
            p_cb->handler(&event, p_cb, p_spis);
    
        }
    
        // Check for SPI semaphore acquired event.
        if (nrf_spis_event_check(p_spis, NRF_SPIS_EVENT_ACQUIRED))
        {
            nrfx_spis_evt_t event;
    
            event.evt_type  = NRFX_SPIS_SPIS_ACQUIRED;
            event.rx_amount = 0;
            event.tx_amount = 0;
    
            nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_ACQUIRED);
            p_cb->handler(&event, p_cb, p_spis);
    
    
        }
    

    New nrfx_spis.c (identical to the v1.5.2 nrfx_spis.c that you referenced above):

    static void spis_irq_handler(NRF_SPIS_Type * p_spis, spis_cb_t * p_cb)
    {
        // @note: as multiple events can be pending for processing, the correct event processing order
        // is as follows:
        // - SPI semaphore acquired event.
        // - SPI transaction complete event.
    
        // Check for SPI semaphore acquired event.
        if (nrf_spis_event_check(p_spis, NRF_SPIS_EVENT_ACQUIRED))
        {
            nrf_spis_event_clear(p_spis, NRF_SPIS_EVENT_ACQUIRED);
            NRFX_LOG_DEBUG("SPIS: Event: %s.", EVT_TO_STR(NRF_SPIS_EVENT_ACQUIRED));
    
            switch (p_cb->spi_state)
            {
                case SPIS_BUFFER_RESOURCE_REQUESTED:
                    nrf_spis_tx_buffer_set(p_spis, (uint8_t *)p_cb->tx_buffer, p_cb->tx_buffer_size);
                    nrf_spis_rx_buffer_set(p_spis, (uint8_t *)p_cb->rx_buffer, p_cb->rx_buffer_size);
    
                    nrf_spis_task_trigger(p_spis, NRF_SPIS_TASK_RELEASE);
    
                    spis_state_change(p_spis, p_cb, SPIS_BUFFER_RESOURCE_CONFIGURED);
                    break;
    
                default:
                    // No implementation required.
                    break;
            }
        }
    

    The notable difference is that in v1.5.2, there is no callback that floats the event up to the higher level:

        p_cb->handler(&event, p_cb, p_spis);

    Of course, I could modify the IRQ to make it behave the way it did but that seems pretty drastic.

    Any suggestions would be welcome.

    Kind regards,

    AC

  • Hello, sorry for the delay. Have you been able to make any progress on this?

    Looking at nrfx_spis_init, it seems like END_ACQUIRE is enabled by default. In that case, everytime the transfer is completed and an END event happen, the semaphore is acquired automatically.

    Just wait for the event NRFX_SPIS_XFER_DONE

    https://github.com/nrfconnect/sdk-hal_nordic/blob/8f013ea950f41bf69b18bf688bfb0dd80a3fdc44/nrfx/drivers/src/nrfx_spis.c#L352

    https://github.com/nrfconnect/sdk-hal_nordic/blob/8f013ea950f41bf69b18bf688bfb0dd80a3fdc44/nrfx/drivers/src/nrfx_spis.c#L360

    This is how it is done in NCS SPIS samples it seems like. Initially at start up you set the rx and tx buffers, then immediately after each transfer is completed, the buffers are updated.

    Best regards,

    Simon

Reply Children
  • Hi Simon,

    Apologies for the slow response to this.

    It looks to me like someone on the vendor side has modified the driver IRQ routine to expose the ACQUIRE status to the higher level.

    Unfortunately, the way the driver works without modification is not appropriate for my case. By way of explanation, I am working on a low latency audio project and I need to manipulate buffers in a 20us window following the ACQURE signal.  The way that ACQUIRE works in the unmodified driver is that on ACQUIRE, the IRQ routine swaps in RX and TX buffers that have been put there prior to the ACQUIRE signal thus adding latency.

    Because of this modification, it is not appropriate to ask for assistance from Nordic so, if you agree, let's close this ticket.

    Kind regards,

    AC

  • skajam66 said:
    Because of this modification, it is not appropriate to ask for assistance from Nordic so, if you agree, let's close this ticket.

    Yes, I agree. I can close the ticket.

    BR,

    Simon

Related