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

nrf52 SAADC - NRFX_SAADC_EVT_DONE never called

using nRF5SDK 160098a08e2

I have the following code:

#define ADC_NOF_SAMPLES 16u
static int16_t s_sample_buffer[ ADC_NOF_SAMPLES ];
static nrf_saadc_channel_config_t const s_adc_channel0 = NRFX_SAADC_DEFAULT_CHANNEL_CONFIG_SE( NRF_SAADC_INPUT_AIN5 );
static void saadc_event_isr( nrfx_saadc_evt_t const *p_event )
{
    volatile uint32_t numOfSamples = 0;
    switch ( p_event->type )
    {
    case NRFX_SAADC_EVT_DONE:  // Event generated when the buffer is filled with samples.
        numOfSamples = p_event->data.done.size;
        break;
    case NRFX_SAADC_EVT_LIMIT: // Event generated after one of the limits is reached.
        break;
    case NRFX_SAADC_EVT_CALIBRATEDONE: // Event generated when the calibration is complete.
        {
            nrfx_err_t err;
            err = nrfx_saadc_buffer_convert( &s_sample_buffer[0], ADC_NOF_SAMPLES );
            APP_ERROR_CHECK(err);
            /*err = nrfx_saadc_sample();
            APP_ERROR_CHECK(err);*/
        }
        break;
    default:
        break;
    }
}

    nrfx_err_t err;
    static nrfx_saadc_config_t const s_saadc_config = {
            .resolution = NRF_SAADC_RESOLUTION_12BIT,
            .oversample = NRF_SAADC_OVERSAMPLE_256X,
            .interrupt_priority = NRFX_SAADC_CONFIG_IRQ_PRIORITY,
            .low_power_mode = false
    };

    // ADC driver is initialized in non-blocking mode, since an event handler is given
    err = nrfx_saadc_init( &s_saadc_config, saadc_event_isr );

    if ( err == NRFX_SUCCESS )
    {
        // Initialize the ADC channel 0
        err = nrfx_saadc_channel_init( 0, &s_adc_channel0 );

        if ( err == NRFX_SUCCESS )
        {
            /*
            * Calibrate the offset with a call to nrfx_saadc_calibrate_offset.
            * You need to wait for the SAADCs DONE event before you can proceed.
            * */
            do
            {
                err = nrfx_saadc_calibrate_offset();
            } while ( err == NRFX_ERROR_BUSY );

            rc = 1u;
        }
    }



I never receive NRFX_SAADC_EVT_DONE. Please advise

  • Hello,

    Could you tell me, are you working out of the provided SAADC example from the SDK?
    Please provide the entire source code, as the root cause for your error might be located elsewhere.

    For future reference, when inserting code as part of a question, I ask that you format it with the code option to significantly increase readability.

    Best regards,
    Karl

  • Hi Karl,

    I am new to these forums, so i will try to figure out how to format the code correctly for the next question i may have Slight smile

    To answer your question.

    No, i do not use the SAADC legacy layer, i have referred to the SAADC driver as described in the infocenter pages:

    after calling nrfx_saadc_calibrate_offset(); i do receive the event NRFX_SAADC_EVT_CALIBRATEDONE.
    But the even though the call to nrfx_saadc_buffer_convert() is successfull it does not seem to do any ADC conversions.
    So I do not receive any NRFX_SAADC_EVT_DONE.
    I cant disclose all of our firmware i am afraid.
    The application i am building upon is based upon the enocean switch example from nrf mesh sdk.
    My application uses a RTOS and consists of several tasks. And one of them is responsible of doing ADC measurements.
    Before the tasks are started i call the following code in main.:
    // Initialize hardware
    ret_code_t err_code;
    
    err_code = nrf_drv_clock_init();
    err_code = nrf_sdh_enable_request();
    err_code = app_timer_init();
    in my app_config.h file i have the following defines in relation to SAADC:
    /** ADC module - SAADC */
    #define SAADC_ENABLED					1
    #define SAADC_CONFIG_RESOLUTION 		2 // 2 = 12 bit
    #define SAADC_CONFIG_OVERSAMPLE			8 // 8 = 256x oversampling
    #define NRFX_SAADC_ENABLED				1
    #define NRFX_SAADC_CONFIG_RESOLUTION 	2 // 2 = 12 bit
    #define NRFX_SAADC_CONFIG_OVERSAMPLE 	8 // 8 = 256x oversampling
  • BardenDK said:
    I am new to these forums, so i will try to figure out how to format the code correctly for the next question i may have

    Great! No problem at all :)

    BardenDK said:
    No, i do not use the SAADC legacy layer, i have referred to the SAADC driver as described in the infocenter pages

    You are in fact enabling the legacy layer, in your app_config.h(SAADC_* applies to the legacy layer). So this might be unintentional?
    Have you taken a look at the provided SAADC example that is provided in the SDK, for reference on how to setup and use the SAADC?

    BardenDK said:
    I cant disclose all of our firmware i am afraid.

    Would you like me to convert your ticket to a private ticket, only viewable by us here as Nordic?
    It would make debugging significantly easier for us, if we have the complete code to look at - but it is of course up to you if you are willing to share it.

    With the code you have provided, it is impossible for me to say anything for certain about the root cause for your error.

    BardenDK said:
    But the even though the call to nrfx_saadc_buffer_convert() is successfull it does not seem to do any ADC conversions.

    How are you attempting to access these conversions? Does the call return without error, and if so; what is placed in the buffer after the call?

    Furthermore, it seems like you do not set your SAADC IRQ priority. Is this intentional?

    Best regards,
    Karl

     

  • You are in fact enabling the legacy layer, in your app_config.h(SAADC_* applies to the legacy layer). So this might be unintentional?
    Have you taken a look at the provided SAADC example that is provided in the SDK, for reference on how to setup and use the SAADC?

    If i remove the defines from app_config, my application wont compile because of undefined references:

    undefined reference to `nrfx_saadc_buffer_convert'

    So, SAADC_ENABLED must be defined to use the nrfx_saadc_* API.

    Furthermore, it seems like you do not set your SAADC IRQ priority. Is this intentional?

    I do, here:

        nrfx_err_t err;
        static nrfx_saadc_config_t const s_saadc_config = {
        		.resolution = NRF_SAADC_RESOLUTION_12BIT,
        		.oversample = NRF_SAADC_OVERSAMPLE_DISABLED,//NRF_SAADC_OVERSAMPLE_128X,//NRF_SAADC_OVERSAMPLE_256X,
        		.interrupt_priority = NRFX_SAADC_CONFIG_IRQ_PRIORITY,
        		.low_power_mode = false
        };
    
        // ADC driver is initialized in non-blocking mode, since an event handler is given
        err = nrfx_saadc_init( &s_saadc_config, saadc_event_isr );

    How are you attempting to access these conversions? Does the call return without error, and if so; what is placed in the buffer after the call?

    I do not attemt to access the conversions, because I wait for the done event that never happens.

    The calls to the following function report success:

    	case NRFX_SAADC_EVT_CALIBRATEDONE: // Event generated when the calibration is complete.
    		{
    			nrfx_err_t err;
    			err = nrfx_saadc_buffer_convert( &s_sample_buffer[0], ADC_NOF_SAMPLES );
    			APP_ERROR_CHECK(err);
    			err = nrfx_saadc_sample();
    			APP_ERROR_CHECK(err);
    		}
    		break;

    after call to nrfx_saadc_sample(), one measurement is put into the buffer.

    No further measurements are performed it seems.....

  • So I tried to add the following code:

    			nrfx_err_t err;
    			err = nrfx_saadc_buffer_convert( &s_sample_buffer[0], ADC_NOF_SAMPLES );
    			APP_ERROR_CHECK(err);
    			err = nrfx_saadc_sample();
    			APP_ERROR_CHECK(err);
    
    			while(1)
    			{
    				while( nrfx_saadc_is_busy() ) {}
    				err = nrfx_saadc_sample();
    				APP_ERROR_CHECK(err);
    			}

    I never gets past nrfx_saadc_is_busy(). So the SAADC never gets into idle state. What is wrong with my initialization of this module ?

        nrfx_err_t err;
        static nrfx_saadc_config_t const s_saadc_config = {
        		.resolution = NRF_SAADC_RESOLUTION_12BIT,
        		.oversample = NRF_SAADC_OVERSAMPLE_DISABLED,//NRF_SAADC_OVERSAMPLE_128X,//NRF_SAADC_OVERSAMPLE_256X,
        		.interrupt_priority = NRFX_SAADC_CONFIG_IRQ_PRIORITY,
        		.low_power_mode = false
        };
    
        // ADC driver is initialized in non-blocking mode, since an event handler is given
        err = nrfx_saadc_init( &s_saadc_config, saadc_event_isr );
    
        if ( err == NRFX_SUCCESS )
        {
        	// Initialize the ADC channel 0
        	err = nrfx_saadc_channel_init( 0, &s_adc_channel0 );
    
        	if ( err == NRFX_SUCCESS )
        	{
        		/*
        		 * Calibrate the offset with a call to nrfx_saadc_calibrate_offset.
        		 * You need to wait for the SAADCs DONE event before you can proceed.
        		 * */
        		do
        		{
        			/*
    					The SAADC has a temperature dependent offset.
    					Therefore, it is recommended to calibrate the SAADC at least once before use,
    					and to re-run calibration every time the ambient temperature has changed by more than 10 °C.
    					Offset calibration is started by triggering the CALIBRATEOFFSET task, and the CALIBRATEDONE
    					event is generated when calibration is done.
        			 */
        			err = nrfx_saadc_calibrate_offset();
        		} while ( err == NRFX_ERROR_BUSY );
    
        		rc = 1u;
        	}
        }

Related