Hello,
I recently tested the nRF51822 with a non-Nordic BLE devices and encountered some problems. When testing with Nordic the connection is maintained with no problem, but while testing using TI's dongle or an android phone the connection is getting dropped. I traced the problem down to an ADC event for the battery read. It seems the ADC IRQ is causing a slight delay which the nordic pca100000 dongle can compensate for but other vendor devices do not.
soft device s110 6.0.0 sdk 5.1.0 target board pac10001 v2.2.0 2014.06
I added some debug signals on gpio to the radio_notification_event and I see 1 mS delay in the radio notification after the ADC event.
If I remove the TASKS_START=1 from the battery_start() routine the connection does not drop, therefore the ADC is certainly related to the problem.
This problem happens even when the connection interval is increased to 500 or slave latency is increased to 1.
/@brief Function for initializing the Radio Notification event handler. */ static void radio_notification_init(void) { uint32_t err_code; err_code = ble_radio_notification_init(NRF_APP_PRIORITY_HIGH, NRF_RADIO_NOTIFICATION_DISTANCE_4560US, on_radio_active_evt); APP_ERROR_CHECK(err_code); } Here is some relevant code: /@brief Function for initializing the Radio Notification event handler. */ static uint8_t radio_pending; void on_radio_active_evt(bool radio_active) { radio_pending = radio_active; if (radio_active) { nrf_gpio_pin_set(DEBUG_LED_1); scale_timer_started=0; } else { //radio not active nrf_gpio_pin_clear(DEBUG_LED_1); if (do_battery_read) { battery_start(); do_battery_read=0; } }
static void batt_meas_timeout_handler(void * p_context) { UNUSED_PARAMETER(p_context); if (radio_pending ) { do_battery_read=1; } else { battery_start(); do_battery_read=0; } }
/**@brief Function for making the ADC start a battery level conversion. */ void battery_start(void) { uint32_t err_code; nrf_gpio_pin_set(DEBUG_LED_0); while(NRF_ADC->BUSY) {} // Configure ADC NRF_ADC->INTENSET = ADC_INTENSET_END_Msk; NRF_ADC->CONFIG = (ADC_CONFIG_RES_8bit << ADC_CONFIG_RES_Pos) | (BATTERY_MEASURE_INPSEL << ADC_CONFIG_INPSEL_Pos) | (BATTERY_MEASURE_REFSEL << ADC_CONFIG_REFSEL_Pos) | (BATTERY_MEASURE_PSEL << ADC_CONFIG_PSEL_Pos) | (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos); NRF_ADC->EVENTS_END = 0; NRF_ADC->ENABLE = ADC_ENABLE_ENABLE_Enabled;
// Enable ADC interrupt
err_code = sd_nvic_ClearPendingIRQ(ADC_IRQn);
APP_ERROR_CHECK(err_code);
err_code = sd_nvic_SetPriority(ADC_IRQn, NRF_APP_PRIORITY_LOW);
APP_ERROR_CHECK(err_code);
err_code = sd_nvic_EnableIRQ(ADC_IRQn);
APP_ERROR_CHECK(err_code);
NRF_ADC->EVENTS_END = 0; // Stop any running conversions.
NRF_ADC->TASKS_START = 1;
}
void ADC_IRQHandler(void) { if (NRF_ADC->EVENTS_END != 0) { uint16_t adc_result; NRF_ADC->EVENTS_END = 0; adc_result = NRF_ADC->RESULT; NRF_ADC->TASKS_STOP = 1; #if 0 battery_convert_adc_to_level(adc_result); scale_adc_config(); #endif nrf_gpio_pin_clear(DEBUG_LED_0); }