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

How to implement timer interrupt in nRF9160?

Timer interrupt does not work well. In the code below, LED doesn't turn off and "interrupt!" message is not received. I really appreciate it if you give  me any advice.

#include <nrf9160.h>
#include <zephyr.h>
#include <misc/printk.h>
#include <device.h>
#include <nrf_timer.h>
#include <gpio.h>

#define TIEMR_INTERVAL_SEC 5

struct device *dev;

// make 5 sec timer
// f_timer = 16*1000*1000 / (2^PRESCALER)
// sec_interval = (2^PRESCALER) / 16*1000*1000 x NRF_TIMER0_S->CC[0]
void config_timer()
{		
        NRF_TIMER1->TASKS_STOP = 1;
        NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;
        NRF_TIMER1->TASKS_CLEAR = 1;                             // clear time
        NRF_TIMER1->PRESCALER = 9;                 // value = 0..9
	NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_32Bit;		   //Set counter to 32 bit resolution. MAX count = 2^32-1
	NRF_TIMER1->CC[0] = 156250;  //Set value for TIMER0
        NRF_TIMER1->INTENSET = TIMER_INTENSET_COMPARE1_Enabled << TIMER_INTENSET_COMPARE1_Pos; 
        NVIC_EnableIRQ(TIMER1_IRQn);
        NVIC_SetPriority(TIMER1_IRQn, 0);
}

void TIMER1_IRQHandler(void)
{
	if ((NRF_TIMER1->EVENTS_COMPARE[0] != 0) && ((NRF_TIMER1->INTENSET & TIMER_INTENSET_COMPARE1_Msk) != 0))
        {
                  NRF_TIMER1->EVENTS_COMPARE[0] = 0;           //Clear compare register 0 event	
                  gpio_pin_write(dev, 16, 0);
                  printk("interrupt!\r\n");
        }
}

void main(void)
{
        printk("------------\r\nHello, World!\r\n");
	dev = device_get_binding("GPIO_0");
        gpio_pin_configure(dev, 16, GPIO_DIR_OUT);

        config_timer();
        gpio_pin_write(dev, 16, 1);

        NRF_TIMER1->TASKS_START = 1;
        while(1){
                 printk("Start to sleep\r\n");
                 k_cpu_idle();
                 printk("timer interrupt for %u sec\r\n", TIEMR_INTERVAL_SEC);
        }
}

<>
***** Booting Zephyr OS v1.13.99-ncs2 *****
------------
Hello, World!
Start to sleep
timer interrupt for 5 sec
Start to sleep
// UART communication stops here

Parents
  • Hi,

     

    Try setting the NRF_TIMER1->SHORTS, field COMPARE_CLEAR for CC[0]:

    https://www.nordicsemi.com/DocLib/Content/Product_Spec/nRF9160/latest/timer?673#register.SHORTS

    If this is not set, the timer will have to roll over again to provide a compare event.

     

    Kind regards,

    Håkon

  • Hi, Hakon. Thank you for your reply. I tested the following code, but got fail. Do you know why?

    <main.c>
    #include <nrf9160.h>
    #include <zephyr.h>
    #include <misc/printk.h>
    #include <device.h>
    #include <nrf_timer.h>
    #include <gpio.h>
    
    #define TIEMR_INTERVAL_SEC 5
    
    struct device *dev;
    
    // make 5 sec timer
    // f_timer = 16*1000*1000 / (2^PRESCALER)
    // sec_interval = (2^PRESCALER) / 16*1000*1000 x NRF_TIMER0_S->CC[0]
    void config_timer()
    {		
            NRF_TIMER1->TASKS_STOP = 1;
            NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;
            NRF_TIMER1->TASKS_CLEAR = 1;                             // clear time
            NRF_TIMER1->PRESCALER = 9;                 // value = 0..9
    	NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_32Bit;		   //Set counter to 32 bit resolution. MAX count = 2^32-1
    	NRF_TIMER1->CC[0] = 156250;  //Set value for TIMER0 156250
            NRF_TIMER1->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos;
            NRF_TIMER1->INTENSET = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos; 
            NVIC_SetPriority(TIMER1_IRQn, 1);
            NVIC_EnableIRQ(TIMER1_IRQn);
            NRF_TIMER1->TASKS_START = 1;               // Start TIMER0
    }
    
    void TIMER1_IRQHandler(void)
    {
            gpio_pin_write(dev, 16, 0);
            printk("interrupt!\r\n");
    	if ((NRF_TIMER1->EVENTS_COMPARE[0] != 0) && ((NRF_TIMER1->INTENSET & TIMER_INTENSET_COMPARE0_Msk) != 0))
            {
                      NRF_TIMER1->EVENTS_COMPARE[0] = 0;           //Clear compare register 0 event	
                      gpio_pin_write(dev, 16, 0);
                      printk("interrupt!\r\n");
            }
    }
    
    void main(void)
    {
            printk("------------\r\nHello, World!\r\n");
    	dev = device_get_binding("GPIO_0");
            gpio_pin_configure(dev, 16, GPIO_DIR_OUT);
    
            config_timer();
            gpio_pin_write(dev, 16, 1);
    
            while(1){
                     printk("Start to sleep\r\n");
                     k_cpu_idle();
                     printk("timer interrupt for %u sec\r\n", TIEMR_INTERVAL_SEC);
            }
    }
    
    

    ***** Booting Zephyr OS v1.13.99-ncs2 *****
    ------------
    Hello, World!
    Start to sleep
    timer interrupt for 5 sec
    Start to sleep
    ***** Hardware exception *****
    Current thread ID = 0x2000009c
    Faulting instruction address = 0xf4240
    Fatal fault in ISR! Spinning...

Reply
  • Hi, Hakon. Thank you for your reply. I tested the following code, but got fail. Do you know why?

    <main.c>
    #include <nrf9160.h>
    #include <zephyr.h>
    #include <misc/printk.h>
    #include <device.h>
    #include <nrf_timer.h>
    #include <gpio.h>
    
    #define TIEMR_INTERVAL_SEC 5
    
    struct device *dev;
    
    // make 5 sec timer
    // f_timer = 16*1000*1000 / (2^PRESCALER)
    // sec_interval = (2^PRESCALER) / 16*1000*1000 x NRF_TIMER0_S->CC[0]
    void config_timer()
    {		
            NRF_TIMER1->TASKS_STOP = 1;
            NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer;
            NRF_TIMER1->TASKS_CLEAR = 1;                             // clear time
            NRF_TIMER1->PRESCALER = 9;                 // value = 0..9
    	NRF_TIMER1->BITMODE = TIMER_BITMODE_BITMODE_32Bit;		   //Set counter to 32 bit resolution. MAX count = 2^32-1
    	NRF_TIMER1->CC[0] = 156250;  //Set value for TIMER0 156250
            NRF_TIMER1->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Enabled << TIMER_SHORTS_COMPARE0_CLEAR_Pos;
            NRF_TIMER1->INTENSET = TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos; 
            NVIC_SetPriority(TIMER1_IRQn, 1);
            NVIC_EnableIRQ(TIMER1_IRQn);
            NRF_TIMER1->TASKS_START = 1;               // Start TIMER0
    }
    
    void TIMER1_IRQHandler(void)
    {
            gpio_pin_write(dev, 16, 0);
            printk("interrupt!\r\n");
    	if ((NRF_TIMER1->EVENTS_COMPARE[0] != 0) && ((NRF_TIMER1->INTENSET & TIMER_INTENSET_COMPARE0_Msk) != 0))
            {
                      NRF_TIMER1->EVENTS_COMPARE[0] = 0;           //Clear compare register 0 event	
                      gpio_pin_write(dev, 16, 0);
                      printk("interrupt!\r\n");
            }
    }
    
    void main(void)
    {
            printk("------------\r\nHello, World!\r\n");
    	dev = device_get_binding("GPIO_0");
            gpio_pin_configure(dev, 16, GPIO_DIR_OUT);
    
            config_timer();
            gpio_pin_write(dev, 16, 1);
    
            while(1){
                     printk("Start to sleep\r\n");
                     k_cpu_idle();
                     printk("timer interrupt for %u sec\r\n", TIEMR_INTERVAL_SEC);
            }
    }
    
    

    ***** Booting Zephyr OS v1.13.99-ncs2 *****
    ------------
    Hello, World!
    Start to sleep
    timer interrupt for 5 sec
    Start to sleep
    ***** Hardware exception *****
    Current thread ID = 0x2000009c
    Faulting instruction address = 0xf4240
    Fatal fault in ISR! Spinning...

Children
Related