Radio transmit and receive in timeslot

Hi,

I am developing a project that includes transmission and reception in particular timeslots. I checked the radio example in nrf5 sdk and copied the trasmission part to my timeslot file. Now first transmission is happening but afer that transmission is not working. I think its getting stuck in this while loop.   while (NRF_RADIO->EVENTS_DISABLED == 0U) 

Please have look at the below code

nrf_radio_signal_callback_return_param_t *radio_callback(uint8_t signal_type) {
  //printf("\n signal = %d",signal_type);
  switch (signal_type) {
  case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START:
    //Start of the timeslot - set up timer interrupt
    signal_callback_return_param.params.request.p_next = NULL;
    signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;

    NRF_TIMER0->INTENSET = TIMER_INTENSET_COMPARE0_Msk;
    NRF_TIMER0->CC[0] = m_slot_length - 1000;
    NVIC_EnableIRQ(TIMER0_IRQn);

    nrf_gpio_pin_toggle(20); //Toggle LED4
    adv_flag = 1;
    break;

  case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO:
    signal_callback_return_param.params.request.p_next = NULL;
    signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
    break;

  //case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0:
  //  //Timer interrupt - attempt to increase timeslot length
  //  signal_callback_return_param.params.extend.length_us = m_slot_length;
  //  signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_EXTEND;
  //  break;
  //case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED:
  //  //Extension succeeded, reset timer(configurations still valid since slot length is the same)
  //  NRF_TIMER0->TASKS_CLEAR = 1;
  //  break;
  case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0:
    //Timer interrupt - do graceful shutdown - schedule next timeslot
    configure_next_event_normal();
    signal_callback_return_param.params.request.p_next = &m_timeslot_request;
    signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END;
    adv_flag = 0;
    break;
  case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED:
    //No implementation needed
    break;
  case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED:
    //Try scheduling a new timeslot
    configure_next_event_earliest();
    signal_callback_return_param.params.request.p_next = &m_timeslot_request;
    signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END;
    break;
  default:
    //No implementation needed
    break;
  }
  return (&signal_callback_return_param);
}
void send_packet() {
  // send the packet:
  NRF_RADIO->PACKETPTR = (uint32_t)&packet;

  NRF_RADIO->EVENTS_READY = 0U;
  NRF_RADIO->TASKS_TXEN = 1;

  while (NRF_RADIO->EVENTS_READY == 0U) {
  printf("hai");
    // wait
  }
  NRF_RADIO->EVENTS_END = 0U;
  NRF_RADIO->TASKS_START = 1U;

  while (NRF_RADIO->EVENTS_END == 0U) {
    // wait
  }

  uint32_t err_code = bsp_indication_set(BSP_INDICATE_SENT_OK);
  NRF_LOG_INFO("The packet was sent");
  APP_ERROR_CHECK(err_code);

  NRF_RADIO->EVENTS_DISABLED = 0U;
  // Disable radio
  NRF_RADIO->TASKS_DISABLE = 1U;

  while (NRF_RADIO->EVENTS_DISABLED == 0U) {
    // wait
  }
}
void clock_initialization() {
  /* Start 16 MHz crystal oscillator */
  NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
  NRF_CLOCK->TASKS_HFCLKSTART = 1;

  /* Wait for the external oscillator to start up */
  while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) {
    // Do nothing.
  }

  /* Start low frequency crystal oscillator for app_timer(used by bsp)*/
  NRF_CLOCK->LFCLKSRC = (CLOCK_LFCLKSRC_SRC_Xtal << CLOCK_LFCLKSRC_SRC_Pos);
  NRF_CLOCK->EVENTS_LFCLKSTARTED = 0;
  NRF_CLOCK->TASKS_LFCLKSTART = 1;

  while (NRF_CLOCK->EVENTS_LFCLKSTARTED == 0) {
    // Do nothing.
  }
}
  int main(void) {
  clock_initialization();
  ble_stack_init();
  timeslot_sd_init();
  for (;;) {

    // idle_state_handle();

    if (adv_flag == 1) {
      radio_configure();
      adv_flag = 0;
      packet = 4;
      send_packet();
      printf("\nw");
      packet = 0;
      NRF_LOG_FLUSH();

    } else {

    }
    __WFE();
  }

Parents
  • Hi,

    I think its getting stuck in this while loop.   while (NRF_RADIO->EVENTS_DISABLED == 0U) 

    I do not immediately see how it could be stuck here (you should get the DISABLED event shortly after writing to the DISABLE task. As you write "think" I wonder if you have actually verified with a debugger that this is the case? If not, can you do it?

    If it is indeed the case, then the only reason that comes to mind is if this triggers an interrupt or for some other reason a higher priority piece of code runs before your loop and sets EVENTS_DISABLED to 0 again. That is just an hypothesis, though.

  • Hi,

    Sorry. I was not in that while .. it is in events ready while loop. while (NRF_RADIO->EVENTS_READY == 0U) . I tested by debugging.

  • Hi,

    I removed all printf and checked using 2 devices. In one device the above code (transmission and time slot combined ) and in other the radio receiver example code. And put two devices in debugging mode. I found that only one packet is received in the receiving side. I have checked and confirmed that one transmission is working and for the second transmission, the lines after while loop in the send_packet() function are not functioning. So the code is getting stuck in that while loop.

  • Hi,

    That is unexpected. Do the two transmits (the first successful and second failing) happen in the same timeslot? Or could it be that the SoftDevice is using the radio in the meantime. It does not look like that from the code snippets but perhaps they do not shot the full picture. Can you share more of your code so that I get a fuller picture of what is happening?

    Also, can you check with a debugger if execution is really halted in the while waiting loop and not just check if something afterwards is happening or not (without it, there could theoretically be another problem somewhere else with higher priority that prevents this code snippet from running, so it would be good to know with certainty that you see that execution is "stuck" in this waiting loop.)

  • /**@brief Request next timeslot event in earliest configuration
     */
    uint32_t request_next_event_earliest(void) {
      m_slot_length = 50000;
      m_timeslot_request.request_type = NRF_RADIO_REQ_TYPE_EARLIEST;
      m_timeslot_request.params.earliest.hfclk = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
      m_timeslot_request.params.earliest.priority = NRF_RADIO_PRIORITY_NORMAL;
      m_timeslot_request.params.earliest.length_us = m_slot_length;
      m_timeslot_request.params.earliest.timeout_us = 1000000;
      return sd_radio_request(&m_timeslot_request);
    }
    
    /**@brief Configure next timeslot event in earliest configuration
     */
    void configure_next_event_earliest(void) {
      m_slot_length = 50000;
      m_timeslot_request.request_type = NRF_RADIO_REQ_TYPE_EARLIEST;
      m_timeslot_request.params.earliest.hfclk = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
      m_timeslot_request.params.earliest.priority = NRF_RADIO_PRIORITY_NORMAL;
      m_timeslot_request.params.earliest.length_us = m_slot_length;
      m_timeslot_request.params.earliest.timeout_us = 1000000;
    }
    
    /**@brief Configure next timeslot event in normal configuration
     */
    void configure_next_event_normal(void) {
      m_slot_length = 50000;
      m_timeslot_request.request_type = NRF_RADIO_REQ_TYPE_NORMAL;
      m_timeslot_request.params.normal.hfclk = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
      m_timeslot_request.params.normal.priority = NRF_RADIO_PRIORITY_HIGH;
      m_timeslot_request.params.normal.distance_us = 1000000;
      m_timeslot_request.params.normal.length_us = m_slot_length;
    }
    
    /**@brief Timeslot signal handler
     */
    void nrf_evt_signal_handler(uint32_t evt_id) {
      uint32_t err_code;
    
      switch (evt_id) {
      case NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN:
        //No implementation needed
        break;
      case NRF_EVT_RADIO_SESSION_IDLE:
        //No implementation needed
        break;
      case NRF_EVT_RADIO_SESSION_CLOSED:
        //No implementation needed, session ended
        break;
      case NRF_EVT_RADIO_BLOCKED:
        //Fall through
      case NRF_EVT_RADIO_CANCELED:
        err_code = request_next_event_earliest();
        APP_ERROR_CHECK(err_code);
        break;
      default:
        break;
      }
    }
    uint32_t timeslot_sd_init(void) {
      uint32_t err_code;
    
      err_code = sd_radio_session_open(radio_callback);
      if (err_code != NRF_SUCCESS) {
        return err_code;
      }
    
      err_code = request_next_event_earliest();
      if (err_code != NRF_SUCCESS) {
        (void)sd_radio_session_close();
        return err_code;
      }
      return NRF_SUCCESS;
    }

  • Do you see this error if you keep all the low-level radio code but remove the SoftDevice and timeslot related code, so that you always have full access to the radio etc? If not (or in any case), can you check if this issue also happens if you do everything in a single timeslot?

  • hi,

    I got the code working by resetting radio register in radio callback case.

        // Disable and enable the Radio to reset the RADIO registers, needed from S1xx v8.x
        NRF_RADIO->POWER = ((RADIO_POWER_POWER_Disabled << RADIO_POWER_POWER_Pos) & RADIO_POWER_POWER_Msk);
        NRF_RADIO->POWER = ((RADIO_POWER_POWER_Enabled << RADIO_POWER_POWER_Pos) & RADIO_POWER_POWER_Msk);
    thanks for your support and timely responses.

Reply
  • hi,

    I got the code working by resetting radio register in radio callback case.

        // Disable and enable the Radio to reset the RADIO registers, needed from S1xx v8.x
        NRF_RADIO->POWER = ((RADIO_POWER_POWER_Disabled << RADIO_POWER_POWER_Pos) & RADIO_POWER_POWER_Msk);
        NRF_RADIO->POWER = ((RADIO_POWER_POWER_Enabled << RADIO_POWER_POWER_Pos) & RADIO_POWER_POWER_Msk);
    thanks for your support and timely responses.

Children
No Data
Related