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

SAADC missing event

Hello.

I have a issue about missing NRF_DRV_SAADC_EVT_DONE event in saadc  handler.

setup is 52832, SDK 15.3.0, S332. enable ANT, BLE

for battery, sensor, I use 2 adc channel.

buffer size is 2.

like ' adc_buffer[2][ADC_BUFFER_SIZE] '.

adc interval is 10ms, adc sampling through ppi

app timer start rtc timer for intrrupt ppi , app timer interval is 9ms, rtc interval is 1ms.

routine is below.

app timer handler -> adc & ppi init -> rtc timer start -> timer rasie interrupt to ppi -> sampling ->  saadc handler -> Done event -> get adc value -> do something -> ppi uninit -> adc uninit

most case, it work very well.

however, sometimes it stop and issue error code 8 : already initalize saadc.

so I checked the cause, when the issue happened, Done event is not raise. it was missed. so it didn't process uninit.

for reducing power consumption, try init & uninit repeatly.

I also tried 'uninit' move to main loop. not callback.

even though, it still issue intermittently.

Could you give me advices?

Thank you in advance.

  • You need to look for the END event, not the DONE event, as the END event signifies that the buffer has been filled and transferred to RAM. The DONE event does not have its interrupt enabled in the driver and will not generate an interrupt. 






  • Thank you.
    I found one more. 

    cause rtc timer interrupt is not working. so saadc sample is not trigger.

    rtc timer interval is 1ms.

    rtc prescaler is 31. (need 1024/s)

    it used nrf_drv_rtc_cc_set(adc_channel, current, current +1, true).

    ex) if current is 0x53, it interrupt count is 0x54.

    is it too tight? 

    thank you

  • If you use PPI you don't need the RTC COMPARE interrupt at all, just the event. 

    And I think you need more than one count after "current". 

    Do you mind sharing your code with some comments? I think you might be on the wrong track. 


  • void adc_init()
    {  
      ret_code_t err_code;     
    
      err_code = nrf_drv_saadc_init(&saadc_config, user_adc_saadc_handler); 
      APP_ERROR_CHECK(err_code);
    
      channel_config.pin_p = (nrf_saadc_input_t)(NRF_SAADC_INPUT_AIN0);
      err_code = nrf_drv_saadc_channel_init(BATTERY_SAADC_CHANNEL, &channel_config); 
      APP_ERROR_CHECK(err_code);
    
      channel_config.pin_p = (nrf_saadc_input_t)(NRF_SAADC_INPUT_AIN1);
      err_code = nrf_drv_saadc_channel_init(ADC_SAADC_CHANNEL, &channel_config); 
      APP_ERROR_CHECK(err_code);
    
      err_code = nrf_drv_saadc_buffer_convert(adc_buffer[0], ADC_BUFFER_SIZE); 
      APP_ERROR_CHECK(err_code);
    
      err_code = nrf_drv_saadc_buffer_convert(adc_buffer[1], ADC_BUFFER_SIZE); 
      APP_ERROR_CHECK(err_code);
    
      adc_sample_event_init();  
    }

    static void adc_config_init(nrf_drv_saadc_config_t *saadc_config, nrf_saadc_channel_config_t *channel_config)
    {
      memset(saadc_config, 0 , sizeof(*saadc_config));
      saadc_config->resolution         = (nrf_saadc_resolution_t)NRFX_SAADC_CONFIG_RESOLUTION; // 12bit
      saadc_config->oversample         = (nrf_saadc_oversample_t)NRFX_SAADC_CONFIG_OVERSAMPLE; // no oversample
      saadc_config->interrupt_priority = NRFX_SAADC_CONFIG_IRQ_PRIORITY; // priority 6
      saadc_config->low_power_mode     = NRFX_SAADC_CONFIG_LP_MODE; // LP mode yes
    
      memset(channel_config, 0 , sizeof(*channel_config));
      channel_config->resistor_p   = NRF_SAADC_RESISTOR_DISABLED;
      channel_config->resistor_n   = NRF_SAADC_RESISTOR_DISABLED;
      channel_config->gain         = NRF_SAADC_GAIN1_6;
      channel_config->reference    = NRF_SAADC_REFERENCE_INTERNAL;
      channel_config->acq_time     = NRF_SAADC_ACQTIME_10US;
      channel_config->mode         = NRF_SAADC_MODE_SINGLE_ENDED;
      channel_config->burst        = NRF_SAADC_BURST_DISABLED;
      channel_config->pin_p        = (nrf_saadc_input_t)(NRF_SAADC_INPUT_AIN0);
      channel_config->pin_n        = NRF_SAADC_INPUT_DISABLED;
    }

    static void adc_sample_event_init()
    {
        ret_code_t err_code;
    
        err_code = nrf_drv_ppi_init(); 
        APP_ERROR_CHECK(err_code);
    
    
        uint32_t timer_compare_event_addr = rtc_get_adc_event_addr(); 
        uint32_t saadc_sample_task_addr   = nrf_drv_saadc_sample_task_get(); 
    
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel, 
                                              timer_compare_event_addr,
                                              saadc_sample_task_addr);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_ppi_channel_enable(m_ppi_channel); // PPI enable
    
        APP_ERROR_CHECK(err_code);
    }

    void rtc_adc_timer_start()
    {
       ret_code_t err_code;
        
       uint32_t current = nrf_drv_rtc_counter_get(&rtc);
       
       err_code = nrf_drv_rtc_cc_set(&rtc, RTC_ADC_CHANNEL, rtc_check_overflow_cc_set(current, ADC_TIMER_INTERVAL), true);
       APP_ERROR_CHECK(err_code);   
    }

    static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
    {  
      switch(int_type)
      {
        case NRF_DRV_RTC_INT_COMPARE0  :  
        
          break;   
    
        case NRF_DRV_RTC_INT_COMPARE1  :  
      
          break;
          
        case NRF_DRV_RTC_INT_COMPARE2  : 
         
          break;
      
        default :
          break;
      }
    }

    more detail, process is below

    I want get adc value interval 10ms.

    to use ppi, need event address. app timer not support func get event address.

    so I used rtc timer. (reason choosing rtc, need low power consumption.)

    app timer interval is 9ms, rtc timer is 1ms (i used prescaler is 31, it meas 1/1024s, almost 1ms)

    after 9ms, app timer handler start rtc timer setting 1ms using nrf_drv_rtc_cc_set function

    passing 1ms, rtc timer send event to ppi, and start measure adc value.

    on rtc handler, there is doing nothing.

    here is issue, sometimes rtc timer is not send event to ppi.

    Thank you.

  • BEN_HB said:
    app timer interval is 9ms, rtc timer is 1ms (i used prescaler is 31, it meas 1/1024s, almost 1ms)

    If you include interrupts into this state machine then you will have no guarantee that you will sample every 10ms as both BLE and ANT event will have execution priority.

    If you set your RTC prescaler to zero and use a COMPARE event at 328 ticks you will get a COMPARE event every 328 * 30.51µs = 10.00728 ms. 



Related