Timer compare not matching after rewriting CC register

Had an interresting issue that we have resolved, but we're trying to understand...

We had a timer (TIMER2) running and matching towards CC[3] every 500us. This match results in the ISR being called. In the sISR we updated CC[2] to generate another match to use a GPIOTE to create a pulse.

When we used it this way - we only got very sporadic matches from CC[2]. However, when we do not update CC[2] we get matches every time.

Is there some sort of "protection" that makes so that the match does not happen within a certain amount of time after writing a CC register?

  • I regret to see that nrf52 support is winding down and that these chips are  apparently no longer recommended for new designs although this is nowhere indicated on the Nordic Semiconductor website.

  • Hello,

    Maybe my answer came out a bit wrong, there is nothing wrong with developing with the nRF52-series, if it's critical for your application to resolve your observation I can try to make a case about it internally.

    Kenneth

  • Hi  Kenneth, I would really appreciate further investigation. 

    The application involves a trailing edge dimmer. The effect of the bug I described is that the light will show a flash before going dark when being dimmed lower. 

  • Hi,

    I think you are looking at the wrong place. The times I have seen someone mention "flash before going dark", the problem occurs at the time the PWM reach the max or min value, at this time the PWM driver will normally stop and switch to steady high or low output as a normal gpio (since it doesn't make sense to run it as a PWM at this stage). I have seen number of times that there are small errors during this transition in the PWM driver; disable/enable PWM and configure output high/low is done in the wrong order, thereby for a short period causing inverted output. At least that is where I would have started looking.

    Kenneth

  • Hello Kenneth.

    I am using  nRF_SDK_17.1.0

    This is the  ppi config:

    static void ppi_init(void) //MOSFET switching and mainteance
    {

    uint32_t input_evt_addr;
    uint32_t gpiote_task_addr_set;
    uint32_t gpiote_task_addr_clr;
    uint32_t timer_task_clr;
    uint32_t timer_task_cap;
    uint32_t timer_evt_addr1;
    uint32_t timer_evt_addr2;
    uint32_t vmon1_evt_addr;
    uint32_t vmon2_evt_addr;

    uint32_t tdia_task_cap0;
    uint32_t tdia_task_cap1;
    uint32_t tdia_task_clr;


    // Configure GPIOTE IN event
    nrf_drv_ppi_init();
    nrf_drv_ppi_channel_alloc(&ppi_channel1);
    nrf_drv_ppi_channel_alloc(&ppi_channel2);
    nrf_drv_ppi_channel_alloc(&ppi_channel3);
    nrf_drv_ppi_channel_alloc(&ppi_channel4);
    nrf_drv_ppi_channel_alloc(&ppi_channel5);

    nrfx_gpiote_in_config_t input_config =
    {
    .is_watcher = false,
    .hi_accuracy = true,
    .pull = NRF_GPIO_PIN_NOPULL,
    .sense = NRF_GPIOTE_POLARITY_TOGGLE,
    .skip_gpio_setup = false
    };
    nrfx_gpiote_in_init(Pin_ZC, &input_config, gpiote_event_handler);
    nrfx_gpiote_in_event_enable(Pin_ZC, true); //zero cross

    nrfx_gpiote_out_config_t out_config = NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH;
    nrfx_gpiote_out_init(Pin_DON, &out_config); //MOSFET on

    input_evt_addr = nrfx_gpiote_in_event_addr_get(Pin_ZC);
    gpiote_task_addr_set = nrfx_gpiote_set_task_addr_get(Pin_DON);
    gpiote_task_addr_clr = nrfx_gpiote_clr_task_addr_get(Pin_DON);
    timer_evt_addr1 = nrfx_timer_event_address_get(&m_timer3,NRF_TIMER_EVENT_COMPARE1);
    timer_evt_addr2 = nrfx_timer_event_address_get(&m_timer3,NRF_TIMER_EVENT_COMPARE2);
    timer_task_clr = nrfx_timer_task_address_get(&m_timer3, NRF_TIMER_TASK_CLEAR);
    timer_task_cap = nrfx_timer_task_address_get(&m_timer3, NRF_TIMER_TASK_CAPTURE0);


    nrfx_ppi_channel_assign(ppi_channel1,input_evt_addr, timer_task_cap);
    nrfx_ppi_channel_fork_assign(ppi_channel1, timer_task_clr);
    nrfx_ppi_channel_assign(ppi_channel2, timer_evt_addr1, gpiote_task_addr_clr);
    nrfx_ppi_channel_assign(ppi_channel3, timer_evt_addr2, gpiote_task_addr_set);

    nrfx_ppi_channel_enable(ppi_channel1); // capture and clear timer on zero cross
    nrfx_ppi_channel_enable(ppi_channel2); //MOSFET on (CC1)
    nrfx_ppi_channel_enable(ppi_channel3); //MOSFET off (CC2)

    nrfx_gpiote_out_task_enable(Pin_DON);

Related