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.

  • Hello,

    zaki_fighting said:
    Hi, I changed my code as follows,but it didn't work. And the uart log never changed.

    My apologies, you should have the uint32_t ram_start = 0, since it will fetch the compile time APP_RAM_START define, and fill it in. So it does not really matter what the ram_start variable is initialized to. Sorry for any confusion this might have caused!

    zaki_fighting said:

    (it seems that the main program has reached the step:

    NRF_LOG_INFO("Debug logging for advertising started."); )

    Based on the last line of the log, it seems a NRF_FAULT_ID_APP_MEMACC fault is generated somewhere. This fault is commonly generated when the application tries to access the RAM allocated for the SoftDevice.
    Could you set out some breakpoints in your code, to pinpoint where this fault is generated using the debugger?

    Best regards,
    Karl

  • Hi, when I set breakpoints in my code,I found the error occurs when initiate the timer, that is 

    "err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, adc_timer_handler);"

    Thank you.

  • zaki_fighting said:

    when I set breakpoints in my code,I found the error occurs when initiate the timer, that is 

    "err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, adc_timer_handler);"

    Good work!
    I see now that you are using TIMER0 for your timer. This peripheral is already in use by the SoftDevice, and is therefore blocked for the application.
    Please use another timer instance, such as TIMER1.

    Best regards,
    Karl

  • Hi, it is worked when I choose the TIMER1 for my timer. But new problem occurred.

    After saadc calibration, saadc stops after sampling twice. And I can be sure that the program is still running normally, because Bluetooth can be searched and connected.

    I suspected that the nrf_drv_saadc_abort function stopped saadc sampling. So I have used nrf_drv_saadc_sample() function to restart saadc sampling, and the return value was 0, but it didn't work.

    related code and log as follows:

    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
    		ret_code_t err_code;
    		uint8_t adc_result[SAMPLES_IN_BUFFER*2],adc_string[SAMPLES_IN_BUFFER*4];
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
    			NRF_LOG_INFO ("%d evt_done",m_adc_evt_counter);
          if(m_adc_evt_counter%12000==0)
          {
    				m_saadc_calibrate = true;                                           																		// Set flag to trigger calibration in main context 
          }
    			for(uint8_t i = 0 ;i<p_event->data.done.size;i++)
    			{
    				adc_result[(i*2)] = p_event->data.done.p_buffer[i] >> 8;
            adc_result[(i*2)+1] = p_event->data.done.p_buffer[i];
    			}
    			HexToString(adc_string,adc_result,SAMPLES_IN_BUFFER*2);
    			if(SAMPLES_IN_BUFFER <= 5)
            {
    						uint16_t length = (uint16_t)(SAMPLES_IN_BUFFER*4);
    					  ble_nus_data_send(&m_nus, &adc_string[0], &length, m_conn_handle);																	  // send data through nus.
    				}	
    			if(m_saadc_calibrate == false)
            {
                err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);            //Set buffer when saadc is not in calibration state. 
                APP_ERROR_CHECK(err_code);
            }
    			m_adc_evt_counter++;
    	  }
    		else if (p_event->type == NRF_DRV_SAADC_EVT_CALIBRATEDONE)
        {                                                                   
            NRF_LOG_INFO("SAADC calibration complete ! \r\n");
    				err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);             					 		//Set buffer after calibration done. 
    				APP_ERROR_CHECK(err_code);
    				err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);             	 				 	 //Need to setup both buffers, as they were both removed with the call to nrf_drv_saadc_abort before calibration.
    				APP_ERROR_CHECK(err_code);	
    				err_code = nrf_drv_saadc_sample();
    				NRF_LOG_DEBUG("%x ,%s",err_code,err_code)
    		}
    }
    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: 0 evt_done
    00> <info> app: SAADC calibration complete ! 
    00> 
    00> <debug> app: 0 ,
    00> <info> app: 1 evt_done
    00> <info> app: 2 evt_done

    Thank you.

  • Thanks for helping me solve the problem.

    I have solved the problem by resetting the sampling buffer after calibration in the saadc_calibrate function instead of saadc_callback function. I think the reason may be that the sampling buffer time is set too late in the calibration callback function.

    //ORINGNAL CODE
    void adc_calibrate(void)
    {
        ret_code_t err_code =nrf_drv_saadc_calibrate_offset();
    		APP_ERROR_CHECK(err_code);
        while (nrf_drv_saadc_is_busy()); 
    }
    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
    		ret_code_t err_code;
    		uint8_t adc_result[SAMPLES_IN_BUFFER*2],adc_string[SAMPLES_IN_BUFFER*4];
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
    			NRF_LOG_INFO ("%d evt_done",m_adc_evt_counter);
          if(m_adc_evt_counter%12000==0)
          {
    				m_saadc_calibrate = true;                                           																		// Set flag to trigger calibration in main context 
          }
    			for(uint8_t i = 0 ;i<p_event->data.done.size;i++)
    			{
    				adc_result[(i*2)] = p_event->data.done.p_buffer[i] >> 8;
            adc_result[(i*2)+1] = p_event->data.done.p_buffer[i];
    			}
    			HexToString(adc_string,adc_result,SAMPLES_IN_BUFFER*2);
    			if(SAMPLES_IN_BUFFER <= 5)
            {
    						uint16_t length = (uint16_t)(SAMPLES_IN_BUFFER*4);
    					  ble_nus_data_send(&m_nus, &adc_string[0], &length, m_conn_handle);																	  // send data through nus.
    				}	
    			if(m_saadc_calibrate == false)
            {
                err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);            //Set buffer when saadc is not in calibration state. 
                APP_ERROR_CHECK(err_code);
            }
    			m_adc_evt_counter++;
    	  }
    		else if (p_event->type == NRF_DRV_SAADC_EVT_CALIBRATEDONE)
        {                                                                   
            NRF_LOG_INFO("SAADC calibration complete ! \r\n");
            	err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);             					 		//Set buffer after calibration done. 
    		APP_ERROR_CHECK(err_code);
    		err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);             	 				 	 //Need to setup both buffers, as they were both removed with the call to nrf_drv_saadc_abort before calibration.
    		APP_ERROR_CHECK(err_code);
    		}
    }
    //CORRECT CODE
    void adc_calibrate(void)
    {
        ret_code_t err_code =nrf_drv_saadc_calibrate_offset();
    		APP_ERROR_CHECK(err_code);
        while (nrf_drv_saadc_is_busy()); 
    		err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0], SAMPLES_IN_BUFFER);             					 		//Set buffer after calibration done. 
    		APP_ERROR_CHECK(err_code);
    		err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1], SAMPLES_IN_BUFFER);             	 				 	 //Need to setup both buffers, as they were both removed with the call to nrf_drv_saadc_abort before calibration.
    		APP_ERROR_CHECK(err_code);
    }
    void saadc_callback(nrf_drv_saadc_evt_t const * p_event)
    {
    		ret_code_t err_code;
    		uint8_t adc_result[SAMPLES_IN_BUFFER*2],adc_string[SAMPLES_IN_BUFFER*4];
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
    			NRF_LOG_INFO ("%d evt_done",m_adc_evt_counter);
          if(m_adc_evt_counter%12000==0)
          {
    				m_saadc_calibrate = true;                                           																		// Set flag to trigger calibration in main context 
          }
    			for(uint8_t i = 0 ;i<p_event->data.done.size;i++)
    			{
    				adc_result[(i*2)] = p_event->data.done.p_buffer[i] >> 8;
            adc_result[(i*2)+1] = p_event->data.done.p_buffer[i];
    			}
    			HexToString(adc_string,adc_result,SAMPLES_IN_BUFFER*2);
    			if(SAMPLES_IN_BUFFER <= 5)
            {
    						uint16_t length = (uint16_t)(SAMPLES_IN_BUFFER*4);
    					  ble_nus_data_send(&m_nus, &adc_string[0], &length, m_conn_handle);																	  // send data through nus.
    				}	
    			if(m_saadc_calibrate == false)
            {
                err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER);            //Set buffer when saadc is not in calibration state. 
                APP_ERROR_CHECK(err_code);
            }
    			m_adc_evt_counter++;
    	  }
    		else if (p_event->type == NRF_DRV_SAADC_EVT_CALIBRATEDONE)
        {                                                                   
            NRF_LOG_INFO("SAADC calibration complete ! \r\n");	
    		}
    }

    Thank you again for spending so much time on my question.

Related