Hi,
My freertos based application (SDK14.2) calls battery monitoring procedure every few minutes .
I've initialized the SAADC
void BATT_SaadcInit(void) { ret_code_t err_code; nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0); err_code = nrf_drv_saadc_init(NULL, BATT_SaadcCallback); APP_ERROR_CHECK(err_code); err_code = nrf_drv_saadc_channel_init(0, &channel_config); APP_ERROR_CHECK(err_code); } void BATT_Init(BATT_EventCallback_t callback) { ... BATT_SaadcInit(); ... }
Within the function I call
static nrf_saadc_value_t BATT_SamplesBuff[BATT_AVG_FACTOR]; ... static void BATT_BattTimerHandler(TimerHandle_t xTimer) { ret_code_t err_code; err_code = nrf_drv_saadc_buffer_convert(BATT_SamplesBuff, BATT_AVG_FACTOR); APP_ERROR_CHECK(err_code); err_code = nrf_drv_saadc_sample(); APP_ERROR_CHECK(err_code); }
When BATT_AVG_FACTOR ==1 I get the SAADC event handler called immediately.
However when setting BATT_AVG_FACTOR = 2 or more, it is never triggered...
Digging further I've noticed that SAADC_IRQHandler(void) in nrf_drv_saadc.c is called twice (even with BATT_AVG_FACTOR greater than 2).
In the 2nd time its called it follows the following route
void SAADC_IRQHandler(void) { if (nrf_saadc_event_check(NRF_SAADC_EVENT_END)) // Enters if block, but does not enter the nested if blocks { nrf_saadc_event_clear(NRF_SAADC_EVENT_END); NRF_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_END)); if (!m_cb.low_power_mode || m_cb.conversions_end) // Doesn't enter { nrf_drv_saadc_evt_t evt; evt.type = NRF_DRV_SAADC_EVT_DONE; evt.data.done.p_buffer = (nrf_saadc_value_t *)m_cb.p_buffer; evt.data.done.size = m_cb.buffer_size; if (m_cb.p_secondary_buffer == NULL) { m_cb.adc_state = NRF_SAADC_STATE_IDLE; } else { m_cb.buffer_size_left = m_cb.secondary_buffer_size; m_cb.p_buffer = m_cb.p_secondary_buffer; m_cb.buffer_size = m_cb.secondary_buffer_size; m_cb.p_secondary_buffer = NULL; if (!m_cb.low_power_mode) { nrf_saadc_task_trigger(NRF_SAADC_TASK_START); } } m_cb.event_handler(&evt); m_cb.conversions_end = false; } } if (m_cb.low_power_mode && nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED)) // Does NOT enter { nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED); NRF_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_STARTED)); if (m_cb.buffer_size_left > m_cb.active_channels) { // More samples to convert than for single event. m_cb.buffer_size_left -= m_cb.active_channels; nrf_saadc_buffer_init((nrf_saadc_value_t *)&m_cb.p_buffer[m_cb.buffer_size - m_cb.buffer_size_left], m_cb.active_channels); } else if ((m_cb.buffer_size_left == m_cb.active_channels) && (m_cb.p_secondary_buffer != NULL)) { // Samples to convert for one event, prepare next buffer. m_cb.conversions_end = true; m_cb.buffer_size_left = 0; nrf_saadc_buffer_init((nrf_saadc_value_t *)m_cb.p_secondary_buffer, m_cb.active_channels); } else if (m_cb.buffer_size_left == m_cb.active_channels) { // Samples to convert for one event, but no second buffer. m_cb.conversions_end = true; m_cb.buffer_size_left = 0; } nrf_saadc_event_clear(NRF_SAADC_EVENT_END); nrf_saadc_task_trigger(NRF_SAADC_TASK_SAMPLE); } if (nrf_saadc_event_check(NRF_SAADC_EVENT_CALIBRATEDONE)) // Does NOT enter { nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE); NRF_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_CALIBRATEDONE)); m_cb.adc_state = NRF_SAADC_STATE_IDLE; nrf_drv_saadc_evt_t evt; evt.type = NRF_DRV_SAADC_EVT_CALIBRATEDONE; m_cb.event_handler(&evt); } if (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED)) // Going into the else block { nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED); NRF_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_SAADC_EVENT_STOPPED)); m_cb.adc_state = NRF_SAADC_STATE_IDLE; } else // Getting into here but do nothing as limit_flags == 0 { uint32_t limit_flags = m_cb.limits_enabled_flags; uint32_t flag_idx; nrf_saadc_event_t event; while (limit_flags) { flag_idx = __CLZ(limit_flags); limit_flags &= ~((1UL << 31) >> flag_idx); event = FLAG_IDX_TO_EVENT(flag_idx); if (nrf_saadc_event_check(event)) { nrf_saadc_event_clear(event); nrf_drv_saadc_evt_t evt; evt.type = NRF_DRV_SAADC_EVT_LIMIT; evt.data.limit.channel = LIMIT_EVENT_TO_CHANNEL(event); evt.data.limit.limit_type = LIMIT_EVENT_TO_LIMIT_TYPE(event); NRF_LOG_DEBUG("Event limit, channel: %d, limit type: %d.", evt.data.limit.channel, evt.data.limit.limit_type); m_cb.event_handler(&evt); } } } }
What am I missing here ?
Thanks