<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Continuous one sided drift in frequency measurement over GPIOTE.</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/82762/continuous-one-sided-drift-in-frequency-measurement-over-gpiote</link><description>Using above strategy for frequency measurement. Frequency source connected with one gpio pin. 
 Only GPIOTE PPI Timer modules are involved 
 HFXO is in use full time through sd_...request command 
 Frequency observed is showing a one sided trend, which</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Thu, 16 Dec 2021 07:49:13 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/82762/continuous-one-sided-drift-in-frequency-measurement-over-gpiote" /><item><title>RE: Continuous one sided drift in frequency measurement over GPIOTE.</title><link>https://devzone.nordicsemi.com/thread/343799?ContentTypeID=1</link><pubDate>Thu, 16 Dec 2021 07:49:13 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e65faf2f-a4a4-4964-9cd0-e5e8589287e3</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
[quote user="thenagi"]1) is using interrupt handler not including soft side of nrf?[/quote]
&lt;p&gt;I am not sure what you mean? If you ask if it could be interrupted/delayed by the SoftDevice, then yes, it can. That does not seem to be what is causing the issue here though as that could give you some odd measurements, but not a general&amp;nbsp; drift as you have shown. In any case, the SoftDevice generally needs a high interrupt latency, if you want to avoid this and don&amp;#39;t need to sample regularly, you can use the &lt;a href="https://infocenter.nordicsemi.com/topic/sds_s132/SDS/s1xx/concurrent_multiprotocol_tsl_api/tsl_usage_examples.html"&gt;timeslot API&lt;/a&gt; to do frequency measurements when the SoftDevice is guaranteed to not interrupt. I suggest waiting with this though, as it does not seem relevant for the current issue (frequency drift in one of the devices).&lt;/p&gt;
[quote user="thenagi"]2) plz comment on my strategy in previous comment, I can get rid of handler , and a timer also :). That would be more core cpu independent IMO.[/quote]
&lt;p&gt;No, you cannot do that. My suggestion about using a single timer was caused my me reading the question too fast. You need two timers to measure the frequency, one in timer mode and one in counter mode, as you are doing, and as described in the old thread you linked to.&lt;/p&gt;
[quote user="thenagi"]&lt;p&gt;3) I agree nrf crystal is drifting , agree some silicon on frequency generator is drifting as well. But net result including both source side and destination side can&amp;#39;t be one sided. Only variable is temperature , which is periodic during day and night, and expectation is net measurement drifting whichever side should show same pattern of up and down. Graph in original issue is of 3 day. Upper one went down continuously, lower one drifted both side.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Another thing if you look at second graph shared in comment, upper nrf graph is showing inflection at same points in time, where lower graph changed its direction. So drift contains a temp dependence but it&amp;#39;s overshadowed by a monotonous downward trend.&lt;/p&gt;[/quote]
&lt;p&gt;I understand.&amp;nbsp;But I do not see any way to explain this from your firmware implementation. I suggest you test the two devices separately (the NRF and whatever is the source of this frequency) using proper lab equipment to understand where the drift comes from (clock inaccuracy). That must be the way forward, as that will narrow down this issue a lot. Currently there is nothing indicating that the issue is related to the nRF or related circuitry at all (though it cannot be ruled out either - before you test this).&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Continuous one sided drift in frequency measurement over GPIOTE.</title><link>https://devzone.nordicsemi.com/thread/343743?ContentTypeID=1</link><pubDate>Wed, 15 Dec 2021 17:30:40 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:9f8fce10-5927-4500-91a4-47ecf1d19f28</guid><dc:creator>thenagi</dc:creator><description>&lt;p&gt;1) is using interrupt handler not including soft side of nrf?&lt;/p&gt;
&lt;p&gt;2) plz comment on my strategy in previous comment, I can get rid of handler , and a timer also :). That would be more core cpu independent IMO.&lt;/p&gt;
&lt;p&gt;3) I agree nrf crystal is drifting , agree some silicon on frequency generator is drifting as well. But net result including both source side and destination side can&amp;#39;t be one sided. Only variable is temperature , which is periodic during day and night, and expectation is net measurement drifting whichever side should show same pattern of up and down. Graph in original issue is of 3 day. Upper one went down continuously, lower one drifted both side.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Another thing if you look at second graph shared in comment, upper nrf graph is showing inflection at same points in time, where lower graph changed its direction. So drift contains a temp dependence but it&amp;#39;s overshadowed by a monotonous downward trend.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Continuous one sided drift in frequency measurement over GPIOTE.</title><link>https://devzone.nordicsemi.com/thread/343728?ContentTypeID=1</link><pubDate>Wed, 15 Dec 2021 15:49:10 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:2580ad7d-9fb5-4ca7-b1f1-81a80b3c0958</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;Ah, sorry. I read your original post too fast and misread it, and then&amp;nbsp;got confused because the code did not do what I expected it to do (which was to simply toggle a GPIO based on the TIMER via PPI).&lt;/p&gt;
&lt;p&gt;For measuring a frequency on a GPIO input this looks sensible.&lt;/p&gt;
&lt;p&gt;The problem here then is that the nRF is measuring the frequency of an external device, and you would expect that frequency to be stable. As there is a drift here, there is a relative change in frequency between the clock in the nRF and the clock in the device generating the signal. There is nothing in your measurements that indicate which of the devices has most of the clock drift though.&lt;/p&gt;
&lt;p&gt;If you have a proper high accuracy frequency counter instrument I suggest you use that to measure the frequency accuracy of both the nRF and the other device, which generates this signal. To measure it for the nRF you can use the &lt;a href="https://infocenter.nordicsemi.com/topic/sdk_nrf5_v17.1.0/nrf_gpiote_example.html"&gt;GPIOTE Example&lt;/a&gt;&amp;nbsp;(just modify it to use a higher frequency).&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Continuous one sided drift in frequency measurement over GPIOTE.</title><link>https://devzone.nordicsemi.com/thread/343700?ContentTypeID=1</link><pubDate>Wed, 15 Dec 2021 14:41:08 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:548329f4-1abf-46ad-8e97-e09cc7b3ddee</guid><dc:creator>thenagi</dc:creator><description>&lt;p&gt;Correct me if my understanding is incorrect.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I should use a single timer in counter mode. Gpiote is linked to increment it.&lt;/p&gt;
&lt;p&gt;Start it -&amp;gt; wait for fixed time -&amp;gt; capture the value -&amp;gt; clear it&lt;/p&gt;
&lt;p&gt;Keep repeating.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Do I need to pause resume all interrupts, maybe soft device, while running this one iteration.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Continuous one sided drift in frequency measurement over GPIOTE.</title><link>https://devzone.nordicsemi.com/thread/343687?ContentTypeID=1</link><pubDate>Wed, 15 Dec 2021 14:18:16 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c3d057bb-2ab7-4cd5-a1b1-617a18efe958</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;Why do you use two timers here? And why do you clear the timers in the interrupt handler (I see you &lt;em&gt;also&lt;/em&gt; clear timer 1 using a short). You should ensure that you have no SW involved in this after configuring the setup, simply use a single timer that toggles the GPIO via PPI, and is cleared using a short. That way, no SW is involved. This should be the first step.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Continuous one sided drift in frequency measurement over GPIOTE.</title><link>https://devzone.nordicsemi.com/thread/343679?ContentTypeID=1</link><pubDate>Wed, 15 Dec 2021 14:06:37 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:07f2e48c-c851-4bfa-9cc0-17305472abd8</guid><dc:creator>thenagi</dc:creator><description>&lt;p&gt;Firmware is attached at the end.&lt;/p&gt;
&lt;p&gt;Regarding HW we are using a ready made ble module based on nrf58232.&lt;/p&gt;
&lt;p&gt;Testing is done in ambient environment.&lt;/p&gt;
&lt;p&gt;External frequency source is being measured in parallel via another frequency reader and am sharing a relative plot. Upper graph showing nrf reading, lower is showing a parallel reading with our existing in-production frequency reader.&lt;br /&gt;&lt;br /&gt;&lt;a href="https://drive.google.com/file/d/1fKTHddlG9pApBo_hFRdMvGUL5wchaozM/view?usp=sharing"&gt;https://drive.google.com/file/d/1fKTHddlG9pApBo_hFRdMvGUL5wchaozM/view?usp=sharing&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;////////////////////////////////////////&lt;br /&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;
#include &amp;quot;gpiote_driver.h&amp;quot;

#define FULE_FREQ_PIN 8

#define TASK_TIMER_TIMER1_INTERVAL             1000  // Timer interval in milliseconds

static nrf_drv_timer_t tasktimer = NRF_DRV_TIMER_INSTANCE(1);
static nrf_drv_timer_t fftimer = NRF_DRV_TIMER_INSTANCE(2);

uint32_t fuelFrequency = 0;

void tasktimer_handler(nrf_timer_event_t event_type, void * p_context)
{
    NRF_TIMER1-&amp;gt;EVENTS_COMPARE[0] = 0;
    
    NRF_TIMER2-&amp;gt;TASKS_CAPTURE[0] = 1;

    //if(nrf_timer_event_check(tasktimer.p_reg, NRF_TIMER_EVENT_COMPARE0)){
    
      fuelFrequency = (double)NRF_TIMER2-&amp;gt;CC[0];
      insertToArr(fuelFrequency);
      NRF_LOG_INFO(&amp;quot;Fuel Frequency : %ld&amp;quot;, fuelFrequency);
      fuelFrequency = 0;

    //}    
    

    NRF_TIMER1-&amp;gt;TASKS_CLEAR = 1;

    NRF_TIMER2-&amp;gt;TASKS_CLEAR = 1;	
                                    
    NRF_TIMER2-&amp;gt;TASKS_START = 1;		
}

void timer_dummy_handler(nrf_timer_event_t event_type, void * p_context){}

void gpiote_event_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action){}

void gpiote_init(void)
{
    ret_code_t err_code;
    uint32_t gpiote_evt_addr;
    uint32_t timer_task_addr;
    uint32_t timer_task_stop_addr;
    uint32_t timer_evt_addr;
    nrf_ppi_channel_t timer_ppi_channel;
    nrf_ppi_channel_t gpiote_ppi_channel;

    
    // Timer 1 Initilize
    nrf_drv_timer_config_t tasktimer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    tasktimer_cfg.frequency = NRF_TIMER_FREQ_31250Hz;
    err_code = nrf_drv_timer_init(&amp;amp;tasktimer, &amp;amp;tasktimer_cfg, tasktimer_handler);
    APP_ERROR_CHECK(err_code);
    //nrf_timer_task_trigger(tasktimer.p_reg, NRF_TIMER_TASK_CLEAR);
    //nrf_timer_event_clear(tasktimer.p_reg, NRF_TIMER_EVENT_COMPARE0);
    //nrf_drv_timer_compare(&amp;amp;tasktimer, NRF_TIMER_CC_CHANNEL0, nrf_drv_timer_ms_to_ticks(&amp;amp;tasktimer, TASK_TIMER_TIMER1_INTERVAL), true);
    nrf_drv_timer_extended_compare(&amp;amp;tasktimer, NRF_TIMER_CC_CHANNEL0, nrf_drv_timer_ms_to_ticks(&amp;amp;tasktimer, TASK_TIMER_TIMER1_INTERVAL), NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
    timer_evt_addr = nrf_drv_timer_event_address_get(&amp;amp;tasktimer, NRF_TIMER_EVENT_COMPARE0);
    
    NRF_LOG_INFO(&amp;quot;TIMER 1 Initilized.&amp;quot;);
    

    // Timer 2 Initilize
    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;
    timer_cfg.mode = NRF_TIMER_MODE_COUNTER;
    err_code = nrf_drv_timer_init(&amp;amp;fftimer, &amp;amp;timer_cfg, timer_dummy_handler);
    APP_ERROR_CHECK(err_code);
    timer_task_addr = nrf_drv_timer_task_address_get(&amp;amp;fftimer, NRF_TIMER_TASK_COUNT);
    timer_task_stop_addr = nrf_drv_timer_task_address_get(&amp;amp;fftimer, NRF_TIMER_TASK_STOP);

    NRF_LOG_INFO(&amp;quot;TIMER 2 Initilized.&amp;quot;);
    

    // GPIOTE Initilize
    //Check if the GPIOTE is initialized
    if (nrf_drv_gpiote_is_init() == NULL) {
      //If its not initialized, init it now
      err_code = nrf_drv_gpiote_init(); //Init the GPIO interrupt and tasks
      APP_ERROR_CHECK(err_code); //Check the error code 
      //(0x8 means the GPIOTE module is already enabled)
    }

    nrf_drv_gpiote_in_config_t inConfig = GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);
    err_code = nrf_drv_gpiote_in_init(FULE_FREQ_PIN, &amp;amp;inConfig, gpiote_event_handler);
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_in_event_enable(FULE_FREQ_PIN, false);
    gpiote_evt_addr = nrf_drv_gpiote_in_event_addr_get(FULE_FREQ_PIN);

    NRF_LOG_INFO(&amp;quot;GPIOTE Initilized.&amp;quot;);


    // GPIOTE PPI Initilize
    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_alloc(&amp;amp;gpiote_ppi_channel);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_assign(gpiote_ppi_channel, gpiote_evt_addr, timer_task_addr);
    APP_ERROR_CHECK(err_code);

    // Enable the PPI channel.
    err_code = nrf_drv_ppi_channel_enable(gpiote_ppi_channel);
    APP_ERROR_CHECK(err_code);

    NRF_LOG_INFO(&amp;quot;GPIOTE PPI Initilized.&amp;quot;);

    
    // timer PPI Initilize
    //err_code = nrf_drv_ppi_init();
    //APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_alloc(&amp;amp;timer_ppi_channel);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_assign(timer_ppi_channel, timer_evt_addr, timer_task_stop_addr);
    APP_ERROR_CHECK(err_code);

    // Enable the PPI channel.
    err_code = nrf_drv_ppi_channel_enable(timer_ppi_channel);
    APP_ERROR_CHECK(err_code);

    NRF_LOG_INFO(&amp;quot;Timer PPI Initilized.&amp;quot;);
    

    
    nrf_drv_timer_enable(&amp;amp;tasktimer);
    nrf_drv_timer_enable(&amp;amp;fftimer);

    NRF_LOG_INFO(&amp;quot;GPIOTE Init Done.&amp;quot;);
}&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Continuous one sided drift in frequency measurement over GPIOTE.</title><link>https://devzone.nordicsemi.com/thread/343648?ContentTypeID=1</link><pubDate>Wed, 15 Dec 2021 13:01:49 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:d2c659e9-2e16-47d6-a778-f0b8f9e1cf45</guid><dc:creator>Einar Thorsrud</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;The way you describe it this looks like it is entirely HW related, as using only a TIMER running of the HFXO, GPIOTE and PPI would not involve any CPU activity, and so this should be deterministic with regards to clock cycles. It would be good to take a look at your test firmware though, just to be sure.&lt;/p&gt;
&lt;p&gt;Other than that, it would also be good to take a lock at your HW, particularly your crystal and load cap values, and also know more about the test conditions (temperature variations, for instance).&lt;/p&gt;
&lt;p&gt;Lastly, what external instruments do you use to measure the GPIO toggling frequency? Could it be that what you see is related to an issue with the measuring equipment/setup?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>