problem in adding time sync features in ESB

Dear all,

[nrf sdk version 17.02 ; Broad:nrf52840DK]

I am now combing the time sync code into ESB protocol.In the original time sync source code,time slot API is used in order to let esb work cocurrently with BLE protocol.

But in my case,I remove that part.I used esb_ptx to send data packet and using an app timer to trigger program sending sync packet each 30ms.

The method for taking timestamp to sync is one main difference  from the source code shown below.

esb_ptx modification

typedef struct
{
    uint8_t message_id;    //recogonize sync_pkt or urllc_payload
   
} urllc_header;
//sync packet format
typedef struct
{
    urllc_header header;
    int32_t  timer_val;
    uint32_t counter_val;
   
} sync_pkt_t;
//data packet format
typedef struct
{
    urllc_header header;
    int32_t seq_num;
    uint32_t time_stamp;                            //time stamp to evaluate latency
    uint8_t data[URLLC_PAYLOAD_LENGTH];

} urllc_payload;

void take_sync_timer_val(sync_pkt_t* p_pkt)
{
    uint32_t sync_timer_val;
    uint32_t count_timer_val;
    uint32_t  peer_count;
    timers_capture(&sync_timer_val, &count_timer_val, &peer_count);
    p_pkt->counter_val = count_timer_val;
    p_pkt->timer_val = sync_timer_val;
}
// timer handler for sending sync packet periodically
static void repeated_timer_handler(void * p_context)
{

    tx_payload.length = sizeof(sync_pkt_t);               //set packet length
    tx_payload.noack = true;                              //sync packet is not required ack
    sync_pkt_t *p_pkt;
    p_pkt = (sync_pkt_t*)malloc(sizeof(sync_pkt_t));
    p_pkt->header.message_id = SYNC_PKT;                  //rx used meassage id to tell whethere the packet is for sync or data transmit
    take_sync_timer_val(p_pkt); 
    memcpy(tx_payload.data,p_pkt,sizeof(sync_pkt_t));
    if (nrf_esb_write_payload(&tx_payload) == NRF_SUCCESS)
    {
         NRF_LOG_INFO("Sending sync packet succeed");
    }        
    else
    {
         NRF_LOG_WARNING("Sending sync failed");
    }
    free(p_pkt);
}

In esb_prx,Rx will receive two types of packet,one is data packet with URLLC_DATA_PKT(0) as meassage_id,the other is sync packet with SYNC_PKT(1) as meassage

id.In RADIO_IRQHandler(),Rx first see the meassage_id,if it equals to SYNC_PKT,then the program follow the compensate procedure as the time sync code,I only modified the

Tx_CHAIN_DELAY to 2800.If Rx received the packet with URLLC_DATA_PKT as meassage_id,then the program follows the precedure in esb_rx.

esb_prx modification

void RADIO_IRQHandler() {
  
    if (NRF_RADIO->EVENTS_READY && (NRF_RADIO->INTENSET & RADIO_INTENSET_READY_Msk)) {
      NRF_RADIO->EVENTS_READY = 0;
       //DEBUG_PIN_SET(DEBUGPIN1);
    }

    if (NRF_RADIO->EVENTS_END && (NRF_RADIO->INTENSET & RADIO_INTENSET_END_Msk)) {
       NRF_RADIO->EVENTS_END = 0;
       //DEBUG_PIN_SET(DEBUGPIN2);
      // Call the correct on_radio_end function, depending on the current protocol state
      if (on_radio_end) {
        on_radio_end();
      }
    }

    if (NRF_RADIO->EVENTS_DISABLED && (NRF_RADIO->INTENSET & RADIO_INTENSET_DISABLED_Msk)) {

      NRF_RADIO->EVENTS_DISABLED = 0;
      uint8_t message_id;
      message_id = m_rx_payload_buffer[2];
      switch (message_id){
      case SYNC_PKT:
            {
            
              bool adjustment_procedure_started;
              sync_pkt_t *p_pkt;
              p_pkt = (sync_pkt_t*)&m_rx_payload_buffer[2];
              adjustment_procedure_started = sync_timer_offset_compensate(p_pkt);
              /*if (adjustment_procedure_started) {
                p_pkt = tx_buf_get();
              }*/
              clear_events_restart_rx();
            }
            break;

      case URLLC_DATA_PKT:
            if (on_radio_disabled) 
            {
              on_radio_disabled();
            }
            
            break;

      }

    }

  }

osciliscope results
the results looks fine at the begining,the fine states probably will remain for two minutes and after that,the wave started to glide slowly(shown in the below vedio),it seems RX didn't receive sync packet anymore.
by the way,I think there are bugs in my radio_irqhandler() in esb_prx,could anyone help me please,thanks a lot!!
 
Best Regards,
Hao.
 
Parents
  • Hi,

    I am sorry for the delay in this thread. Edvin is out of office and I have inherited it from him. Have you had any progress on your end the last couple of weeks?

  • Hi,

    Sorry for the late reply,I didn't solve it yet,can you help me check the code snippet please.

    I probably did something wrong. 

  • Hi,

    No problem, I can take a look. I am not able to see much from these snippets though. Can you upload your full project here (at least everything related to ESB), and explain in a bit more detail what you have done, what you have seen from debugging/testing etc?

  • nRF5_SDK_17.0.2_esb_tx.7z

    Hi,sorry for the late reply, my TX program is in ...\nRF5_SDK_17.0.2_esb_tx\examples\proprietary_rf\esb_ptx, in main.c,the while loop(line.325) sending the data packet periodically using nrf_esb_write_payload(&tx_payload).

        while (true)
        {
            
            uint32_t time_stamp;
            uint32_t seq;
    
            tx_payload.length = sizeof(urllc_payload);
            tx_payload.noack = true;                        //all packet is not required ack
            urllc_payload *p_urllc_payload;
            p_urllc_payload = (urllc_payload*)malloc(sizeof(urllc_payload));
            p_urllc_payload -> header.message_id = URLLC_DATA_PKT;
            p_urllc_payload -> seq_num = seq;
            time_stamp = TIME_SYNC_TIMESTAMP_TO_USEC(ts_timestamp_get_ticks_u64()); //get ticks and transfer to USEC
            p_urllc_payload -> time_stamp =  time_stamp;
            memcpy(tx_payload.data,p_urllc_payload,sizeof(urllc_payload));
               
            if (nrf_esb_write_payload(&tx_payload) == NRF_SUCCESS)
            {
    
              //NRF_LOG_INFO("Sending urllc data packet succeed");
    
            }        
            else{
    
              NRF_LOG_WARNING("Sending urllc data packet failed");
            
            }
            free(p_urllc_payload);
            seq++;
            
            nrf_delay_ms(50);
            NRF_LOG_FLUSH();
        }

    Mean while,there is a app timer called sync_timer keep sending sync packet every 30ms 

    static void repeated_timer_handler(void * p_context)
    {
    
        tx_payload.length = sizeof(sync_pkt_t);               //set tx_payload length packet length
        tx_payload.noack = true;                              //all packet is not required ack
        sync_pkt_t *p_pkt;
        p_pkt = (sync_pkt_t*)malloc(sizeof(sync_pkt_t));
        p_pkt->header.message_id = SYNC_PKT;
        take_sync_timer_val(p_pkt); 
        memcpy(tx_payload.data,p_pkt,sizeof(sync_pkt_t));
        if (nrf_esb_write_payload(&tx_payload) == NRF_SUCCESS)
        {
             //NRF_LOG_INFO("Sending sync packet succeed");
        }        
        else
        {
             NRF_LOG_WARNING("Sending sync failed");
        }
        free(p_pkt);
    }

    And all the time sync featured code related to time sync TX is in ...\nRF5_SDK_17.0.2_esb_tx\components\proprietary_rf\esb\nrf_esb.c

  • nRF5_SDK_17.0.2_esb_rx.7z 

    Above is my Rx program,it is in ...\nRF5_SDK_17.0.2_esb_rx\examples\proprietary_rf\esb_prx,basically the time sync featured code is added in main.c and ...\nRF5_SDK_17.0.2_esb_tx\components\proprietary_rf\esb\nrf_esb.c,in nrf_esb.c,the RADIO_IRQHandler() is called when radio receiving packet,in the unmodified version of nrf_esb.c,once receiving packet,on_radio_disabled() is called.but in my case,I have two kinds of receiving packet,one is urllc_data_pkt and the other is sync_pkt identified by meassage_id.

    So in RADIO_IRQHandler(),I treat urllc_data_pkt as the esb data packet (follow the original procedure how esb handle the data) and I add the case:SYNC_PKT to handle the sync procedure.

    void RADIO_IRQHandler() {
      
        if (NRF_RADIO->EVENTS_READY && (NRF_RADIO->INTENSET & RADIO_INTENSET_READY_Msk)) {
          NRF_RADIO->EVENTS_READY = 0;
           //DEBUG_PIN_SET(DEBUGPIN1);
        }
    
        if (NRF_RADIO->EVENTS_END && (NRF_RADIO->INTENSET & RADIO_INTENSET_END_Msk)) {
           NRF_RADIO->EVENTS_END = 0;
           //DEBUG_PIN_SET(DEBUGPIN2);
          // Call the correct on_radio_end function, depending on the current protocol state
          if (on_radio_end) {
            on_radio_end();
          }
        }
    
        if (NRF_RADIO->EVENTS_DISABLED && (NRF_RADIO->INTENSET & RADIO_INTENSET_DISABLED_Msk)) {
    
          NRF_RADIO->EVENTS_DISABLED = 0;
          uint8_t message_id;
          message_id = m_rx_payload_buffer[2];
          switch (message_id){
          case SYNC_PKT:
                {
                  bool adjustment_procedure_started;
                  sync_pkt_t *p_pkt;
                  p_pkt = (sync_pkt_t*)&m_rx_payload_buffer[2];
                  adjustment_procedure_started = sync_timer_offset_compensate(p_pkt);
                  if (adjustment_procedure_started) {
                    p_pkt = tx_buf_get();
                  }
                  clear_events_restart_rx();
                }
                break;
    
          case URLLC_DATA_PKT:
                if (on_radio_disabled) 
                {
                  on_radio_disabled();
                }
                
                break;
    
          }
    
        }
    
      }
    

    Thanks for your kindly help

    Best Regards,

    Hao.

Reply
  • nRF5_SDK_17.0.2_esb_rx.7z 

    Above is my Rx program,it is in ...\nRF5_SDK_17.0.2_esb_rx\examples\proprietary_rf\esb_prx,basically the time sync featured code is added in main.c and ...\nRF5_SDK_17.0.2_esb_tx\components\proprietary_rf\esb\nrf_esb.c,in nrf_esb.c,the RADIO_IRQHandler() is called when radio receiving packet,in the unmodified version of nrf_esb.c,once receiving packet,on_radio_disabled() is called.but in my case,I have two kinds of receiving packet,one is urllc_data_pkt and the other is sync_pkt identified by meassage_id.

    So in RADIO_IRQHandler(),I treat urllc_data_pkt as the esb data packet (follow the original procedure how esb handle the data) and I add the case:SYNC_PKT to handle the sync procedure.

    void RADIO_IRQHandler() {
      
        if (NRF_RADIO->EVENTS_READY && (NRF_RADIO->INTENSET & RADIO_INTENSET_READY_Msk)) {
          NRF_RADIO->EVENTS_READY = 0;
           //DEBUG_PIN_SET(DEBUGPIN1);
        }
    
        if (NRF_RADIO->EVENTS_END && (NRF_RADIO->INTENSET & RADIO_INTENSET_END_Msk)) {
           NRF_RADIO->EVENTS_END = 0;
           //DEBUG_PIN_SET(DEBUGPIN2);
          // Call the correct on_radio_end function, depending on the current protocol state
          if (on_radio_end) {
            on_radio_end();
          }
        }
    
        if (NRF_RADIO->EVENTS_DISABLED && (NRF_RADIO->INTENSET & RADIO_INTENSET_DISABLED_Msk)) {
    
          NRF_RADIO->EVENTS_DISABLED = 0;
          uint8_t message_id;
          message_id = m_rx_payload_buffer[2];
          switch (message_id){
          case SYNC_PKT:
                {
                  bool adjustment_procedure_started;
                  sync_pkt_t *p_pkt;
                  p_pkt = (sync_pkt_t*)&m_rx_payload_buffer[2];
                  adjustment_procedure_started = sync_timer_offset_compensate(p_pkt);
                  if (adjustment_procedure_started) {
                    p_pkt = tx_buf_get();
                  }
                  clear_events_restart_rx();
                }
                break;
    
          case URLLC_DATA_PKT:
                if (on_radio_disabled) 
                {
                  on_radio_disabled();
                }
                
                break;
    
          }
    
        }
    
      }
    

    Thanks for your kindly help

    Best Regards,

    Hao.

Children
Related