Hi
I'm trying to integrate the iBeacon and Eddystone protocol together. For this I'm using the timeslot to advertise the packets simultaneously. I have successfully integrated the ibeacon and eddystone together and it is working fine.
But the issue comes when i try to update the advertising interval the radio events are getting blocked. Always it advertises for few seconds and then error pops up. While integrating i have fixed a value for the advertising interval and successfully integrated it but when i change the values of advertising interval the issue arises.
The err_code says ERROR 17 [NRF_ERROR_BUSY]
I do have some questions reg the time-slot parameters
1. while requesting the next event or the earliest does the timeout_us event and length_us have any dependencies on advertising interval? Do we need to change those as per adv interval?
2. using the NRF_LOG_INFO has been an issue with the timeslot. ERROR 17 [NRF_ERROR_BUSY] .
I have attached my code, could you please let me know if i'm doing anything wrong
thanks
static enum packet_t packet = IBEACON; int pdu_count = 1; uint32_t m_request_earliest_beacon(enum NRF_RADIO_PRIORITY priority) { m_adv.timeslot_request.request_type = NRF_RADIO_REQ_TYPE_EARLIEST; m_adv.timeslot_request.params.earliest.hfclk = NRF_RADIO_HFCLK_CFG_NO_GUARANTEE; m_adv.timeslot_request.params.earliest.priority = priority; m_adv.timeslot_request.params.earliest.length_us = SLOT_LENGTH; m_adv.timeslot_request.params.earliest.timeout_us = 1000UL; return sd_radio_request(&m_adv.timeslot_request); } nrf_radio_request_t * m_configure_next_event_beacon(uint32_t interval_us) { m_adv.timeslot_request.request_type = NRF_RADIO_REQ_TYPE_NORMAL; m_adv.timeslot_request.params.normal.hfclk = NRF_RADIO_HFCLK_CFG_NO_GUARANTEE; m_adv.timeslot_request.params.normal.priority = NRF_RADIO_PRIORITY_HIGH; m_adv.timeslot_request.params.normal.distance_us = interval_us * 1000; //to ms m_adv.timeslot_request.params.normal.length_us = SLOT_LENGTH; return &m_adv.timeslot_request; } uint32_t m_request_normal(void) { m_adv.timeslot_request.request_type = NRF_RADIO_REQ_TYPE_NORMAL; m_adv.timeslot_request.params.normal.hfclk = NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED; m_adv.timeslot_request.params.normal.priority = NRF_RADIO_PRIORITY_NORMAL; m_adv.timeslot_request.params.normal.distance_us = _ibeacon_ts.adv_interval * 1000 * 2; m_adv.timeslot_request.params.normal.length_us = SLOT_LENGTH; return sd_radio_request(&m_adv.timeslot_request); } /* common config */ static void m_configure_radio() { NRF_RADIO->POWER = 1; NRF_RADIO->PCNF0 = (((1UL) << RADIO_PCNF0_S0LEN_Pos ) & RADIO_PCNF0_S0LEN_Msk) | (((2UL) << RADIO_PCNF0_S1LEN_Pos ) & RADIO_PCNF0_S1LEN_Msk) | (((6UL) << RADIO_PCNF0_LFLEN_Pos ) & RADIO_PCNF0_LFLEN_Msk); NRF_RADIO->PCNF1 = (((RADIO_PCNF1_ENDIAN_Little) << RADIO_PCNF1_ENDIAN_Pos ) & RADIO_PCNF1_ENDIAN_Msk) | (((3UL) << RADIO_PCNF1_BALEN_Pos ) & RADIO_PCNF1_BALEN_Msk) | (((0UL) << RADIO_PCNF1_STATLEN_Pos ) & RADIO_PCNF1_STATLEN_Msk) | ((((uint32_t) 37) << RADIO_PCNF1_MAXLEN_Pos ) & RADIO_PCNF1_MAXLEN_Msk) | ((RADIO_PCNF1_WHITEEN_Enabled << RADIO_PCNF1_WHITEEN_Pos ) & RADIO_PCNF1_WHITEEN_Msk); NRF_RADIO->CRCCNF = (((RADIO_CRCCNF_SKIPADDR_Skip) << RADIO_CRCCNF_SKIPADDR_Pos ) & RADIO_CRCCNF_SKIPADDR_Msk) | (((RADIO_CRCCNF_LEN_Three) << RADIO_CRCCNF_LEN_Pos ) & RADIO_CRCCNF_LEN_Msk); NRF_RADIO->CRCPOLY = 0x0000065b; NRF_RADIO->RXADDRESSES = ((RADIO_RXADDRESSES_ADDR0_Enabled) << RADIO_RXADDRESSES_ADDR0_Pos); NRF_RADIO->SHORTS = ((1 << RADIO_SHORTS_READY_START_Pos) | (1 << RADIO_SHORTS_END_DISABLE_Pos)); NRF_RADIO->MODE = ((RADIO_MODE_MODE_Ble_1Mbit) << RADIO_MODE_MODE_Pos ) & RADIO_MODE_MODE_Msk; NRF_RADIO->TIFS = 150; NRF_RADIO->INTENSET = (1 << RADIO_INTENSET_DISABLED_Pos); NRF_RADIO->PREFIX0 = 0x0000008e; //access_addr[3] NRF_RADIO->BASE0 = 0x89bed600; //access_addr[0:3] NRF_RADIO->CRCINIT = 0x00555555; NVIC_DisableIRQ(RADIO_IRQn); NVIC_EnableIRQ(RADIO_IRQn); } static void periph_radio_evts_clear(void) { NRF_RADIO->EVENTS_ADDRESS = 0; NRF_RADIO->EVENTS_BCMATCH = 0; NRF_RADIO->EVENTS_DEVMATCH = 0; NRF_RADIO->EVENTS_DEVMISS = 0; NRF_RADIO->EVENTS_DISABLED = 0; NRF_RADIO->EVENTS_END = 0; NRF_RADIO->EVENTS_PAYLOAD = 0; NRF_RADIO->EVENTS_READY = 0; NRF_RADIO->EVENTS_RSSIEND = 0; } static void m_handle_start(uint8_t ch1,uint8_t ch2) { // Configure TX_EN on TIMER EVENT_0 NRF_PPI->CH[ch1].TEP = (uint32_t)(&NRF_RADIO->TASKS_TXEN); NRF_PPI->CH[ch1].EEP = (uint32_t)(&NRF_TIMER0->EVENTS_COMPARE[ch2]); NRF_PPI->CHENSET = (1 << ch1); // Configure and initiate radio m_configure_radio(); periph_radio_evts_clear(); NRF_RADIO->TASKS_DISABLE = 1; } static void m_set_adv_ch(uint32_t channel) { if (channel == ADV_CHANNEL_37) { NRF_RADIO->FREQUENCY = FREQ_ADV_CHANNEL_37; NRF_RADIO->DATAWHITEIV = ADV_CHANNEL_37; } if (channel == ADV_CHANNEL_38) { NRF_RADIO->FREQUENCY = FREQ_ADV_CHANNEL_38; NRF_RADIO->DATAWHITEIV = ADV_CHANNEL_38; } if (channel == ADV_CHANNEL_39) { NRF_RADIO->FREQUENCY = FREQ_ADV_CHANNEL_39; NRF_RADIO->DATAWHITEIV = ADV_CHANNEL_39; } } static void m_handle_radio_disabled(enum mode_t mode, uint8_t ch) { switch (mode) { case ADV_RX_CH37: m_set_adv_ch(ADV_CHANNEL_37); NRF_RADIO->TASKS_TXEN = 1; break; case ADV_RX_CH38: m_set_adv_ch(ADV_CHANNEL_38); NRF_TIMER0->TASKS_CLEAR = 1; NRF_TIMER0->CC[ch] = 400; break; case ADV_RX_CH39: m_set_adv_ch(ADV_CHANNEL_39); NRF_TIMER0->TASKS_CLEAR = 1; NRF_TIMER0->CC[ch] = 400; break; default: break; } } void get_eddystone_packet() { NRF_RADIO->PACKETPTR = (uint32_t) m_get_adv_packet_es_uid(); } } static nrf_radio_signal_callback_return_param_t * m_timeslot_callback(uint8_t signal_type) { static nrf_radio_signal_callback_return_param_t signal_callback_return_param; static enum mode_t mode; signal_callback_return_param.params.request.p_next = NULL; signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE; switch (signal_type) { case NRF_RADIO_CALLBACK_SIGNAL_TYPE_START: NRF_LOG_INFO("i'am in SIGNAL_TYPE_START"); switch (packet) { case IBEACON: m_handle_start(7,0); break; case EDDYSTONE : m_handle_start(8,1); break; } mode = ADV_INIT; mode++; break; case NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO: switch (packet) { case IBEACON: if (NRF_RADIO->EVENTS_DISABLED == 1) { NRF_RADIO->EVENTS_DISABLED = 0; m_handle_radio_disabled(mode,0); mode++; NRF_RADIO->PACKETPTR = (uint32_t) m_get_adv_packet_ibeacon(); if (mode == ADV_DONE) { NRF_LOG_INFO("i'am in ibeacon TYPE_RADIO"); NRF_PPI->CHENCLR = (1 << 7); packet = EDDYSTONE; if (m_adv.is_running) { signal_callback_return_param.params.request.p_next = m_configure_next_event_beacon(_ibeacon_ts.adv_interval); signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END; } else { signal_callback_return_param.callback_action =NRF_RADIO_SIGNAL_CALLBACK_ACTION_END; } } } break; case EDDYSTONE: if (NRF_RADIO->EVENTS_DISABLED == 1) { NRF_RADIO->EVENTS_DISABLED = 0; m_handle_radio_disabled(mode,1); mode++; get_eddystone_packet(); if (mode == ADV_DONE) { NRF_LOG_INFO("i'am in eddystone TYPE_RADIO \n"); NRF_PPI->CHENCLR = (1 << 8); packet = IBEACON; if (m_adv.is_running) { signal_callback_return_param.params.request.p_next = m_configure_next_event_beacon(_eddystone.adv_interval); signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END; NRF_RADIO->INTENSET = (0 << RADIO_INTENSET_DISABLED_Pos); } else { signal_callback_return_param.callback_action = NRF_RADIO_SIGNAL_CALLBACK_ACTION_END; } } } break; } break; default: if (_ibeacon_ts.error_handler != NULL) { _ibeacon_ts.error_handler(NRF_ERROR_INVALID_STATE); } if (_eddystone.error_handler != NULL) { _eddystone.error_handler(NRF_ERROR_INVALID_STATE); } break; } return (&signal_callback_return_param); } void app_beacon_sd_evt_signal_handler(uint32_t event) { uint32_t err_code; NRF_LOG_INFO("app_beacon_on_sys_evt: %d\r\n", event); switch (event) { case NRF_EVT_RADIO_SESSION_IDLE: NRF_LOG_INFO("Radio IDLE"); if (m_adv.is_running) { err_code = sd_radio_session_close(); APP_ERROR_CHECK(err_code); if ((err_code != NRF_SUCCESS) && (_ibeacon_ts.error_handler != NULL) && (_eddystone.error_handler != NULL)) { _ibeacon_ts.error_handler(err_code); } m_adv.is_running = false; } break; case NRF_EVT_RADIO_SESSION_CLOSED: NRF_LOG_INFO("Radio closed"); if (m_adv.keep_running) { _beacon_advertising_start(); } break; case NRF_EVT_RADIO_BLOCKED: NRF_LOG_INFO("Radio blocked"); err_code = sd_radio_session_close(); APP_ERROR_CHECK(err_code); uint32_t err_code = sd_radio_session_open(m_timeslot_callback); NRF_LOG_INFO("Timeslot session opened"); if ((err_code != NRF_SUCCESS) && (_ibeacon_ts.error_handler != NULL) && (_eddystone.error_handler != NULL)) { _ibeacon_ts.error_handler(err_code); } // TODO: A proper solution should try again in <block_count> * m_beacon.adv_interval err_code = m_request_earliest_beacon(NRF_RADIO_PRIORITY_HIGH); if ((err_code != NRF_SUCCESS) && (_ibeacon_ts.error_handler != NULL) && (_eddystone.error_handler != NULL)) { _ibeacon_ts.error_handler(err_code); } break; case NRF_EVT_RADIO_CANCELED: // Fall through NRF_LOG_INFO("Timeslot CANCELED"); if (m_adv.keep_running) { // TODO: A proper solution should try again in <block_count> * m_beacon.adv_interval // err_code = m_request_earliest(NRF_RADIO_PRIORITY_HIGH); err_code = m_request_normal(); if ((err_code != NRF_SUCCESS) && (_ibeacon_ts.error_handler != NULL) && (_eddystone.error_handler != NULL)) { _ibeacon_ts.error_handler(err_code); } } break; default: NRF_LOG_INFO("Radio default"); break; } } void _beacon_advertising_start(void) { m_adv.keep_running = true; m_adv.is_running = true; uint32_t err_code = sd_radio_session_open(m_timeslot_callback); NRF_LOG_INFO("Timeslot session opened"); if ((err_code != NRF_SUCCESS) && (_ibeacon_ts.error_handler != NULL) && (_eddystone.error_handler != NULL)) { _ibeacon_ts.error_handler(err_code); } err_code = m_request_earliest_beacon(NRF_RADIO_PRIORITY_HIGH); NRF_LOG_INFO("Timeslot request earliest"); if ((err_code != NRF_SUCCESS) && (_ibeacon_ts.error_handler != NULL) && (_eddystone.error_handler != NULL)) { _ibeacon_ts.error_handler(err_code); } } void _beacon_advertising_stop(void) { m_adv.keep_running = false; }