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

nrfx_saadc_irq_handler not getting triggered

Hi ,

I am using saadc to measure battery voltage i m using the sample example given as reference ble_app_proximity/

I am doing adc_configuration in one file and triggering nrf_drv_saadc_sample() from different file in this case alone  nrfx_saadc_irq_handler is not getting triggered

if i call the nrf_drv_saadc_sample() from same file everything is working fine.

Could you help me identify why this is happening?

SDK version  15.2

nRF52840

Parents
  • I m not calling it as part of bas_init() i am calling it in the BLE_BAS_EVT_NOTIFICATION_ENABLED event

    static void bas_evt_handler(ble_bas_t * p_ess_service, ble_bas_evt_t * p_evt)
    {
    uint32_t err_code;
    (void)p_ess_service;
    switch (p_evt->evt_type)
    {
    case BLE_BAS_EVT_NOTIFICATION_ENABLED:
    // Start battery timer
    battery_level_update();
    break;

    case BLE_BAS_EVT_NOTIFICATION_DISABLED:
    break;
    default:
    // No implementation needed.
    break;
    }


    int8_t battery_level_update(void)
    {
    ret_code_t err_code;
    static bool is_adc_configured = false;

    if (!is_adc_configured)
    {
    err_code = adc_configure();
    is_adc_configured = true;
    if (NRF_SUCCESS != err_code)
    {
    return -1;
    }

    }
    err_code = nrf_drv_saadc_sample();

    while (!adc_transfer_done)//updated in adc_event_handler
    ;

    *bat_status_percent = batt_status_percentage;
    *bat_status_mv = batt_status_in_milli_volts;

    if (NRFX_SUCCESS == err_code)
    {
    return 0;
    }
    return -1;
    }

Reply
  • I m not calling it as part of bas_init() i am calling it in the BLE_BAS_EVT_NOTIFICATION_ENABLED event

    static void bas_evt_handler(ble_bas_t * p_ess_service, ble_bas_evt_t * p_evt)
    {
    uint32_t err_code;
    (void)p_ess_service;
    switch (p_evt->evt_type)
    {
    case BLE_BAS_EVT_NOTIFICATION_ENABLED:
    // Start battery timer
    battery_level_update();
    break;

    case BLE_BAS_EVT_NOTIFICATION_DISABLED:
    break;
    default:
    // No implementation needed.
    break;
    }


    int8_t battery_level_update(void)
    {
    ret_code_t err_code;
    static bool is_adc_configured = false;

    if (!is_adc_configured)
    {
    err_code = adc_configure();
    is_adc_configured = true;
    if (NRF_SUCCESS != err_code)
    {
    return -1;
    }

    }
    err_code = nrf_drv_saadc_sample();

    while (!adc_transfer_done)//updated in adc_event_handler
    ;

    *bat_status_percent = batt_status_percentage;
    *bat_status_mv = batt_status_in_milli_volts;

    if (NRFX_SUCCESS == err_code)
    {
    return 0;
    }
    return -1;
    }

Children
  • Thank you for clarifying.

    What is the content of your adc_configure function?
    Is the error code it returns one returned by for example saadc_init, or channel_init?
    If so, why are you not passing it to an APP_ERROR_CHECK? This would let you know if it failed.
    In general, you should always pass a returned error code to an APP_ERROR_CHECK, and then rather implement specific error handling in the APP_ERROR_CHECK, rather, if that is desired.

    I think your problem here lies with the line while (!adc_transfer_done)//updated in adc_event_handler.
    Here, you are already in an event handler, and you are asking to wait in the event handler for another event handler to finish processing.
    What is the interrupt priority of the SAADC?
    I suspect that the SAADC's interrupt priority is equal to or lower than the BAS event - which ensures that the SAADC can not interrupt the BAS event, and thus the BAS event can not complete.
    I recommend that you do not make these kinds of while waiting loops within event handlers, it is not an advisable practice.

    Furthermore, you might be waiting forever here either way, since you are not checking the error code of the nrf_drv_saadc_sample call - which might have failed. If it fails, you will not know about it, and be stuck forever waiting for the sampling to complete.

    Please remove this, and see if it resolves your issue.

    Looking forward to hearing if this resolves your issue! 

    Best regards,
    Karl

  • adc_configure() calls these functions  saadc_init(), saadc_channel_init() and saadc_buffer_convert() and it returns success 

    nrf_drv_saadc_sample() also returns success but event handler is not triggered at all 

    I have configured the priority like below

    #define NRFX_SAADC_CONFIG_IRQ_PRIORITY 6 

    #define BLE_BAS_BLE_OBSERVER_PRIO 2

    as you said if i call this adc_configure()  and nrf_drv_saadc_sample()  other than bas event it works

    Also after configuring and reading my first ADC sample if i call nrf_drv_saadc_sample()  in bas event it works as expected the adc event is getting triggered

    whether the priority issue comes only for first sample? 

  • john.ashok said:

    I have configured the priority like below

    #define NRFX_SAADC_CONFIG_IRQ_PRIORITY 6 

    #define BLE_BAS_BLE_OBSERVER_PRIO 2

    Please see the Interrupt Priority section of the SoftDevice specification for details about the available priority levels.

    john.ashok said:
    nrf_drv_saadc_sample() also returns success but event handler is not triggered at all 

    That is good. Could you confirm for me that you have added an APP_ERROR_CHECK to all error codes returned by NRF5 SDK functions?

    john.ashok said:
    as you said if i call this adc_configure()  and nrf_drv_saadc_sample()  other than bas event it works

    Thank you for mentioning this, this is very helpful for the debugging.

    john.ashok said:

    Also after configuring and reading my first ADC sample if i call nrf_drv_saadc_sample()  in bas event it works as expected the adc event is getting triggered

    whether the priority issue comes only for first sample? 

    By this, do you mean that it works as expected if you moved the adc_configure function call outside of the BAS event, and then just called _sample as part of the BAS event handler?
    Did you change the waiting while() loop in the BAS event handler, or implement the waiting differently?

    Best regards,
    Karl

  • Could you confirm for me that you have added an APP_ERROR_CHECK to all error codes returned by NRF5 SDK functions?

    Yes i have used APP_ERROR_CHECK 

    By this, do you mean that it works as expected if you moved the adc_configure function call outside of the BAS event, and then just called _sample as part of the BAS event handler?

    I have moved adc_configure outside BAS event and first call of _sample is also done outside BAS event.

    after that if i call _sample in BAS event it works fine.

    But if i call _sample in BAS event without calling it before it hangs(event not getting triggered)

    means first call of _sample has to be somewhere outside BAS event

    i m sure about the why it behaves like that 

    Did you change the waiting while() loop in the BAS event handler, or implement the waiting differently?

    No, for now waiting while() loop is still there

  • john.ashok said:
    Yes i have used APP_ERROR_CHECK
    john.ashok said:
    No, for now waiting while() loop is still there

    Thank you for confirming this.

    john.ashok said:

    I have moved adc_configure outside BAS event and first call of _sample is also done outside BAS event.

    after that if i call _sample in BAS event it works fine.

    But if i call _sample in BAS event without calling it before it hangs(event not getting triggered)

    means first call of _sample has to be somewhere outside BAS event

    i m sure about the why it behaves like that 

    Strange indeed - especially with the low priority assigned to the SAADC.
    Are you certain that 

    To avoid this being an issue at all you may instead link the TASKS_START or TASKS_SAMPLE to your BAS event using PPI. I would recommend that you do so regardless of this issue, since the sampling then will not require CPU interference for each sample taken. In other words, this will allow sampling to continue regardless of what the CPU might be busy with - such as maintaining BLE connections.
    Would this be something you could consider implementing in your project?

    Best regards,
    Karl

Related