This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

The Saadc of issue of uninit

i init the saadc and uinit saadc ,then init saadc again. my code is below:

err_code = nrf_drv_saadc_init(NULL, saadc_callback);
err_code = nrf_drv_saadc_channel_init(0, &channel_config_se1);
err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool, 1);

 nrf_drv_saadc_uninit();

err_code = nrf_drv_saadc_init(NULL, saadc_callback);
err_code = nrf_drv_saadc_channel_init(0, &channel_config_se1);
err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool, 1);

from now .the err_code is correct .

But when i use nrf_drv_saadc_sample(), geting a error in SAADC_IRQHandler. And this is my callback:

void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
{
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
{
nrf_drv_saadc_buffer_convert(m_buffer_pool,1);
}

In SAADC_IRQHandler, the code enter in below:

if (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED))
{
nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
NRF_LOG_DEBUG("Event: %s.\r\n", (uint32_t)EVT_TO_STR(NRF_SAADC_EVENT_STOPPED));
m_cb.adc_state = NRF_SAADC_STATE_IDLE;
}

if i dont use  nrf_drv_saadc_uninit(),there is greater.

what i can do???

Parents
  • Hello, can you explain what are you trying to achieve? What is your setup MCU, sdk, softdevice? what does the error says? Recently I had problems while using SAADC. I would recommend you to take a look at proximity example. Moreover, do you do temperature calibration?

  • i use the softdevice, sdk is nRF5_SDK_12.3.0_d7731ad.

    my error is that i said in above. 

    when i use saadc,anything is ok. But i wanna uninit the saadc to power down the consumption.

    But when i init saadc in twice more,saadc cant work well. 

     nrf_drv_saadc_sample error is 0x08, That means saadc is not busy.

    i bubeg the code , and i find the code enter if (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED)) in SAADC_IRQHandler.

    why when i init saadc in twice more,the code enter nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED)???

  • What do you mean by this: "the code cant check the stop interrput ,as init some bugs in next init code"? Are you actually checking the error codes from your calls to nrf_drv_saadc_*, or are they only assigned? You say you get error 0x08 when calling nrf_drv_saadc_sample, this indicate that the driver is in IDLE state, normally because no buffer have been setup. You should have received an error code when you called one of the nrf_drv_saadc_* functions.

  • I guess the problem is inside the SAADC_IRQHandler. When using the uninit inside the callback there is a NRF_SAADC_EVENT_STOPPED event created. As the handling of the end event in line 117 (nRF5_SDK_12.3.0_d7731ad) is not terminating the IRQ function, the stop event is handled in line 190, setting the state of the driver to NRF_SAADC_STATE_IDLE after the reinit has been performed in the callback. The next call to nrf_drv_saadc_sample is then creating the invalid state error.

    Solution: In SAADC_IRQHandler use else if to handle each kind of event:

    void SAADC_IRQHandler(void)
    {
        if (nrf_saadc_event_check(NRF_SAADC_EVENT_END))
        {
            nrf_saadc_event_clear(NRF_SAADC_EVENT_END);
            NRF_LOG_DEBUG("Event: %s.\r\n", (uint32_t)EVT_TO_STR(NRF_SAADC_EVENT_END));
    
            if (!m_cb.low_power_mode || m_cb.conversions_end)
            {
                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;
            }
        }
        else if (m_cb.low_power_mode && nrf_saadc_event_check(NRF_SAADC_EVENT_STARTED))
        {
            nrf_saadc_event_clear(NRF_SAADC_EVENT_STARTED);
            NRF_LOG_DEBUG("Event: %s.\r\n", (uint32_t)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);
        }
        else if (nrf_saadc_event_check(NRF_SAADC_EVENT_CALIBRATEDONE))
        {
            nrf_saadc_event_clear(NRF_SAADC_EVENT_CALIBRATEDONE);
            NRF_LOG_DEBUG("Event: %s.\r\n", (uint32_t)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);
        }
        else if (nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED))
        {
            nrf_saadc_event_clear(NRF_SAADC_EVENT_STOPPED);
            NRF_LOG_DEBUG("SAADC IRQ -- Event: %s.\r\n", (uint32_t)EVT_TO_STR(NRF_SAADC_EVENT_STOPPED));
            m_cb.adc_state = NRF_SAADC_STATE_IDLE;
        }
        else
        {
            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: %s.\r\n", evt.data.limit.channel, (uint32_t)EVT_TO_STR(evt.data.limit.limit_type));
                    m_cb.event_handler(&evt);
                }
            }
        }
    }

  • has this issue resolved in SDK 14 or SDK 15?

    Please reply.

  • I am facing the same issue as discussed above. I tried using else if case as suggested above and it solved the problem but I don't want to change the driver and would rather prefer use latest version of SDK if the problem is solved. I am using currently SDK 12. Kindly let me know if there is a SDK version which solves this issue.

  • I do not understand why this issue should apprear. The uninit function disable all interrupts before triggering STOP task. Implementing the workaround proposed by will most likely break the functionality of the abort function (see this thread for more details - this issue have been fixed in SDK 15).

Reply Children
Related