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

semaphore equivalents for nRF51822 and nRF52840

I have been working with the pc-ble-driver on the PC. Now I want to move my code to the nRF51822 and nRF52840 chips. Starting with the DKs first.

On the PC when I get an ble_evt_t in the dispatch callback (usually called ble_evt_dispatch() in the SDK examples) I triggered a posix semaphone on certain events, for example the write of some command on a control point. I also used a similar semaphore when sending measurements. On an indication/notification event I would trigger the semaphore and in the measurement send method I would be waiting on that semaphore to send the next measurement.

For example on the Indication event

case BLE_GATTS_EVT_HVC:
            printf("Confirmation of indication on handle %d received at time %llu\n", p_ble_evt->evt.gatts_evt.params.hvc.handle,
                (GetTickCount64() - elapsedTimeStart));
            fflush(stdout);
            sem_post(&indicateSem);
            break;

In the measurement sending method I would have a matching 

sem_wait(&indicateSem);

These are the standard posix calls.

I want to do the same on the chips. Is there an equivalent to this 'semaphore'  one can wait on and post?

Maybe these are not necessary? Usually timely returns on callbacks are 'mandatory'. However, having semaphores FORCES synchrony between the peripheral and central which is one of the main points here.

At the moment I am using SDK 12.3.0 and SoftDevice s130 (the latest SDK/SoftDevice for the nRF51822).

Its probably somewhere in the SDK documentation but the search function is so bad one will only hit the search if one is on the right page. The search routines do not work globally over the entire documentation which makes searching for items that you have no idea where they might be is next to impossible. It wont even find the word 'wait' when it is right in the text on the same page. I am not sure what the search is for. IN any case, I have had to turn to searching here to get results. Posix-like Semaphores seem to be a rare topic.

I do see this sd_app_evt_wait() in the example code on the power management.

Is there a call I can make that will cause this method to FHIR or is this something only SoftDevice can do?

Thanks

  • Hi,

    The closest thing you get in the SDK is nrf_atomic, which can be used to implement a semaphore. That only works on the nRF52 series though, as it depends on the LDREX/STREX instructions.

  • Is there some way I can accomplish the same task using s130? I remember reading something somewhere about being able to poll for interrupts coming up from SoftDevice. If I could catch the indication event using this polliing that would be one solution

    Is there a way to do a non-busy wait during this polling loop?

    Looking at sd_app_evt_wait(). Can I use this to wait for a BLE_GATTS_EVT_HVC event? Can I do it selectively? Or do I have to get ALL events? What will happen to my standard event handler (often called ble_evt_dispatch()) in the examples.

    Man this is a real pain! Mutexes but no semaphore!

    Is there such a thing as an application interrupt so I can use sd_app_evt_wait() that I can trigger from the event handler callback? Boy that would be wonderful.

    Is there a way to simulate a condition variable or does that require non-existent support on this chip? Is there a way to simulate a semaphore using mutexes on the nrf51822?

    Would this be a valid option?

    error_code = sd_ble_gatts_hvx(m_adapter, m_connection_handle, &hvx_params);
    if (error_code == NRF_SUCCESS || error_code == NRF_ERROR_BUSY)
    {
        while (error_code == NRF_ERROR_BUSY)
        {
            error_code = sd_ble_gatts_hvx(m_adapter, m_connection_handle, &hvx_params);
        }
        ....
    }

    I did try this code using the pc-ble-driver and it DID work. (I have working code using the pc-ble-driver that I am attempting to port to an actual chip). Sometimes it took five to six retries before it was no longer busy. In this manner I was able to skip using semaphores. Before, on success, I just waited on a semaphore after the indication call and in the call back, signaled it when the indication signaled complete.

  • Hi,

    brianreinhold said:
    Can I use this to wait for a BLE_GATTS_EVT_HVC event? Can I do it selectively? Or do I have to get ALL events?

    You get events from the SoftDevice by polling sd_evt_get(), but there is no way to poll for just some specific events.

    brianreinhold said:
    Is there a way to do a non-busy wait during this polling loop?

    Yes. Typically you would call sd_evt_get() repeatedly back-to-back until there are no more events (it returns NRF_ERROR_NOT_FOUND), and then you would wait for a interrupt from the SoftDevice before pollig again. During that time you would typically put the device in system on low power mode by calling sd_app_evt_wait().

    brianreinhold said:
    Is there such a thing as an application interrupt so I can use sd_app_evt_wait() that I can trigger from the event handler callback? Boy that would be wonderful.

    Can you elaborate?

    brianreinhold said:
    Is there a way to simulate a condition variable or does that require non-existent support on this chip? Is there a way to simulate a semaphore using mutexes on the nrf51822?

    I am not sure what you mean by simulate here, but there is no way to implement a proper semaphore on the nRF51 series as there is no HW support for atomic operations. A typical way to achieve the same goal if you need to do some atomic operations is to use critical sections (CRITICAL_REGION_ENTER() / CRITICAL_REGION_EXIT()) . With that, you disable interrupts, change a shared variable, and enable interrupts again. This is more intrusive than a proper semaphore, but should give you the same benefit.

    brianreinhold said:
    Would this be a valid option?

    Yes

  • I ended up doing the last option where I repeatedly invoked sd_ble_gatts_hvx() until not busy. This appears to have worked, at least using the pc driver. I have not tried it yet on an actual chip (or DK).

Related