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

Error to use ble_advertising_advdata_update() in timer callback function

Hello,

I am using nrf52840 and SDK 16.0.0

I have integrated two examples, ble_app_template and nrf_calendar example. Now I have a problem. I wanna update the manufacturer specific data every 1 sec, so I put the advertisement update function(advertisement_update()) inside the callback function so that the advertisement_update() can be called every 1 sec. My code looks like below. (advertising_init() , advertisement_update(), callback function, and main())

/**@brief Function for initializing the Advertising functionality.
 */
static void advertising_init(void)
{
    ret_code_t             err_code;
    ble_advertising_init_t init;     // Struct containing advertising parameters
    // Build advertising data struct to pass into @ref ble_advertising_init.
    memset(&init, 0, sizeof(init));
    
    ble_advdata_manuf_data_t                  manuf_data; // Variable to hold manufacturer specific data
    uint8_t eg_data[]                         = {0x12, 0x34, 0x56};  // Our data to advertise
    
    manuf_data.company_identifier             = 0x0059;   // Nordics company ID
    manuf_data.data.p_data                    = eg_data;
    manuf_data.data.size                      = sizeof(eg_data);
    init.advdata.p_manuf_specific_data        = &manuf_data;
    
    init.advdata.name_type               = BLE_ADVDATA_SHORT_NAME;  // Use a shortened name
    init.advdata.short_name_len          = 5; // Advertise only first 8 letters of name
    init.advdata.include_appearance      = false;
    init.advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
    init.advdata.uuids_complete.p_uuids  = m_adv_uuids;

    init.config.ble_adv_fast_enabled  = true;
    init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
    init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;

    init.evt_handler = on_adv_evt;

    err_code = ble_advertising_init(&m_advertising, &init);
    APP_ERROR_CHECK(err_code);

    ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}


/**@ Function for updating Timestamp data **/
static void advertising_update(void)
{
    ret_code_t             err_code;

    static ble_advdata_t new_data; // SDK 16.x.x implementation is similar to advertising_init

    // Variables used for manufacturer specific data
    ble_advdata_manuf_data_t manuf_data_2;
    uint8_t                  timestamp_data[4];
    
    // Encoding the timestamp 
    uint8_t *time_ptr = timestamp_encode(nrf_cal_get_time()->tm_mon,
                                         nrf_cal_get_time()->tm_mday,
                                         nrf_cal_get_time()->tm_hour,
                                         nrf_cal_get_time()->tm_min,
                                         nrf_cal_get_time()->tm_sec);
                            
    // Encoded timestamp into the data buffer.
    timestamp_data[0] = *(time_ptr);
    timestamp_data[1] = *(time_ptr+1);
    timestamp_data[2] = *(time_ptr+2);
    timestamp_data[3] = *(time_ptr+3);
    
    
    manuf_data_2.company_identifier  = 0x0059;
    manuf_data_2.data.p_data         = timestamp_data; 
    manuf_data_2.data.size           = sizeof(timestamp_data);

    new_data.p_manuf_specific_data   = &manuf_data_2;
    
    new_data.name_type               = BLE_ADVDATA_SHORT_NAME;
    new_data.short_name_len          = 5;
    new_data.include_appearance      = false;
    new_data.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    new_data.uuids_complete.uuid_cnt = 0;
    new_data.uuids_complete.p_uuids  = m_adv_uuids;
    
    //SDK16.x.x implementation will handle all buffering and encoding inside the update function
    err_code = ble_advertising_advdata_update(&m_advertising, &new_data, NULL);  
    APP_ERROR_CHECK(err_code);

}

// Function to call back every 1 sec 
void calendar_stamp_update()
{
    advertising_update();
    
    if(run_time_updates)
    {
        print_current_time();
        
    }
    
}

// Main function
int main(void)
{   
    bool erase_bonds;
    
    /** Calendar example merging starts from here **/
    uint8_t uart_byte;
    uint32_t year, month, day, hour, minute, second;
    NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
    NRF_CLOCK->TASKS_HFCLKSTART = 1;
    while(NRF_CLOCK->EVENTS_HFCLKSTARTED == 0);
    
    
    nrf_cal_init();
    nrf_cal_set_callback(calendar_stamp_update, 1);
    uart_init();
    
    /** Ble example code starts from here **/
    // Initialize.
    //log_init();
    timers_init();
    buttons_leds_init(&erase_bonds);
    power_management_init();
    ble_stack_init();
    gap_params_init();
    gatt_init();
    advertising_init();
    
    services_init();
    conn_params_init();
    peer_manager_init();
    
    // Start execution.
    //NRF_LOG_INFO("Template example started.");
    application_timers_start();
    advertising_start(erase_bonds);
    
    /** Calendar example **/
    printf("\r\nCalendar demo\r\n\n");
    printf("s - Set time\r\n");
    printf("g - Get time\r\n");
    printf("r - Run continuous time updates\r\n\n");
    
    while (true)
    {
        if(app_uart_get(&uart_byte) == NRF_SUCCESS)
        {
            switch(uart_byte)
            {
                case 's':
                    run_time_updates = false;
                
                    year = (uint32_t)uart_get_parameter("Enter year", 1970, 2100);
                    month = (uint32_t)uart_get_parameter("Enter month", 0, 11);
                    day = (uint32_t)uart_get_parameter("Enter day", 1, 31);
                    hour = (uint32_t)uart_get_parameter("Enter hour", 0, 23);
                    minute = (uint32_t)uart_get_parameter("Enter minute", 0, 59);
                    second = (uint32_t)uart_get_parameter("Enter second", 0, 59);
                    
                    nrf_cal_set_time(year, month, day, hour, minute, second);
                    
                    printf("Time set: ");
                    printf("%s", nrf_cal_get_time_string(false));
                    printf("\r\n\n");
                    break;
                
                case 'g':
                    print_current_time();
                    
                    //advertising_update_mfg_data();
                    break;

                case 'r':
                    run_time_updates = !run_time_updates;
                    printf(run_time_updates ? "Time updates on\r\n" : "Time updates off\r\n");
                    
                    break;
                
               
            }
        }
    }

    
  
    // Enter main loop.
    for (;;)
    {
        idle_state_handle();
    }
}

Problem #1

Whenever I reboot and try to execute nrf_set_callback() inside main(), it stops running and always returns NRF_BREAKPOINT_COND. What more confused me is when I put the advertisement_update() on the just main function (not inside the callback) it updates the data without any error.

void nrf_cal_set_callback(void (*callback)(void), uint32_t interval)
{
    
    // Set the calendar callback, and set the callback interval in seconds
    cal_event_callback = callback;
    m_rtc_increment = interval;
    m_time += CAL_RTC->COUNTER / 8;
    CAL_RTC->TASKS_CLEAR = 1;
    CAL_RTC->CC[0] = interval * 8;  
    
}

Problem #2

When I tried to merge the two examples before, I had to change the RTC setting in nrf_calendar example from RTC0 to RTC2, because RTO0 was already used by SoftDevice in ble_app_template example. I was trying to use RTC1 so I did like below in nrf_calendar.h

#define CAL_RTC                 NRF_RTC1
#define CAL_RTC_IRQn            RTC1_IRQn
#define CAL_RTC_IRQHandler      RTC1_IRQHandler
#define CAL_RTC_IRQ_Priority    3

but the compile failed like below. I have no idea what that means. I appreciate if you could you explain it to me?

Always thanks to Nordic support team. Thanks !!

Parents
  • Hi

    1. Do you call nrf_set_callback() or nrf_cal_set_callback() in your main function? The fact that it is okay to update the advertisement means that one of the other components within the callback function is causing the breakpoint.

    2. This means that you're trying to use RTC1 more than once in your application. I think this is because the app_timer uses RTC1, so you have to use RTC2 instead.

    Best regards,

    Simon

Reply
  • Hi

    1. Do you call nrf_set_callback() or nrf_cal_set_callback() in your main function? The fact that it is okay to update the advertisement means that one of the other components within the callback function is causing the breakpoint.

    2. This means that you're trying to use RTC1 more than once in your application. I think this is because the app_timer uses RTC1, so you have to use RTC2 instead.

    Best regards,

    Simon

Children
No Data
Related