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
  • Håkon,

    I have been doing lots of experimenting and searching my provided code base. I found the issue with my PPI configuration...turns out that CHANNEL7 was used elsewhere in the code that I had not seen previously and CH 7 was being enabled and disabled which explains why my setup wasn't working. I tested using CHANNEL 8 and things started working properly.

    On the timing side, I experimented with triggering the timer capture on the NRF_SAADC->EVENTS_END (end of ADC capture and transfer via DMA) using CHANNEL 8 and found that my timestamp fluctuated around ~1.1us but occasionally got as high as 75us. I would guess this is due to the timing of the ADC acquisition and DMA transfer. Since this is not accurate enough for our application, I decided to setup the PPI timer capture to trigger off of the start of ADC acquisition which is always very accurate using CHANNEL6 which was already setup to begin the ADC capture.

    My PPI setup looks like this now:

    // Setup PPI Channel 6 to trigger an ADC sample upon TIMER3 reaching compare register 0 (CC[0])
    nrf_ppi_channel_endpoint_setup(NRF_PPI_CHANNEL6, (uint32_t) nrf_timer_event_address_get(NRF_TIMER3, NRF_TIMER_EVENT_COMPARE0), nrf_drv_saadc_sample_task_get());
    
    // Setup PPI Channel 6 to also capture the high-speed timer tick when an ADC event is triggered
    nrf_ppi_fork_endpoint_setup(NRF_PPI_CHANNEL6, (uint32_t) &NRF_TIMER3->TASKS_CAPTURE[4]);

    I believe that I am out of the woods and have gained a good understanding of the Nordic PPI system through this work.

    Thank you for your time and insights.

    -Mike

  • Hey Mike,

    I'm glad to hear you solved the issue. The PPI system is alot of fun, but there's also quite a few avenues for issues with strange symptoms :P 

    BR,
    Håkon. 

Reply Children
No Data
Related