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

nRF52 TIMER PPI GPIOTE dropouts/pauses issue

Hi. I'm trying to output frequency (in the 1,250 Hz to 1,750 Hz range) on GPIO. Each frequency should be outputted for 5ms time. For that, I use 2 TIMERs: one for 5ms counter and one for frequency output + PPI + GPIOTE. I have a lookup array with "tones" for certain frequencies. When the 5ms timer fires up I pass the next value from the array to the frequency output timer as the CC value.

The problem is when frequency outputs I can see some dropouts in frequency with logic analyzer. These dropouts occur in different moments but in most cases, they last about 4ms.

I expect to frequency change without any dropouts and pauses. What I'm doing wrong?

Here is the code
(based on ...\nRF5_SDK_17.0.2_d674dde\examples\peripheral\timer)

#define GPIO_FREQ_OUT 4
static const nrf_drv_timer_t timer_inst_t5ms = NRF_DRV_TIMER_INSTANCE(1); //!don't use TIMER0 with softdevice
static const nrf_drv_timer_t timer_inst_freq = NRF_DRV_TIMER_INSTANCE(3); //!don't use TIMER0 with softdevice
static nrf_ppi_channel_t     m_ppi_channel;
uint16_t tone_member = 1;
uint32_t timer_5ms_counter = 0;

/**
 * @brief Handler for timer events.
 */
void t5ms_timer_event_handler(nrf_timer_event_t event_type, void *p_context)
{
    switch (event_type)
    {
    case NRF_TIMER_EVENT_COMPARE0:
        nrf_gpio_pin_toggle(3);
        fm_set_duty(tone_array[tone_member]);
        //**********tone_member table go up
        if (tone_member < TONE_TABLE_MEMBERS)
        {
           tone_member++;
        }
        else if (tone_member >= TONE_TABLE_MEMBERS)
        {
           tone_member = 0;
           nrf_drv_timer_disable(&timer_inst_t5ms);
           nrf_drv_timer_disable(&timer_inst_freq);
           nrf_drv_ppi_channel_disable(m_ppi_channel);
           nrf_drv_gpiote_out_task_disable(GPIO_FREQ_OUT);
        }
        //**********tone table go up
        break;
    }
}

void fm_set_duty(uint32_t period)
{
    nrf_drv_timer_extended_compare(&timer_inst_freq,
                                 NRF_TIMER_CC_CHANNEL0,
                                 period,
                                 NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                 false);
}

/**
 * @brief Function for main application entry.
 */
int main(void)
{
    uint32_t time_ticks;
    uint32_t err_code = NRF_SUCCESS;

    err_code = nrf_drv_ppi_init();
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_gpiote_init();
    APP_ERROR_CHECK(err_code);

    //>>>GPIOTE init
    nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);

    err_code = nrf_drv_gpiote_out_init(GPIO_FREQ_OUT, &config);
    APP_ERROR_CHECK(err_code);
    //<<<GPIOTE init

    ////>>>TIMER init
    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_16;
    err_code = nrf_drv_timer_init(&timer_inst_freq, &timer_cfg, freq_timer_event_handler);
    APP_ERROR_CHECK(err_code);

    nrf_drv_timer_extended_compare(&timer_inst_freq,
                                   NRF_TIMER_CC_CHANNEL0,
                                   tone_array[0],
                                   NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                   false);
    ////<<<<TIMER init

    //>>>PPI init
    err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel);
    APP_ERROR_CHECK(err_code);

    uint32_t compare_evt_addr;
    uint32_t gpiote_task_addr;
    compare_evt_addr = nrf_drv_timer_event_address_get(&timer_inst_freq, NRF_TIMER_EVENT_COMPARE0);
    gpiote_task_addr = nrf_drv_gpiote_out_task_addr_get(GPIO_FREQ_OUT);

    err_code = nrf_drv_ppi_channel_assign(m_ppi_channel, compare_evt_addr, gpiote_task_addr);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_ppi_channel_enable(m_ppi_channel);
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_out_task_enable(GPIO_FREQ_OUT);
    //<<<PPI init

    ////>>>TIMER init
    timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32;

    err_code = nrf_drv_timer_init(&timer_inst_t5ms,
                                  &timer_cfg,
                                  t5ms_timer_event_handler);
    APP_ERROR_CHECK(err_code);

    time_ticks = nrf_drv_timer_ms_to_ticks(&timer_inst_t5ms, 5);

    nrf_drv_timer_extended_compare(&timer_inst_t5ms,
                                   NRF_TIMER_CC_CHANNEL0,
                                   time_ticks,
                                   NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                   true);

    nrf_drv_timer_enable(&timer_inst_t5ms);
    ////<<<<TIMER init

    nrf_drv_timer_enable(&timer_inst_freq);

    //>>>GPIO init
    nrf_gpio_cfg_output(3);
    //<<<GPIO init

    while (1)
    {
        __WFI();
    }
}


const uint16_t tone_array[1024] = {
6400, 6398, 6395, 6393, 6390, 6388, 6385, 6383, 6380, 6378, 6375, 6373, 6370, 6368, 6365, 6363,
6360, 6358, 6356, 6353, 6351, 6348, 6346, 6343, 6341, 6338, 6336, 6333, 6331, 6329, 6326, 6324,
6321, 6319, 6316, 6314, 6311, 6309, 6307, 6304, 6302, 6299, 6297, 6295, 6292, 6290, 6287, 6285,
6282, 6280, 6278, 6275, 6273, 6270, 6268, 6266, 6263, 6261, 6258, 6256, 6254, 6251, 6249, 6247,
6244, 6242, 6239, 6237, 6235, 6232, 6230, 6228, 6225, 6223, 6220, 6218, 6216, 6213, 6211, 6209,
6206, 6204, 6202, 6199, 6197, 6195, 6192, 6190, 6188, 6185, 6183, 6181, 6178, 6176, 6174, 6171,
6169, 6167, 6164, 6162, 6160, 6157, 6155, 6153, 6150, 6148, 6146, 6143, 6141, 6139, 6137, 6134,
6132, 6130, 6127, 6125, 6123, 6121, 6118, 6116, 6114, 6111, 6109, 6107, 6105, 6102, 6100, 6098,
6095, 6093, 6091, 6089, 6086, 6084, 6082, 6080, 6077, 6075, 6073, 6071, 6068, 6066, 6064, 6062,
6059, 6057, 6055, 6053, 6050, 6048, 6046, 6044, 6042, 6039, 6037, 6035, 6033, 6030, 6028, 6026,
6024, 6022, 6019, 6017, 6015, 6013, 6011, 6008, 6006, 6004, 6002, 6000, 5997, 5995, 5993, 5991,
5989, 5986, 5984, 5982, 5980, 5978, 5975, 5973, 5971, 5969, 5967, 5965, 5962, 5960, 5958, 5956,
5954, 5952, 5949, 5947, 5945, 5943, 5941, 5939, 5936, 5934, 5932, 5930, 5928, 5926, 5924, 5921,
5919, 5917, 5915, 5913, 5911, 5909, 5907, 5904, 5902, 5900, 5898, 5896, 5894, 5892, 5890, 5887,
5885, 5883, 5881, 5879, 5877, 5875, 5873, 5871, 5868, 5866, 5864, 5862, 5860, 5858, 5856, 5854,
5852, 5850, 5848, 5845, 5843, 5841, 5839, 5837, 5835, 5833, 5831, 5829, 5827, 5825, 5823, 5820,
5818, 5816, 5814, 5812, 5810, 5808, 5806, 5804, 5802, 5800, 5798, 5796, 5794, 5792, 5790, 5788,
5786, 5784, 5781, 5779, 5777, 5775, 5773, 5771, 5769, 5767, 5765, 5763, 5761, 5759, 5757, 5755,
5753, 5751, 5749, 5747, 5745, 5743, 5741, 5739, 5737, 5735, 5733, 5731, 5729, 5727, 5725, 5723,
5721, 5719, 5717, 5715, 5713, 5711, 5709, 5707, 5705, 5703, 5701, 5699, 5697, 5695, 5693, 5691,
5689, 5687, 5685, 5683, 5681, 5679, 5677, 5675, 5673, 5671, 5669, 5667, 5666, 5664, 5662, 5660,
5658, 5656, 5654, 5652, 5650, 5648, 5646, 5644, 5642, 5640, 5638, 5636, 5634, 5632, 5630, 5629,
5627, 5625, 5623, 5621, 5619, 5617, 5615, 5613, 5611, 5609, 5607, 5605, 5604, 5602, 5600, 5598,
5596, 5594, 5592, 5590, 5588, 5586, 5584, 5583, 5581, 5579, 5577, 5575, 5573, 5571, 5569, 5567,
5565, 5564, 5562, 5560, 5558, 5556, 5554, 5552, 5550, 5549, 5547, 5545, 5543, 5541, 5539, 5537,
5535, 5534, 5532, 5530, 5528, 5526, 5524, 5522, 5520, 5519, 5517, 5515, 5513, 5511, 5509, 5507,
5506, 5504, 5502, 5500, 5498, 5496, 5495, 5493, 5491, 5489, 5487, 5485, 5484, 5482, 5480, 5478,
5476, 5474, 5473, 5471, 5469, 5467, 5465, 5463, 5462, 5460, 5458, 5456, 5454, 5452, 5451, 5449,
5447, 5445, 5443, 5442, 5440, 5438, 5436, 5434, 5433, 5431, 5429, 5427, 5425, 5424, 5422, 5420,
5418, 5416, 5415, 5413, 5411, 5409, 5408, 5406, 5404, 5402, 5400, 5399, 5397, 5395, 5393, 5391,
5390, 5388, 5386, 5384, 5383, 5381, 5379, 5377, 5376, 5374, 5372, 5370, 5369, 5367, 5365, 5363,
5362, 5360, 5358, 5356, 5354, 5353, 5351, 5349, 5348, 5346, 5344, 5342, 5341, 5339, 5337, 5335,
5334, 5332, 5330, 5328, 5327, 5325, 5323, 5321, 5320, 5318, 5316, 5315, 5313, 5311, 5309, 5308,
5306, 5304, 5302, 5301, 5299, 5297, 5296, 5294, 5292, 5290, 5289, 5287, 5285, 5284, 5282, 5280,
5278, 5277, 5275, 5273, 5272, 5270, 5268, 5267, 5265, 5263, 5262, 5260, 5258, 5256, 5255, 5253,
5251, 5250, 5248, 5246, 5245, 5243, 5241, 5240, 5238, 5236, 5235, 5233, 5231, 5230, 5228, 5226,
5225, 5223, 5221, 5220, 5218, 5216, 5215, 5213, 5211, 5210, 5208, 5206, 5205, 5203, 5201, 5200,
5198, 5196, 5195, 5193, 5191, 5190, 5188, 5186, 5185, 5183, 5181, 5180, 5178, 5177, 5175, 5173,
5172, 5170, 5168, 5167, 5165, 5163, 5162, 5160, 5159, 5157, 5155, 5154, 5152, 5150, 5149, 5147,
5146, 5144, 5142, 5141, 5139, 5138, 5136, 5134, 5133, 5131, 5129, 5128, 5126, 5125, 5123, 5121,
5120, 5118, 5117, 5115, 5113, 5112, 5110, 5109, 5107, 5105, 5104, 5102, 5101, 5099, 5098, 5096,
5094, 5093, 5091, 5090, 5088, 5086, 5085, 5083, 5082, 5080, 5079, 5077, 5075, 5074, 5072, 5071,
5069, 5067, 5066, 5064, 5063, 5061, 5060, 5058, 5057, 5055, 5053, 5052, 5050, 5049, 5047, 5046,
5044, 5042, 5041, 5039, 5038, 5036, 5035, 5033, 5032, 5030, 5029, 5027, 5025, 5024, 5022, 5021,
5019, 5018, 5016, 5015, 5013, 5012, 5010, 5009, 5007, 5005, 5004, 5002, 5001, 4999, 4998, 4996,
4995, 4993, 4992, 4990, 4989, 4987, 4986, 4984, 4983, 4981, 4980, 4978, 4977, 4975, 4973, 4972,
4970, 4969, 4967, 4966, 4964, 4963, 4961, 4960, 4958, 4957, 4955, 4954, 4952, 4951, 4949, 4948,
4946, 4945, 4943, 4942, 4940, 4939, 4937, 4936, 4934, 4933, 4931, 4930, 4929, 4927, 4926, 4924,
4923, 4921, 4920, 4918, 4917, 4915, 4914, 4912, 4911, 4909, 4908, 4906, 4905, 4903, 4902, 4900,
4899, 4898, 4896, 4895, 4893, 4892, 4890, 4889, 4887, 4886, 4884, 4883, 4881, 4880, 4879, 4877,
4876, 4874, 4873, 4871, 4870, 4868, 4867, 4865, 4864, 4863, 4861, 4860, 4858, 4857, 4855, 4854,
4852, 4851, 4850, 4848, 4847, 4845, 4844, 4842, 4841, 4840, 4838, 4837, 4835, 4834, 4832, 4831,
4830, 4828, 4827, 4825, 4824, 4822, 4821, 4820, 4818, 4817, 4815, 4814, 4812, 4811, 4810, 4808,
4807, 4805, 4804, 4803, 4801, 4800, 4798, 4797, 4796, 4794, 4793, 4791, 4790, 4789, 4787, 4786,
4784, 4783, 4782, 4780, 4779, 4777, 4776, 4775, 4773, 4772, 4770, 4769, 4768, 4766, 4765, 4763,
4762, 4761, 4759, 4758, 4757, 4755, 4754, 4752, 4751, 4750, 4748, 4747, 4745, 4744, 4743, 4741,
4740, 4739, 4737, 4736, 4734, 4733, 4732, 4730, 4729, 4728, 4726, 4725, 4724, 4722, 4721, 4719,
4718, 4717, 4715, 4714, 4713, 4711, 4710, 4709, 4707, 4706, 4705, 4703, 4702, 4700, 4699, 4698,
4696, 4695, 4694, 4692, 4691, 4690, 4688, 4687, 4686, 4684, 4683, 4682, 4680, 4679, 4678, 4676,
4675, 4674, 4672, 4671, 4670, 4668, 4667, 4666, 4664, 4663, 4662, 4660, 4659, 4658, 4656, 4655,
4654, 4652, 4651, 4650, 4648, 4647, 4646, 4644, 4643, 4642, 4640, 4639, 4638, 4636, 4635, 4634,
4633, 4631, 4630, 4629, 4627, 4626, 4625, 4623, 4622, 4621, 4619, 4618, 4617, 4616, 4614, 4613,
4612, 4610, 4609, 4608, 4606, 4605, 4604, 4603, 4601, 4600, 4599, 4597, 4596, 4595, 4594, 4592,
4591, 4590, 4588, 4587, 4586, 4584, 4583, 4582, 4581, 4579, 4578, 4577, 4576, 4574, 4573, 4572
};


My setup:
nRF52832 (NRF52 DK)
SDK 17.0.2
SES 5.5
SoftDevice none (but in future this code must with it)

Logic analyzer screenshots (bottom channel is a visualization of the 5ms timer)




Hope you can help me. I'm out of ideas.

  • Sorry for the typo in frequency. 
    My freq_timer_event_handler() is just empty. As In some examples on SDK. 


    void freq_timer_event_handler(nrf_timer_event_t event_type, void *p_context)
    {
    }

  • Could you try to stop the timer when setting the new CC value, and see if that helps?

    void fm_set_duty(uint32_t period)
    {
    
      nrf_drv_timer_disable(&timer_inst_freq);
      nrf_drv_timer_clear(&timer_inst_freq);
      nrf_drv_timer_extended_compare(&timer_inst_freq,
                                     NRF_TIMER_CC_CHANNEL0,
                                     period,
                                     NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                     false);
      nrf_drv_timer_enable(&timer_inst_freq);
    
    }

  • Sure. I tried your suggestion but it doesn't resolve our issue.
    Same 4ms pauses from time to time and shorter pauses on each tick off 5ms  timer.

    I tried with both disabling and clearing

    void fm_set_duty(uint32_t period)
    {
    
      nrf_drv_timer_disable(&timer_inst_freq);
      nrf_drv_timer_clear(&timer_inst_freq);
      nrf_drv_timer_extended_compare(&timer_inst_freq,
                                     NRF_TIMER_CC_CHANNEL0,
                                     period,
                                     NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                     false);
      nrf_drv_timer_enable(&timer_inst_freq);
    }

    and only with disabling
    void fm_set_duty(uint32_t period)
    {
    
      nrf_drv_timer_disable(&timer_inst_freq);
      nrf_drv_timer_extended_compare(&timer_inst_freq,
                                     NRF_TIMER_CC_CHANNEL0,
                                     period,
                                     NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK,
                                     false);
      nrf_drv_timer_enable(&timer_inst_freq);
    }

    without any luck.

  • Looks like your array index is out of bounds. (tone_array[1024] is not valid). Try this t5ms_timer_event_handler instead:

    void t5ms_timer_event_handler(nrf_timer_event_t event_type, void *p_context)
    {
        switch (event_type)
        {
            case NRF_TIMER_EVENT_COMPARE0:
                nrf_gpio_pin_toggle(3);
                fm_set_duty(tone_array[tone_member]);
                //**********tone_member table go up
                if (tone_member < (TONE_TABLE_MEMBERS-1))
                {
                    tone_member++;
                }
                else if (tone_member >= (TONE_TABLE_MEMBERS-1))
                {
                    tone_member = 0;
                    // nrf_drv_timer_disable(&timer_inst_t5ms);
                    // nrf_drv_timer_disable(&timer_inst_freq);
                    // nrf_drv_ppi_channel_disable(m_ppi_channel);
                    // nrf_drv_gpiote_out_task_disable(GPIO_FREQ_OUT);
                }
                //**********tone table go up
    
                //************30 sec ramp from tone table******
                if (timer_5ms_counter >= 6000)
                {
                    nrf_drv_timer_disable(&timer_inst_t5ms);
                    nrf_drv_timer_disable(&timer_inst_freq);
                    nrf_drv_ppi_channel_disable(m_ppi_channel);
                    nrf_drv_gpiote_out_task_disable(GPIO_FREQ_OUT);
                }
                timer_5ms_counter++;
                break;
        }
    }

  • Thanks for pointing on that! Can't believe that I can miss that.

    I tested with correct bounds and if I didn't perform a CLEAR task there are 4ms pauses.


    They are caused by Counter overflow? Also, I noticed that pauses only appear when both timers are triggered at the same time. Why this is so?

    The second test was with the CLEAR task on each 5ms timer trigger. This time there are no 4ms pauses, which is good. But as before we got a little pause on each 5ms tick.



    So now we have 2 situations but none of them suits our needs. Any ideas?

Related