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

Capture timer using PPI adc DONE event

Hello,

First time post and brand new to the nRF52832 chip. I am tasked with building firmware that will synchronize ADC samples across multiple devices. I have started with the BLE time_sync demo and have verified that the BLE time synchronization is working very well with TIMER2 & TIMER3. Each device begins capturing ADC samples at the same time and sends the samples to a central device with an included time stamp. Each BLE packet contains 75 samples plus a 32-bit timestamp. The timestamp can either be taken when the first of the 75 samples is captured or the time of the last sample capture.

The ADC sample capture is triggered off of a PPI timer running at 256Hz. This is setup as follows:

    nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL6, 
        (uint32_t) nrf_timer_event_address_get(NRF_TIMER3, NRF_TIMER_EVENT_COMPARE4),
        nrf_drv_saadc_sample_task_get());
        
    The data is stored via DMA using 2 buffers:

    //Set up DMA for conversion, triggered w/ NRF_SDADC_TASK_SAMPLE or nrfx__saadc_sample()
    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);

When a DMA buffer is filled, I receive the NRF_SAADC_EVENT_DONE event via the saadc_callback.

My problem is that there is quite a bit of jitter in the timestamps that I am currently capturing in the saadc_callback method. I believe this is because of the delays caused by the BLE activity and the priority of this event. I need the timestamp to be accurate to 1uS. I have verified that the two device clocks are accurate to this degree with the BLE syncing on average but my timestamps vary up to several milliseconds which is unacceptable.

I would like to capture the timer values (TIMER2 and TIMER3 used in the demo for tracking the synchronized device time) using PPI so that when I read the values in the callback, they are accurate to the time that the ADC event actually occurred. I have not been able to do this. I am trying to cache the values when the DMA DONE event occurs. I have tried the following with no luck. The Capture registers are never updated.

uint32_t chn7 = 7;
NRF_PPI->CHENCLR = (1 << chn7);
NRF_PPI->CH[chn7].EEP = (uint32_t) nrf_saadc_event_address_get(NRF_SAADC_EVENT_DONE),
NRF_PPI->CH[chn7].TEP = (uint32_t) &m_params.high_freq_timer[0]->TASKS_CAPTURE[4];
NRF_PPI->FORK[chn7].TEP = (uint32_t) &m_params.high_freq_timer[1]->TASKS_CAPTURE[4];

Can someone help me with my configuration? Or provide an alternate way of getting the timestamp accuracy I need?

Thanks so much,

-Mike

Parents
  • Hi Håkon,

    Thank you for the feedback. Getting < 125ns timing would be fantastic. I believe I have setup the configuration as you suggested but it isn't working. It appears that whenever the timer is captured, it's counter or some other event is occurring that prevents my other PPI connections from firing. At least that's my guess. I have a secondary counter (again from the BLE timer sync example) that is not being incremented as it should be.

    Here is my configuration logic:

        nrf_ppi_channel_disable(NRF_PPI_CHANNEL7);
        nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL7,
            (uint32_t) &NRF_SAADC->EVENTS_END,
            (uint32_t) &NRF_TIMER3->TASKS_CAPTURE[4]);
    
        //nrf_ppi_fork_endpoint_setup(NRF_PPI_CHANNEL7, (uint32_t) &TIMER2->TASKS_CAPTURE[4]);
        nrf_ppi_channel_enable(NRF_PPI_CHANNEL7);
    

    I have commented out the TEP for TIMER2 for the moment as I am just trying to get at least one of them to work. My interrupt that normally occurs when TIMER2 is incremented is no longer firing when I configure this PPI. It seems that configuring this PPI completely breaks the rest of the program flow. If I comment out this code, then everything works again, along with my very jittery timing.

    This seems like a pretty simple configuration; but not being very familiar with the Nordic architecture I'm sure I'm missing something.

    Any additional pointers?

    Thanks again,

    -Mike

  • Do you mind sharing the rest of the relevant parts of your code? 

    It's a bit hard to see what exactly you are doing. 

    It will also help me if you can explain exactly what TIMER2 is supposed to do. I assume TIMER3 is the synchronous clock.

Reply Children
No Data
Related