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