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

Porting Project from SDK12.2 to SDK14.1, SAADC issue

I had the following setup, two app_timers triggering blocking SAADC reads in the callback functions

app_timer 1000ms triggering 1 Blocking SAADC read (For battery service, default Bluetooth SIG battery service)

ret_code_t err_code;
nrf_saadc_value_t  data_buffer = 0;

nrf_saadc_channel_config_t  channel_config1 =
    NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4);

err_code = nrf_drv_saadc_init(NULL,battery_level_adc_event_handler );
APP_ERROR_CHECK(err_code);

err_code = nrf_drv_saadc_channel_init(SAADC_CHANNEL_BAS, &channel_config1);
APP_ERROR_CHECK(err_code);

err_code = nrf_drv_saadc_sample_convert(SAADC_CHANNEL_BAS, &data_buffer);
APP_ERROR_CHECK(err_code);

nrf_drv_saadc_channel_uninit(SAADC_CHANNEL_BAS);
nrf_drv_saadc_uninit();

//static nrf_saadc_value_t prev_data_buffer = 500;
float battery_in_percent = 0.0;

if(data_buffer > 145)
{
	battery_in_percent = slope * (data_buffer-147);
	if(battery_in_percent > 100)
	{
		battery_in_percent = 100;
	}
	NRF_LOG_RAW_INFO("Battery in percent %d\n", (uint8_t)battery_in_percent);
	//prev_data_buffer = data_buffer;
}
else
{
	battery_in_percent = 0;
}

err_code = ble_bas_battery_level_update(m_bas, (uint8_t)battery_in_percent);           //Send the battery level over BLE

if ((err_code != NRF_SUCCESS) &&
    (err_code != NRF_ERROR_INVALID_STATE) &&
    (err_code != NRF_ERROR_RESOURCES) &&
    (err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING)
   )
{
    NRF_LOG_ERROR("Battery Service Error: %u\n", err_code);
	APP_ERROR_HANDLER(err_code);                                               //Assert on error
}

app_timer 1000ms triggering 5 Blocking SAADC reads (custom service characteristic), 5 IR sensor connected to multiplexer connected to AIN5, write_linear_array() selects which pin on the multiplexer is being used

    ret_code_t err_code;
enable_linear_array();

nrf_saadc_channel_config_t	channel_config =
	NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN5);

err_code = nrf_drv_saadc_init(NULL, saadc_callback);
APP_ERROR_CHECK(err_code);

err_code = nrf_drv_saadc_channel_init(SAADC_CHANNEL, &channel_config);
APP_ERROR_CHECK(err_code);

config_linear_array_out();
uint8_t sample_counter = 0;
nrf_saadc_value_t  data_buffer=0 ;
uint8_t readINflags = 0;

/* Sample 1 */
write_linear_array(sample_counter);
err_code = nrf_drv_saadc_sample_convert(0, &data_buffer);
APP_ERROR_CHECK(err_code);
if(err_code)
	return err_code;

if(data_buffer > IR_SENSOR_THRESHOLD){
	readINflags |= 0b00000001;
}

/* Sample 2*/
sample_counter++;
write_linear_array(sample_counter);
err_code = nrf_drv_saadc_sample_convert(0, &data_buffer);
APP_ERROR_CHECK(err_code);

if(data_buffer > IR_SENSOR_THRESHOLD){
	readINflags |= 0b00000010;
}

/* Sample 3 */
sample_counter++;
write_linear_array(sample_counter);
err_code = nrf_drv_saadc_sample_convert(0, &data_buffer);
APP_ERROR_CHECK(err_code);

if(data_buffer > IR_SENSOR_THRESHOLD){
	readINflags |= 0b00000100;
}

/* Sample 4 */
sample_counter++;
write_linear_array(sample_counter);

err_code = nrf_drv_saadc_sample_convert(0, &data_buffer);
APP_ERROR_CHECK(err_code);

if(data_buffer > IR_SENSOR_THRESHOLD){
	readINflags |= 0b00001000;
}

/* Sample 5 */
sample_counter++;
write_linear_array(sample_counter);

err_code = nrf_drv_saadc_sample_convert(0, &data_buffer);
APP_ERROR_CHECK(err_code);

if(data_buffer > IR_SENSOR_THRESHOLD){
	readINflags |= 0b00010000;
}

disable_linear_array();
nrf_drv_saadc_channel_uninit(SAADC_CHANNEL);
nrf_drv_saadc_uninit();

The battery measurement app_timer is always running, the other one is on demand (if notify happens on custom characteristic) Both characteristics have read and notify properties. For the custom characteristic a read will the code above directly outside the app_timer.

These worked fine with SDK12.2 and SDK13, however recently I started porting the project to SDK14.1 and the following is happening. When debugging there are no errors and I can read the characteristics fine via BLE or occasionally I get an unknown fault at 0x000128A0 or 0x00014CCC. When compiled with -O3 and not in debug, it runs for a while then goes into a reset loop (keeps resetting) after running for a while or after trying to read the custom characteristic.

With app_timers still running and the SAADC portions completely commented out [and the SAADC disabled as module] I have no issues.

  • Are you pausing the always-running timer when you do the on-demand sampling of the SAADC, or make sure that the other timer handler does not try to initialize the SAADC when it is already initialized by the other? If the chip restarts, it have ended up in the error handler, where the default recovery is to reset the chip. If you enable NRF_LOG and defined the preprocessor symbol DEBUG, the error handler in SDK 14.1 should print the error code and info about that caused the function, if you are not able to reproduce it while debugging.

  • Hey Jørgen, I have NRF_LOG enabled with DEBUG, and have SAADC log enabled. I never get error returns from the SAADC log. The weird thing that happens is before the reset problem happens, the SAADC will return really high or really low reading before the reset. Like a reading of 15.

    And no I do not have a way of knowing if the the SAADC is already initialized, should I use a mutex or similar to protect the SAADC as a resource?

    Another weird thing is this exact setup gave me no problems with previous SDKs

  • I just noticed something APP_TIMER_CONFIG_OP_QUEUE_SIZE was 20 in my last project it was changed to 10 when I changed my SDK. I changed it back to 20 and now it seems working and also put some protection to see if SAADC is already in use. I have other timers didnt mention it above which dont use the SAADC.

    Now it runs fine in -O0 DEBUG with the debugger attached. If I try to run -O0 DEBUG without the debugger attached I get this

    <error> app: ERROR 3735928559 [Unknown error code] at ../../nRF5_SDK_14.1.0_1dda907/components/drivers_nrf/pwm/nrf_drv_pwm.c:375
    

    I am using the PWM to blink an LED, which indicates if it is shutting down or powered on

    With -O3 it still exhibits the reset behavior

  • I tried with the DEBUG compiler flag with -03 but it still resets with any info, as soon as I start IR sensors notification. this is what I see

    Triggering battery level update...
    <info> saadc: Function: nrf_drv_saadc_init, error code: NRF_SUCCESS.
    <info> saadc: Channel initialized: 1.
    <info> saadc: Function: nrf_drv_saadc_channel_init, error code: NRF_SUCCESS.
    <info> saadc: Conversion value: 7, channel: 1.
    <warning> saadc: Function: nrf_drv_saadc_sample_convert, error code: NRF_SUCCESS.
    <info> saadc: Channel denitialized: 1.
    <info> saadc: Function: nrf_drv_saadc_channel_uninit, error code: NRF_SUCCESS.
    <info> app: Connected.
    

    2nd run without connecting

    RAM Start: 20002140
    BLE init
    <info> app: Fast advertising.
    After init
    Triggering battery level update...
    <info> saadc: Function: nrf_drv_saadc_init, error code: NRF_SUCCESS.
    <info> saadc: Channel ini▒
    

    After I connect and start notifications it resets with no info after these lines. If I just let it run without connecting it resets on its own after a small time. By the way the conversion value is very small its normally around 400ish for the battery when it is working correctly

    SAADC module disabled, all SAADC code commented out, -O0 DEBUG & -O3 ok

    SAADC module enabled, but all SAADC code commented out, -O0 DEBUG & -O3 ok

    SAADC module enabled, only battery SAADC code un-commented , -O0 DEBUG Ok, -O3 reset forever

    I will try to use non-blocking instead to see what happends

  • A note on the SAADC conversion value, with -O3 after flashing the program it will give the expected value but after one reset it gives a wrong value

    ** After -O3 Flash (right after flashing it runs fine), value around 400ish

    Triggering battery level update...
    <info> saadc: Function: nrf_drv_saadc_init, error code: NRF_SUCCESS.
    <info> saadc: Channel initialized: 0.
    <info> saadc: Function: nrf_drv_saadc_channel_init, error code: NRF_SUCCESS.
    <info> saadc: Conversion value: 437, channel: 0.
    <warning> saadc: Function: nrf_drv_saadc_sample_convert, error code: NRF_SUCCESS.
    <info> saadc: Channel denitialized: 0.
    <info> saadc: Function: nrf_drv_saadc_channel_uninit, error code: NRF_SUCCESS.
    

    *** After reset of -03 Flash (after resetting once, the SAADC conversion values stay like this), value around 8ish or 65530ish

    Triggering battery level update...
    <info> saadc: Function: nrf_drv_saadc_init, error code: NRF_SUCCESS.
    <info> saadc: Channel initialized: 0.
    <info> saadc: Function: nrf_drv_saadc_channel_init, error code: NRF_SUCCESS.
    <info> saadc: Conversion value: 8, channel: 0.
    <warning> saadc: Function: nrf_drv_saadc_sample_convert, error code: NRF_SUCCESS.
    <info> saadc: Channel denitialized: 0.
    <info> saadc: Function: nrf_drv_saadc_channel_uninit, error code: NRF_SUCCESS.
    
    Triggering battery level update...
    <info> saadc: Function: nrf_drv_saadc_init, error code: NRF_SUCCESS.
    <info> saadc: Channel initialized: 0.
    <info> saadc: Function: nrf_drv_saadc_channel_init, error code: NRF_SUCCESS.
    <info> saadc: Conversion value: 65530, channel: 0.
    <warning> saadc: Function: nrf_drv_saadc_sample_convert, error code: NRF_SUCCESS.
    <info> saadc: Channel denitialized: 0.
    <info> saadc: Function: nrf_drv_saadc_channel_uninit, error code: NRF_SUCCESS.
    
Related