Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Time synchronization with alternating masters

Dear members,

with success I implemented the time synchronization example from the nRF5 SDK guide.
This example works perfect for a single master, but what if the master changes?
When I check my scope it will show that the new master starts sending the sync beacons, but the slave (previous master) is not receiving and stays low.
Would there be a solution to put a master in receiver mode after stopping the sync beacons?

I am using four nRF52840-DKs with Segger Studio, SDK 17 and a S140 softdevice (used for a custom BLE service)

Parents Reply Children
  • Hello Kenneth,

    that would be great. If I find the solution before Easter I will let you know ;).

    Regards, Egbert

  • Hello Kenneth,

    I was not able to find a solution to this item. Did you managed to contact the creator of this example?

    Regards, Egbert

  • Hi Egbert,

    I suspect there is state information still lingering after stopping the transmitter. Could you try the attached diff on your side?

    My test was  the following, based on 2 x nRF52-DK.

    1) Press button 1 on DK #1 to assign this role of transmitter

    2) Observe that both DKs toggle GPIO in unison

    3) Press button 1 on DK #1 to stop transmitting

    4) Wait until DK #2 reports desynchronization (GPIO stops togglnig)

    5) Press button 1 on DK #2 to assign this role of transmitter

    6) Observe that both DKs toggle GPIO in unison

    diff --git a/nRF5_SDK_16.0.0_98a08e2/examples/common/time_sync.c b/nRF5_SDK_16.0.0_98a08e2/examples/common/time_sync.c
    index 4a21351..871498a 100644
    --- a/nRF5_SDK_16.0.0_98a08e2/examples/common/time_sync.c
    +++ b/nRF5_SDK_16.0.0_98a08e2/examples/common/time_sync.c
    @@ -128,6 +128,7 @@ static nrf_atomic_u32_t m_sync_pkt_ringbuf_idx;
     
     static nrf_atomic_flag_t m_timeslot_session_open;
     static nrf_atomic_flag_t m_pending_close;
    +static nrf_atomic_flag_t m_pending_tx_stop;
     static nrf_atomic_u32_t  m_blocked_cancelled_count;
     static uint32_t          m_total_timeslot_length = 0;
     static uint32_t          m_timeslot_distance = 0;
    @@ -469,6 +470,15 @@ void timeslot_begin_handler(void)
     
         m_total_timeslot_length = 0;
     
    +    if (m_pending_tx_stop)
    +    {
    +        nrf_atomic_flag_clear(&m_send_sync_pkt);
    +        nrf_atomic_flag_clear(&m_pending_tx_stop);
    +        m_timeslot_distance = 0;
    +        m_synchronized = false;
    +        m_master_counter_diff = 0;
    +    }
    +
         if (!m_send_sync_pkt)
         {
             if (m_radio_state    != RADIO_STATE_RX ||
    @@ -737,6 +747,7 @@ void SWI3_EGU3_IRQHandler(void)
             if (m_synchronized)
             {
                 m_synchronized = false;
    +            m_master_counter_diff = 0;
     
                 if (m_callback)
                 {
    @@ -1217,7 +1228,7 @@ uint32_t ts_tx_start(uint32_t sync_freq_hz)
     
     uint32_t ts_tx_stop()
     {
    -    nrf_atomic_flag_clear(&m_send_sync_pkt);
    +    nrf_atomic_flag_set(&m_pending_tx_stop);
     
         return NRF_SUCCESS;
     }
    

    Best regards,

    Audun

  • Hi again,

    I thought about it some more and decided the previous diff was a not so good workaround. This one should work better, as it doesn't reset the "m_master_counter_diff" variable. Resetting this variable would cause a jump in timestamps, which is probably not desirable.

    Best regards,

    Audun

    diff --git a/nRF5_SDK_16.0.0_98a08e2/examples/common/time_sync.c b/nRF5_SDK_16.0.0_98a08e2/examples/common/time_sync.c
    index 4a21351..65c5c13 100644
    --- a/nRF5_SDK_16.0.0_98a08e2/examples/common/time_sync.c
    +++ b/nRF5_SDK_16.0.0_98a08e2/examples/common/time_sync.c
    @@ -128,6 +128,7 @@ static nrf_atomic_u32_t m_sync_pkt_ringbuf_idx;
     
     static nrf_atomic_flag_t m_timeslot_session_open;
     static nrf_atomic_flag_t m_pending_close;
    +static nrf_atomic_flag_t m_pending_tx_stop;
     static nrf_atomic_u32_t  m_blocked_cancelled_count;
     static uint32_t          m_total_timeslot_length = 0;
     static uint32_t          m_timeslot_distance = 0;
    @@ -469,6 +470,14 @@ void timeslot_begin_handler(void)
     
         m_total_timeslot_length = 0;
     
    +    if (m_pending_tx_stop)
    +    {
    +        nrf_atomic_flag_clear(&m_send_sync_pkt);
    +        nrf_atomic_flag_clear(&m_pending_tx_stop);
    +        m_timeslot_distance = 0;
    +        m_synchronized = false;
    +    }
    +
         if (!m_send_sync_pkt)
         {
             if (m_radio_state    != RADIO_STATE_RX ||
    @@ -517,6 +526,7 @@ void timeslot_begin_handler(void)
     
         p_pkt->timer_val   = m_params.high_freq_timer[0]->CC[1];
         p_pkt->counter_val = m_params.high_freq_timer[1]->CC[1];
    +    p_pkt->counter_val += m_master_counter_diff;
     
     //    p_pkt->rtc_val     = m_params.rtc->COUNTER;
     
    @@ -1217,7 +1227,7 @@ uint32_t ts_tx_start(uint32_t sync_freq_hz)
     
     uint32_t ts_tx_stop()
     {
    -    nrf_atomic_flag_clear(&m_send_sync_pkt);
    +    nrf_atomic_flag_set(&m_pending_tx_stop);
     
         return NRF_SUCCESS;
     }
    

  • Hello Audun,

    Thank you for your reply!

    I did the diff on my side it all compiles ok. But I think I did something wrong, since I am not able to switch masters. All the steps as described work fine, except for the last step (step 6) since only the new master starts to toggle, the new slave does not toggle its GPIO. 

    Can you tell me the reason why you added "m_master_counter_diff" and where to declare this variable?

    regards Egbert

Related