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

Can't start advertising in timer callback

I want to make my nRF52 turn on every 5 minutes, send data to a device over BLE and go back to sleep. For some reason once I turn on BLE advertising LED1 becomes solid and i can't connect to my device even though nothing is paired with it. Here is my callback:

static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
    uint32_t err_code;
	
    if (int_type == NRF_DRV_RTC_INT_COMPARE0)
    {
      collect_data();

      advertising_start(BLE_ADV_MODE_FAST);
      printf("Waiting for BLE connection\n");
      while(m_conn_handle == BLE_CONN_HANDLE_INVALID) {
        power_manage();
      }
      nrf_delay_ms(2000);
      send_data();
      nrf_delay_ms(2000);

      sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
      m_conn_handle = BLE_CONN_HANDLE_INVALID;
      sd_ble_gap_adv_stop();

      err_code = nrf_drv_rtc_cc_set(&rtc,0,RTC_CC_VALUE_SEC * RTC2_CONFIG_FREQUENCY,true);       //Set RTC compare value.
      APP_ERROR_CHECK(err_code);
      nrf_drv_rtc_counter_clear(&rtc);                               //Clear the RTC counter to start count from zero
    }
}

The while loop is where my code gets stuck. Could anyone help me figure out why? Also, is there a way I can make that while loop time out after 10 seconds so the nRF goes back to sleep. I have set the advertising timeout but would that return from the callback? Thanks!

EDIT:

In response to Aryan's comment, here are more details. I am using RTC2 and have enabled it in the nrf_drv_config.h here:

#define RTC2_ENABLED 1

#if (RTC2_ENABLED == 1)
#define RTC2_CONFIG_FREQUENCY    32768
#define RTC2_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW
#define RTC2_CONFIG_RELIABLE     false

#define RTC2_INSTANCE_INDEX      (RTC0_ENABLED+RTC1_ENABLED)
#endif

I declare and init the RTC timers here:

const  nrf_drv_rtc_t           rtc = NRF_DRV_RTC_INSTANCE(2); /**< Declaring an instance of nrf_drv_rtc for RTC2.

static void lfclk_config(void)
{
    ret_code_t err_code = nrf_drv_clock_init();                        //Initialize the clock source specified in the nrf_drv_config.h file, i.e. the CLOCK_CONFIG_LF_SRC constant
    APP_ERROR_CHECK(err_code);

    nrf_drv_clock_lfclk_request(NULL);
}

static void rtc_config(void)
{
    uint32_t err_code;

    //Initialize RTC instance
    err_code = nrf_drv_rtc_init(&rtc, NULL, rtc_handler);              //Initialize the RTC with callback function rtc_handler. The rtc_handler must be implemented in this applicaiton. Passing NULL here for RTC configuration means that configuration will be taken from the nrf_drv_config.h file.
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_rtc_cc_set(&rtc,0,RTC_CC_VALUE_SEC * RTC2_CONFIG_FREQUENCY,true);           //Set RTC compare value to trigger interrupt. Configure the interrupt frequency by adjust RTC_CC_VALUE and RTC2_CONFIG_FREQUENCY constant in the nrf_drv_config.h file
    APP_ERROR_CHECK(err_code);

    //Power on RTC instance
    nrf_drv_rtc_enable(&rtc);                                          //Enable RTC
}

int main(void) {

  bool erase_bonds;

  // Initialize BLE stack.
  timers_init();
  buttons_leds_init(&erase_bonds);
  ble_stack_init();
  device_manager_init(erase_bonds);
  gap_params_init();
  services_init();
  advertising_init();
  conn_params_init();

  lfclk_config();                                  //Configure low frequency 32kHz clock
  rtc_config();                                    //Configure RTC. The RTC will generate periodic interrupts. Requires 32kHz clock to operate.

  while(1)
  {
      __WFE();                                     //These three commands disable the CPU. CPU will wake up again on any event or interrupt.
      __SEV();
      __WFE();
  }
}

Is there something wrong in the configuration/initialization? Once the rtc handler reaches the loop with power_manage() it just gets stuck and isn't advertising anything with LED1 being on and solid. Thanks!

Parents
  • The problem is the while loop inside the interrupt handler, thereby you are blocking all interrupts at this and lower levels. Therefore you are never getting any ble event (these are usually delivered at APP_IRQ_PRIORITY_LOW level) and so the advertising module can not work properly. Usually the m_conn_handle variable is also changed in an event handler, but due to the fact, that you're blocking these event handlers, this variable will never change.

    To solve this, you should get rid of the while loop, so just start advertising in the rtc handler, and do the the rest when you get the connection event.

  • Awesome thanks! Is the only way to react to the connection event through on_ble_evt? I'd like my code for this action to all be in one place if possible. If not, I could just call a function from on_ble_evt.

Reply Children
No Data
Related