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!