[nRF52833] TIMER3 does not enter IRQ and keeps going

Hello,

I am trying to use TIMER3 where it should count 1ms ticks for 15 seconds and then stop.

Tried the below code. However it never enters ISR. 

Please let me know if I am configuring it incorrectly or something else.

As Channel 0 is being used by Timer 2 already, I have chosen channel 3.

Also tried setting priority to 3.

// Timer tick duration (1 ms = 16000 ticks at 16 MHz)
#define TIMER_TICK_1MS   16000

// Total duration (15 seconds = 15000 ms)
#define TIMER_DURATION_15S   (15000 * TIMER_TICK_1MS)


void hw_timer3_init(uint32_t tick_count) 
{

    // Stop Timer 3 before configuring
    nrf_timer_task_trigger(NRF_TIMER3, NRF_TIMER_TASK_STOP);
    // Configure TIMER3 in Timer mode
    nrf_timer_mode_set(NRF_TIMER3, NRF_TIMER_MODE_TIMER);
    // Set frequency to 16 MHz
    nrf_timer_frequency_set(NRF_TIMER3, NRF_TIMER_FREQ_16MHz);
    // Set the timer to 32-bit mode
    nrf_timer_bit_width_set(NRF_TIMER3, NRF_TIMER_BIT_WIDTH_32);
    // Set the compare value (tick_count)
    nrf_timer_cc_write(NRF_TIMER3, NRF_TIMER_CC_CHANNEL3, tick_count);
    // Enable interrupt for compare event on channel 3
    nrf_timer_int_enable(NRF_TIMER3, NRF_TIMER_INT_COMPARE3_MASK);
    // Enable TIMER3 interrupt in NVIC
    NVIC_EnableIRQ(TIMER3_IRQn);
    // Configure the timer to auto-clear on compare match
    nrf_timer_shorts_enable(NRF_TIMER3, NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK);
}

void TIMER3_IRQHandler(void) 
{
    // Check for COMPARE3 event
    if (nrf_timer_event_check(NRF_TIMER3, NRF_TIMER_EVENT_COMPARE3)) 
    {
        nrf_timer_event_clear(NRF_TIMER3, NRF_TIMER_EVENT_COMPARE3);  // Clear the event

        // Stop the timer
        nrf_timer_task_trigger(NRF_TIMER3, NRF_TIMER_TASK_STOP);

        // Set GPIO P1.03 high to indicate timer expiration
        nrf_gpio_pin_toggle(NRF_GPIO_PIN_MAP(1, PIN_P1_03));
    }
}


Starting Timer 3 in main ()

    nrf_timer_task_trigger(NRF_TIMER3, NRF_TIMER_TASK_CLEAR);
    nrf_timer_task_trigger(NRF_TIMER3, NRF_TIMER_TASK_START);

Parents
  • Update:

    I have observed that if there is no processing or printing etc. in main() then the IRQ Handler is hit and if I had some logic like below in main loop,

    g_ticks = timer3_get_ticks();
    NRF_LOG_INFO("T3 g_ticks = %u ", g_ticks); 

    then the Timer3 never goes into the IRQ handler and keeps on running.

  • Hello,

    I also tried to implement single shot hardware timer using instance 1, channel 0 using PPI and GPIOTE.

    However the Timer continues to run even after the single shot period and never enters the ISR also.

    Tried both APIs 

    rf_drv_timer_extended_compare()  and nrf_drv_timer_compare()

    The NRF_TIMER_SHORT_COMPARE0_STOP_MASK does not really stop the timer. 

    The requirement is to use hardware timer for 30s or more and after it's expiry raise a GPIO 

    #define TIMER_TICK_1MS                 16000
    #define TICKS_DURATION_30S             (30000 * TIMER_TICK_1MS)
    
    static void ppi_init(void)
    {
        uint32_t err_code = NRF_SUCCESS;
    
        //Initialize the PPI driver
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
        
       // Allocate the first unused PPI channel 
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel1);
        APP_ERROR_CHECK(err_code);
        
        
        // Assigning task and event endpoints so that the PPI channel triggers the OUT task of the LED_1 GPIO pin on TIMER0 COMPARE[0] match.
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel1,
                                              nrf_drv_timer_event_address_get(&m_timer1, NRF_TIMER_EVENT_COMPARE0),
                                              nrf_drv_gpiote_out_task_addr_get(LED_1)); 
        APP_ERROR_CHECK(err_code);
          
    
        // Enable the PPI channel 
        err_code = nrf_drv_ppi_channel_enable(m_ppi_channel1);
        APP_ERROR_CHECK(err_code);
    }
    
    
    void timer1_event_handler(nrf_timer_event_t event_type, void * p_context)
    {
        switch(event_type)
        {
            case NRF_TIMER_EVENT_COMPARE0:
                nrf_drv_gpiote_out_task_trigger(LED_1);
                NRF_LOG_INFO("Toggle LED1 \r\n");
                break;
            default:
                // Do nothing.
                break;
        }
        
    }
    
    
    static void hw_timer1_init(void) 
    {
        
        ret_code_t err_code;
        
        // Configure the timer to use the default configuration set in sdk_config.h
        nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        
        //Initializing the Timer driver
        err_code = nrf_drv_timer_init(&m_timer1, &timer_cfg, timer1_event_handler);
        APP_ERROR_CHECK(err_code);
        
        /*Configure the timer to generate the COMPARE event after 200*1000UL ticks and enable the shortcut that triggers the CLEAR task on every COMPARE event. */
        
        // nrf_drv_timer_extended_compare(&m_timer1, NRF_TIMER_CC_CHANNEL0, TICKS_DURATION_30S, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK |NRF_TIMER_SHORT_COMPARE0_STOP_MASK, true); // Set last argument to false for Task 3
        nrf_drv_timer_compare(&m_timer1, NRF_TIMER_CC_CHANNEL0, TICKS_DURATION_30S, true);
    
        nrfx_timer_compare_int_enable(&m_timer1,NRF_TIMER_CC_CHANNEL0);
    
        // Turning on the Timer. 
        nrf_drv_timer_enable(&m_timer1);
    }
    
    
    static void gpiote_init(void) 
    {    
        ret_code_t err_code;
        
        // Check wether the GPIOTE driver has been initialized before by any other module, e.g. app_button_init().
        if (!nrf_drv_gpiote_is_init())
        {
            // Initialize the GPIOTE driver
            err_code = nrf_drv_gpiote_init();
            APP_ERROR_CHECK(err_code);
        }
    
        // Configure the GPIO pin so that its toggled every time the OUT task is triggerd
        nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false); 
        
        // Apply the configuration above to the LED_1 GPIO pin.  
        err_code = nrf_drv_gpiote_out_init(LED_1, &config);
        APP_ERROR_CHECK(err_code);
           
        // Enabling the OUT task for the LED_1 GPIO pin.
        nrf_drv_gpiote_out_task_enable(LED_1);
    }
    
    
    int main()
    {
        gpiote_init();  // Initialize GPIO
        ppi_init();     // Initialize PPI
    
        NRF_LOG_INFO("Init and Starting Timer 1");
        hw_timer1_init();
        
        
        for (;;)
        {
            idle_state_handle();
    
            l_ticks = timer1_get_ticks();
            NRF_LOG_INFO(" l_ticks = %u", l_ticks);
            NRF_LOG_FLUSH();
    
            nrf_delay_ms(10000);
        }
    
    }
    
    
    

Reply
  • Hello,

    I also tried to implement single shot hardware timer using instance 1, channel 0 using PPI and GPIOTE.

    However the Timer continues to run even after the single shot period and never enters the ISR also.

    Tried both APIs 

    rf_drv_timer_extended_compare()  and nrf_drv_timer_compare()

    The NRF_TIMER_SHORT_COMPARE0_STOP_MASK does not really stop the timer. 

    The requirement is to use hardware timer for 30s or more and after it's expiry raise a GPIO 

    #define TIMER_TICK_1MS                 16000
    #define TICKS_DURATION_30S             (30000 * TIMER_TICK_1MS)
    
    static void ppi_init(void)
    {
        uint32_t err_code = NRF_SUCCESS;
    
        //Initialize the PPI driver
        err_code = nrf_drv_ppi_init();
        APP_ERROR_CHECK(err_code);
        
       // Allocate the first unused PPI channel 
        err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel1);
        APP_ERROR_CHECK(err_code);
        
        
        // Assigning task and event endpoints so that the PPI channel triggers the OUT task of the LED_1 GPIO pin on TIMER0 COMPARE[0] match.
        err_code = nrf_drv_ppi_channel_assign(m_ppi_channel1,
                                              nrf_drv_timer_event_address_get(&m_timer1, NRF_TIMER_EVENT_COMPARE0),
                                              nrf_drv_gpiote_out_task_addr_get(LED_1)); 
        APP_ERROR_CHECK(err_code);
          
    
        // Enable the PPI channel 
        err_code = nrf_drv_ppi_channel_enable(m_ppi_channel1);
        APP_ERROR_CHECK(err_code);
    }
    
    
    void timer1_event_handler(nrf_timer_event_t event_type, void * p_context)
    {
        switch(event_type)
        {
            case NRF_TIMER_EVENT_COMPARE0:
                nrf_drv_gpiote_out_task_trigger(LED_1);
                NRF_LOG_INFO("Toggle LED1 \r\n");
                break;
            default:
                // Do nothing.
                break;
        }
        
    }
    
    
    static void hw_timer1_init(void) 
    {
        
        ret_code_t err_code;
        
        // Configure the timer to use the default configuration set in sdk_config.h
        nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        
        //Initializing the Timer driver
        err_code = nrf_drv_timer_init(&m_timer1, &timer_cfg, timer1_event_handler);
        APP_ERROR_CHECK(err_code);
        
        /*Configure the timer to generate the COMPARE event after 200*1000UL ticks and enable the shortcut that triggers the CLEAR task on every COMPARE event. */
        
        // nrf_drv_timer_extended_compare(&m_timer1, NRF_TIMER_CC_CHANNEL0, TICKS_DURATION_30S, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK |NRF_TIMER_SHORT_COMPARE0_STOP_MASK, true); // Set last argument to false for Task 3
        nrf_drv_timer_compare(&m_timer1, NRF_TIMER_CC_CHANNEL0, TICKS_DURATION_30S, true);
    
        nrfx_timer_compare_int_enable(&m_timer1,NRF_TIMER_CC_CHANNEL0);
    
        // Turning on the Timer. 
        nrf_drv_timer_enable(&m_timer1);
    }
    
    
    static void gpiote_init(void) 
    {    
        ret_code_t err_code;
        
        // Check wether the GPIOTE driver has been initialized before by any other module, e.g. app_button_init().
        if (!nrf_drv_gpiote_is_init())
        {
            // Initialize the GPIOTE driver
            err_code = nrf_drv_gpiote_init();
            APP_ERROR_CHECK(err_code);
        }
    
        // Configure the GPIO pin so that its toggled every time the OUT task is triggerd
        nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false); 
        
        // Apply the configuration above to the LED_1 GPIO pin.  
        err_code = nrf_drv_gpiote_out_init(LED_1, &config);
        APP_ERROR_CHECK(err_code);
           
        // Enabling the OUT task for the LED_1 GPIO pin.
        nrf_drv_gpiote_out_task_enable(LED_1);
    }
    
    
    int main()
    {
        gpiote_init();  // Initialize GPIO
        ppi_init();     // Initialize PPI
    
        NRF_LOG_INFO("Init and Starting Timer 1");
        hw_timer1_init();
        
        
        for (;;)
        {
            idle_state_handle();
    
            l_ticks = timer1_get_ticks();
            NRF_LOG_INFO(" l_ticks = %u", l_ticks);
            NRF_LOG_FLUSH();
    
            nrf_delay_ms(10000);
        }
    
    }
    
    
    

Children
No Data
Related