This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Triggering saadc with RTC2 compare channel - initially working and than stops

Hi,

I am working on nrf52832, s132, SDK17, trying to trigger the saadc with the RTC2 

This is my setup :

const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(2);
static nrf_saadc_value_t     m_buffer_pool[2][SAMPLES_IN_BUFFER];
static nrf_ppi_channel_t     m_ppi_channel;
static uint32_t              m_adc_evt_counter;

void saadc_sampling_event_init(void)
{
    ret_code_t err_code;

    nrf_drv_rtc_config_t config = NRF_DRV_RTC_DEFAULT_CONFIG;
    err_code = nrf_drv_rtc_init(&rtc, &config, rtc_handler);
    APP_ERROR_CHECK(err_code);

	 err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 200,true);
    APP_ERROR_CHECK(err_code);

    //Power on RTC instance
    nrf_drv_rtc_enable(&rtc);
    
    uint32_t rtc_compare_event_addr = nrf_drv_rtc_event_address_get(&rtc, NRF_RTC_EVENT_COMPARE_0);
    uint32_t rtc_clear_task_addr = nrf_drv_rtc_task_address_get(&rtc, NRF_RTC_TASK_CLEAR);
    uint32_t saadc_sample_event_addr = nrf_drv_saadc_sample_task_get();

    /* setup ppi channel so that timer compare event is triggering sample task in SAADC */
    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, rtc_compare_event_addr, saadc_sample_event_addr);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_ppi_channel_fork_assign(m_ppi_channel, rtc_clear_task_addr);
    APP_ERROR_CHECK(err_code);
		
}


void saadc_init_NordicPlayground(void)
{
    ret_code_t err_code;
	
    nrf_drv_saadc_config_t saadc_config = NRF_DRV_SAADC_DEFAULT_CONFIG;
    saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT;
	
    nrf_saadc_channel_config_t channel_0_config =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4);
    channel_0_config.gain = NRF_SAADC_GAIN1_4;
    channel_0_config.reference = NRF_SAADC_REFERENCE_VDD4;
	
    nrf_saadc_channel_config_t channel_1_config =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN5);
    channel_1_config.gain = NRF_SAADC_GAIN1_4;
    channel_1_config.reference = NRF_SAADC_REFERENCE_VDD4;
	
    nrf_saadc_channel_config_t channel_2_config =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN6);
    channel_2_config.gain = NRF_SAADC_GAIN1_4;
    channel_2_config.reference = NRF_SAADC_REFERENCE_VDD4;
	
    nrf_saadc_channel_config_t channel_3_config =
        NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN7);
    channel_3_config.gain = NRF_SAADC_GAIN1_4;
    channel_3_config.reference = NRF_SAADC_REFERENCE_VDD4;				
	
    err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_channel_init(0, &channel_0_config);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(1, &channel_1_config);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(2, &channel_2_config);
    APP_ERROR_CHECK(err_code);
    err_code = nrf_drv_saadc_channel_init(3, &channel_3_config);
    APP_ERROR_CHECK(err_code);	

    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0],SAADC_SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);   
    err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1],SAADC_SAMPLES_IN_BUFFER);
    APP_ERROR_CHECK(err_code);
}

void saadc_sampling_event_enable(void)
{
    ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);

    APP_ERROR_CHECK(err_code);
}

void adc_ppi_init(void)
{
	saadc_sampling_event_init();
	saadc_init_NordicPlayground();
    saadc_sampling_event_enable();	
}	

what I am trying to do is to periodically trigger a series of samples and than stop them until the next cycle, I have done this successfully on the nRF51 by retiming the CC compare channel on the interrupt, I set the compare channel again a few times each time the interrupt is called and than stops, the entire series of samples takes a few milliseconds. after 1sec passes I start the process again. it is important for me to time exactly my samples, I can not have them just run continuously.

This is my original code for the nRF51,on which I tried to base my solution for the nRF52, note that I was using the CC2 for RTC1

void RTC1_IRQHandler(void)
{
   // Clear all events (also unexpected ones)
	 NRF_RTC1->EVENTS_COMPARE[0] = 0;
	 NRF_RTC1->EVENTS_COMPARE[1] = 0;
	
	if (NRF_RTC1->EVENTS_COMPARE[2] != 0)
	{
				rtc1_c2_counter++;		
				NRF_RTC1->EVENTS_COMPARE[2] = 0;
			
				if (rtc1_c2_counter >= ADC_BUFFER_SIZE)
				{
					rtc1_c2_counter = 0;
				}			
				else
				{
					NRF_RTC1->CC[2] = add_rtc_offset(0x20*10);
				}
	}
	else
	{
			NRF_RTC1->EVENTS_COMPARE[2] = 0;
	}	
	
    NRF_RTC1->EVENTS_COMPARE[3] = 0;
    NRF_RTC1->EVENTS_TICK       = 0;
    NRF_RTC1->EVENTS_OVRFLW     = 0;

    // Check for expired timers
    timer_timeouts_check();
}

I started the sequence so :

uint32_t add_rtc_offset(uint32_t offset)	
{
		uint32_t rtc_current;
		uint32_t rtc_updated;

		rtc_current = NRF_RTC1->COUNTER;
	
		if ((rtc_current + offset) > RTC1_MAX)
		{
			rtc_updated = offset - (RTC1_MAX - rtc_current) ;
		}
		else
		{
			rtc_updated = rtc_current + offset;
		}
					
		return(rtc_updated);
}

NRF_RTC1->CC[chan] = add_rtc_offset(0x20*offset);

It worked fine on my nRF51822 with s130, but it does not work for me on the nRF52, because once I stop updating the CC it stops working and the next trigger never works again.

I followed a suggestion on the forum and tried to do reconfigure the entire compare channel on the interrupt like so :

(note the I am using RTC2, compare channel 0)

static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
{
    ret_code_t err_code;
		
	//-------------------------------------
	if (rtc2_c0_counter >= ADC_BUFFER_SIZE)
	{
		rtc2_c0_counter = 0;
	}			
	else
	{
		err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 200,true);
		rtc2_c0_counter++;
	}		
		
	NRF_RTC2->EVENTS_COMPARE[0] = 0;
	NRF_RTC2->EVENTS_COMPARE[1] = 0;
	NRF_RTC2->EVENTS_COMPARE[2] = 0;
	NRF_RTC2->EVENTS_COMPARE[3] = 0;
    NRF_RTC2->EVENTS_TICK       = 0;
    NRF_RTC2->EVENTS_OVRFLW     = 0;		

}

and this is how I triggered it :

err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 200,true);

That also worked for one sequence only and the following attempts to re-trigger failed.

Any suggestions?

Thanks in advance!

Ron

Parents
  • Hello,

    Looks like you are forgetting to clear the RTC counter from the driver callback?

    Please try to clear it like this:

    static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
    {
        uint32_t err_code; 
    
        if (int_type == NRF_DRV_RTC_INT_COMPARE0)
        {
            nrf_gpio_pin_toggle(COMPARE_EVENT_OUTPUT);
            
            nrf_drv_rtc_counter_clear(&rtc);
            err_code = nrf_drv_rtc_cc_set(&rtc,0 ,COMPARE_COUNTERTIME * 200,true);
            APP_ERROR_CHECK(err_code);
        }
    }

    Best regards,

    Vidar

  • Hi Vidar,

    Thanks for your help,

    If I clear it, do I still need to do the following? :

    	NRF_RTC2->EVENTS_COMPARE[0] = 0;
    	NRF_RTC2->EVENTS_COMPARE[1] = 0;
    	NRF_RTC2->EVENTS_COMPARE[2] = 0;
    	NRF_RTC2->EVENTS_COMPARE[3] = 0;
        NRF_RTC2->EVENTS_TICK       = 0;
        NRF_RTC2->EVENTS_OVRFLW     = 0;	

    Anyway I implemented the following code 

    static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
    {
        ret_code_t err_code;
    		
    		if (int_type == NRF_DRV_RTC_INT_COMPARE0)
    		{
    			nrf_drv_rtc_counter_clear(&rtc);
    				
    			//-------------------------------------
    			if (rtc2_c0_counter >= ADC_BUFFER_SIZE)
    			{
    				rtc2_c0_counter = 0;
    			}			
    			else
    			{
    				err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 200,true);
    				rtc2_c0_counter++;
    			}		
    		}
    }

    It still does not work beyond the first series of samples, as long as I am resetting the the CC -

    nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 200,true);
    it is working, but after I stop it on the ADC_BUFFER_SIZE sample, it never starts again, clearing the RTC does not seems to fix it.

    Any ideas?

    Thanks!

Reply
  • Hi Vidar,

    Thanks for your help,

    If I clear it, do I still need to do the following? :

    	NRF_RTC2->EVENTS_COMPARE[0] = 0;
    	NRF_RTC2->EVENTS_COMPARE[1] = 0;
    	NRF_RTC2->EVENTS_COMPARE[2] = 0;
    	NRF_RTC2->EVENTS_COMPARE[3] = 0;
        NRF_RTC2->EVENTS_TICK       = 0;
        NRF_RTC2->EVENTS_OVRFLW     = 0;	

    Anyway I implemented the following code 

    static void rtc_handler(nrf_drv_rtc_int_type_t int_type)
    {
        ret_code_t err_code;
    		
    		if (int_type == NRF_DRV_RTC_INT_COMPARE0)
    		{
    			nrf_drv_rtc_counter_clear(&rtc);
    				
    			//-------------------------------------
    			if (rtc2_c0_counter >= ADC_BUFFER_SIZE)
    			{
    				rtc2_c0_counter = 0;
    			}			
    			else
    			{
    				err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 200,true);
    				rtc2_c0_counter++;
    			}		
    		}
    }

    It still does not work beyond the first series of samples, as long as I am resetting the the CC -

    nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 200,true);
    it is working, but after I stop it on the ADC_BUFFER_SIZE sample, it never starts again, clearing the RTC does not seems to fix it.

    Any ideas?

    Thanks!

Children
  • Hi,

    If I clear it, do I still need to do the following? :

    The driver is responsible for clearing of these events. So no, you shouldn't clear them in the application callback.

    You have to explicitly re-enable the event by calling nrf_drv_rtc_cc_set() after you have gotten a compare event if you want the compare event to trigger again. This is because the driver's IRQ handler is disables it.

  • Hi,

    I understand regarding the rest,

    regrading the retriggering, what if I want it to stop after 4 samples for example, and than start the cycle again in the future, say after 1 sec?

    Thanks again

  • Hi,

    regrading the retriggering, what if I want it to stop after 4 samples for example, and than start the cycle again in the future, say after 1 sec?

    Can you set the CC register to trigger the interrupt again in 1 second then?

  • Hi,

    Can you set the CC register to trigger the interrupt again in 1 second

    Yes, after 1 sec I do call the same command again; I call it cyclically every 1 sec,

    err_code = nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 200,true);

    But the interrupt does not appear again as in the first call, and I don't know why 

    Thanks

  • Hi,

    I only see you calling nrf_drv_rtc_cc_set(&rtc,0,COMPARE_COUNTERTIME * 200,true); when you hit the else statement in rtc_handler() and not if you enter the first if statement.

Related