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

After configured internal low frequency clock source,advertising stop but saadc still working

The program flow of the slave is to sample the analog signal source through the saadc and then send it to the host through the nus.
When debugging on nrf52dk, configure the chip to xtal mode and the program can run smoothly. But when the chip is configured as a 32.768k internal low-frequency clock source RC, after each reset, the broadcast signal appears for a while and disappears, but the saadc sampling continues to run. Why?
The strange thing is that the first run after programming the program is normal.

  • When the error occurs, I get the information as follows:

    m_data_data.fault_id == 0x00004001;   m_data_data.pc==0x0002C395;   m_data_data.error_info==0x2000DA10;

    m_data_data.p_file_name==main.c;   m_data_data.line_num==0x00000129;   m_data_data.err_code==0x00000008;

    the code of the line 292-298(DEC):

     

    static void adc_timer_handler(void * p_context)
    {
    		ret_code_t err_code;
    		NRF_LOG_INFO("SAADC loop.");
    		err_code = nrf_drv_saadc_sample(); 
    		APP_ERROR_CHECK(err_code);
    }

    When there is an error, the serial port usually gives out related error information, but it does not now.

    Another strange thing, the program will run normally a few times.

    I don’t know if this information is enough for your analysis. If you need any more information, please tell me.

    Thank you.

  • Hi

    I don't see any mention of it in this case, but are you using the nRF5 SDK or nRFConnect SDK for development here? I assumed you were using the nRF5 SDK, as that is the most common to use with the nRF52 series. Seems very strange that you don't get an error code out of the terminal in your case.

    Can you provide some more information on your ADC code, I.E. SAADC_INIT() for instance? We would in general recommend using the SAADC as how we do in the SDK example though, by connecting the timer event with the sample task of the SAADC to get periodic samples.

    Best regards,

    Simon

  • HI, I am sorry for cann't give you  some useful information. I use the  nRF5 SDK15.2.0 for development here. And my code about SAADC as follows:

    /**related code in main function**/    
        BLE_saadc_init();
        // Start execution.
        NRF_LOG_INFO("Debug logging for adc over RTT started.");
    	  nrf_delay_ms(500);
        saadc_test();
    	  
        // Enter main loop.
        for (;;)
        {
    				if(m_saadc_calibrate == true)
            {
                nrf_drv_saadc_abort();                                  // Abort all ongoing conversions. Calibration cannot be run if SAADC is busy
                adc_calibrate();
                m_saadc_calibrate = false;
            } 
    				while(NRF_LOG_PROCESS() != NRF_SUCCESS);
            idle_state_handle();			
        }
        /**others related code**/
        /**saadc init**/
        void BLE_saadc_init(void)
    {
    			ret_code_t err_code;
    			nrf_drv_saadc_config_t saadc_config;
    			saadc_config.low_power_mode = true;                                                   //Enable low power mode.
    			saadc_config.resolution = NRF_SAADC_RESOLUTION_10BIT;                                 //Set SAADC resolution to 12-bit. This will make the SAADC output values from 0 (when input voltage is 0V) to 2^12=4096 (when input voltage is 3.6V for channel gain setting of 1/6).
    			saadc_config.oversample = NRF_SAADC_OVERSAMPLE_2X;                                           //Set oversample to 4x. This will make the SAADC output a single averaged value when the SAMPLE task is triggered 4 times.
    			saadc_config.interrupt_priority = APP_IRQ_PRIORITY_LOW; 
    			nrf_saadc_channel_config_t channel_config 	=		
    			NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN1);
                 channel_config.burst =  NRF_SAADC_BURST_ENABLED;                                   //Configure burst mode for channel 0. Burst is useful together with oversampling. When triggering the SAMPLE task in burst mode, the SAADC will sample "Oversample" number of times as fast as it can and then output a single averaged value to the RAM buffer. If burst mode is not enabled, the SAMPLE task needs to be triggered "Oversample" number of times to output a single averaged value to the RAM buffer.		
    			channel_config.gain 			= NRF_SAADC_GAIN1_6;
    			err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);    //&saadc_config
    			APP_ERROR_CHECK(err_code);
    			err_code = nrf_drv_saadc_channel_init(0, &channel_config);
    			APP_ERROR_CHECK(err_code);
    	
    #ifndef  SAADC_BLOCKING 
    			err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);
    			APP_ERROR_CHECK(err_code);
    			err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);
    			APP_ERROR_CHECK(err_code);
    #endif
    }
    /**saadc timer set**/
    void saadc_test()
    {
    	ret_code_t	err_code;
    	err_code	=	app_timer_create(&m_timer,APP_TIMER_MODE_REPEATED,adc_timer_handler);
    	APP_ERROR_CHECK(err_code);
    	app_timer_start(m_timer, APP_TIMER_TICKS(5),NULL);
    }
    /**timer callback function**/
    static void adc_timer_handler(void * p_context)
    {
    		ret_code_t err_code;
    		NRF_LOG_INFO("SAADC loop.");
    		err_code = nrf_drv_saadc_sample(); 
    		APP_ERROR_CHECK(err_code);
    }
    /**saadc callback function**/
    static int buf_i;
    static uint8_t uart_send_buf[4];
    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
    		//U_IntData uart_data;
    		ret_code_t err_code;
    		uint16_t sample_sum=0;
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
    			NRF_LOG_INFO ("%d evt_done",m_adc_count);
          if(m_adc_count%12000==0)
          {
    				m_saadc_calibrate = true;                                           // Set flag to trigger calibration in main context when SAADC is stopped
          }
    			for(uint8_t i = 0 ; i < SAMPLES_IN_BUFFER ; i++)
    			{
    				sample_sum+= abs(p_event->data.done.p_buffer[i]);
    				NRF_LOG_INFO ("%d /n",p_event->data.done.p_buffer[i]);
    			}
    			sample_ave=(uint16_t)(sample_sum/(int)(SAMPLES_IN_BUFFER)*3.6/1024*100);
    			NRF_LOG_INFO("result:%d",sample_ave);
    			uart_send_buf[0]=0xFF;
    			uart_send_buf[3]=0xAF;
    			uint_char(sample_ave,uart_send_buf);
    			//uart_data.value=sample_ave;
    			//float_char(sample_ave,uart_send_buf);
          NRF_LOG_DEBUG("sending data from saadc. Writing data on UART.");
          NRF_LOG_HEXDUMP_DEBUG(uart_send_buf,4);
            for (uint32_t i = 0; i < 4; i++)
            {
                do 
    							{	
    								err_code = app_uart_put(uart_send_buf[i]);
                    if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY))
                    {
                        NRF_LOG_ERROR("Failed receiving adc message. Error 0x%x. ", err_code);
                        APP_ERROR_CHECK(err_code);
                    }
                } while (err_code == NRF_ERROR_BUSY);
            }
    				//while (app_uart_put('\n') == NRF_ERROR_BUSY);
            
        
    			if (buf_i<8000)
    			{
    			sample_ave_buf[buf_i]=(int) (sample_ave*1000);
    			NRF_LOG_DEBUG("%p,%p",&sample_ave_buf[0],&sample_ave_buf[7999]);
    			buf_i++;
    			}
    			if(m_saadc_calibrate == false)
            {
                err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);             //Set buffer so the SAADC can write to it again. 
                APP_ERROR_CHECK(err_code);
    					
            }
    			m_adc_count++;
    	  }
    		else if (p_event->type == NRF_DRV_SAADC_EVT_CALIBRATEDONE)
        {                                                                   
         
    			
            NRF_LOG_INFO("SAADC calibration complete ! \r\n");                                              //Print on UART
    		}
    }

  • Hi

    Can you please check the return value of your app_timer_start() function, just so we know that it returns successfully? I don't see that you've initialized the app_timer either, but I assume you just omitted it from this snippet?

    You can also try setting the ADC to blocking mode, to make sure it will wait for the transmission to be completed before doing the next one. Can you also upload the RTT log you're seeing? Please make sure that your app_uart_put() comes from app_uart_fifo, and not app_uart.c.

    Best regards,

    Simon

  • Hi,

    Firstly, the return value of app_timer_start() function I get is "0"(print in %x format). And, I have initialized the app_timer.

    Also I'm sure that the app_uart_put() comes from app_uart_fifo.

    Before setting the ADC to blocking mode,the RTT log as follows:

    00> <debug> nrf_sdh: State request: 0x00000000
    00> <debug> nrf_sdh: State change: 0x00000000
    00> <debug> nrf_sdh: State change: 0x00000001
    00> <debug> nrf_sdh_ble: RAM starts at 0x20002A00
    00> <info> app: Debug logging for advertising started.
    00> <info> app: Debug logging for adc over RTT started.
    00> <info> app: app_timer_start erecode==0
    00> <info> app: SAADC loop.
    00> <info> app: 0 evt_done
    00> <info> app: 47 /n
    00> <info> app: result:16
    00> <debug> app: sending data from saadc. Writing data on UART.
    00> <debug> app: 0x200030A8,0x2000ADA4

    After setting the ADC to blocking mode,and the program runs continuously (load on the nrf52-dk and the self-made pcb), but never enter in saadc callback function. 

    And after I add other function (like uart_put), program can also run on the nrf52-dk, but when load on the self-made pcb, program stop at every time power on ,the RTT log as follows:(but can run normally after reset)

    00> <error> app: ERROR 4 [NRF_ERROR_NO_MEM] at main.c:347
    00> PC at: 0x0002C551
    00> <error> app: End of error report

    Finally, all in all, I want to know the solution to nrf_no_mem and the reason for the failure in non-blocking mode. It is best for you to provide a solution. Thank you.

    Best regards,

Related