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

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

Children
Related