Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

NRF_EVT_RADIO_BLOCKED then NRF_ERROR_FORBIDDEN when requesting next earliest timeslot

I'm running into an issue when trying to use the timeslot API for advertising while concurrently scanning. Scanning is using a 100 ms interval with 50 ms window and initialized and started using 

sd_ble_gap_scan_start(&m_scan_param, &m_scan_buffer);

The timeslot API is used to advertise when the radio is idle between scan windows. The relevant timeslot code is:

void timeslot_evt_signal_handler(uint32_t evt_id) {

    switch (evt_id) {
    case NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN:
        break;
    case NRF_EVT_RADIO_SESSION_IDLE:
uint32_t err_code = sd_radio_session_close();
APP_ERROR_CHECK(err_code);
break;
case NRF_EVT_RADIO_SESSION_CLOSED:
break;
case NRF_EVT_RADIO_BLOCKED:
case NRF_EVT_RADIO_CANCELED:
uint32_t err_code = m_request_earliest(NRF_RADIO_PRIORITY_NORMAL, total_distance); // 2-10 times original distance
APP_ERROR_CHECK(err_code);
break;
default:
break;
}
}


static uint32_t m_request_earliest(enum NRF_RADIO_PRIORITY priority, uint32_t timeout_ms) {
    m_btle_timeslot_request.request_type = NRF_RADIO_REQ_TYPE_EARLIEST;
    m_btle_timeslot_request.params.earliest.hfclk = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
    m_btle_timeslot_request.params.earliest.priority = priority;
    m_btle_timeslot_request.params.earliest.length_us = BTLE_ADV_SLOT_LENGTH; // 5500 us;
    m_btle_timeslot_request.params.earliest.timeout_us = timeout_ms * 1000;
    return sd_radio_request(&m_btle_timeslot_request);
}


nrf_radio_signal_callback_return_param_t *timeslot_radio_callback(uint8_t signal_type) {
    switch (signal_type) {
    case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START:
        if (m_timeslot_active_mode & TIMESLOT_MODE_ADV) {
            btle_adv_evt_start(&m_signal_callback_return_param);
        }
        break;

    case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO:
        if (m_timeslot_active_mode & TIMESLOT_MODE_ADV) {
            btle_adv_evt_radio(&m_signal_callback_return_param);
        }
        break;

    case NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0:
        break;
    case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED:
        break;
    case NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED:
        break;
    default:
        break;
    }
    return (&m_signal_callback_return_param);
}

void btle_adv_evt_start(nrf_radio_signal_callback_return_param_t *param) {
    param->params.request.p_next = NULL;
    param->callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE;
}

void btle_adv_evt_radio(nrf_radio_signal_callback_return_param_t *param) {
// Computations for distance removed
param->params.request_type = NRF_RADIO_REQ_TYPE_NORMAL;
param->params.params.normal.hfclk = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED;
param->params.params.normal.priority = NRF_RADIO_PRIORITY_NORMAL;
param->params.params.normal.distance_us = distance;
param->params.params.normal.length_us = BTLE_ADV_SLOT_LENGTH; // 5500 us;
}

Everything works fine if there is no scanning or if distance is a multiple of 100 ms, but timeslot_evt_signal_handler gets a NRF_EVT_RADIO_BLOCKED event for other timing intervals. All of the examples show trying to request the next earliest timeslot when a blocked event occurs (which is what is done here), but that results in a NRF_ERROR_FORBIDDEN response.

What should be the proper handling and/or setup of the timeslots to handle a NRF_EVT_RADIO_BLOCKED event?

Thanks!

Parents
  • After some further investigation, it appears that the second blocked event wasn't from the request next earliest. Two blocked events are happening for the NRF_RADIO_REQ_TYPE_NORMAL request. This causes two immediate requests for the next earliest timeslots, so the the NRF_ERROR_FORBIDDEN occurred. There appears to be a bug in the SDK that's causing two blocked events instead of just one. I was able to work around this by using a flag to prevent two simultaneous timeslot requests.

Reply
  • After some further investigation, it appears that the second blocked event wasn't from the request next earliest. Two blocked events are happening for the NRF_RADIO_REQ_TYPE_NORMAL request. This causes two immediate requests for the next earliest timeslots, so the the NRF_ERROR_FORBIDDEN occurred. There appears to be a bug in the SDK that's causing two blocked events instead of just one. I was able to work around this by using a flag to prevent two simultaneous timeslot requests.

Children
No Data
Related