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

nrf9160 interrupts {

Dear Sir.

I have a question regarding the nRF9160 Interrupt procedure.

I have 2 interrupts on my nRF9160 custom board.

The 1st interrupt is an external interrupt every 2mSec.

 Set up for the external interrupt :

 

void AFE4900_Interrupt_Config(void)
{
    gpio_pin_configure(dev_io, GPIO_INT_PIN, GPIO_DIR_IN | GPIO_INT | GPIO_PUD_PULL_UP | GPIO_INT_EDGE);
    gpio_init_callback(&gpio_cb, AFE4900_Interrupt, BIT(GPIO_INT_PIN));
    gpio_add_callback(dev_io, &gpio_cb);
    gpio_pin_enable_callback(dev_io, GPIO_INT_PIN);
}

 

 The 2nd interrupt is 1 hz interrupt (timer interrupt configured by the CPU) :

  

  k_timer_init(&my_timer, my_expiry_function, NULL);

        k_timer_start(&my_timer, K_SECONDS(TIEMR_INTERVAL_SEC),K_SECONDS(TIEMR_INTERVAL_SEC));

 

What happens is that the 1hz timer has a high priority then the external interrupt , 

I measure in the scope and see that external interrupt is shifted by time when the 1hz interrupt occurs.

How can I set the external interrupt to have higher priority than the timer interrupt ?.

Parents
  • Hi,

     

     

    k_timer_init(&my_timer, my_expiry_function, NULL);

     This will run in interrupt priority, which is inherited from the kernel timer instance RTC1, which is hardcoded with this priority:

    https://github.com/nrfconnect/sdk-zephyr/blob/master/drivers/timer/nrf_rtc_timer.c#L102

     

    I wouldn't recommend changing this.

     

    How can I set the external interrupt to have higher priority than the timer interrupt ?.

    GPIOTE needs to have a higher priority than RTC1, which has '1', so you'll need GPIOTE prio to '0'.

    This can be done by creating a $board_name.overlay file (nrf9160_pca10090ns.overlay if using ncs tag v1.2.0, nrf9160dk_nrf9160ns.overlay on current master) holding your configuration:

    &gpiote {
        status = "okay";
        interrupts = <49 0>;
    };

     

    I tested the above with the zephyr/samples/basic/button, where I added this to the button callback:

    void button_pressed(struct device *gpiob, struct gpio_callback *cb,
    		    u32_t pins)
    {
    	printk("Button pressed at %" PRIu32 "\n", k_cycle_get_32());
    	printk("GPIOTE ISR Prio: %d\n", NVIC_GetPriority(GPIOTE1_IRQn));
    	printk("RTC1 ISR Prio: %d\n", NVIC_GetPriority(RTC1_IRQn));
    }

     

    And it now prints this:

    Button pressed at 26472
    GPIOTE ISR Prio: 1
    RTC1 ISR Prio: 2
    

     

    A side note: In DTS, the number is offset by '1' compared to what is read out from the NVIC (NVIC_GetPriority(...)). 0 in DTS -> 1 when you read NVIC directly.

     

    Could you try this and see if it works better?

    You can also consider to use a system workqueue when handling larger non-timing critical logic in interrupt handlers.

     

    Kind regards,

    Håkon

Reply
  • Hi,

     

     

    k_timer_init(&my_timer, my_expiry_function, NULL);

     This will run in interrupt priority, which is inherited from the kernel timer instance RTC1, which is hardcoded with this priority:

    https://github.com/nrfconnect/sdk-zephyr/blob/master/drivers/timer/nrf_rtc_timer.c#L102

     

    I wouldn't recommend changing this.

     

    How can I set the external interrupt to have higher priority than the timer interrupt ?.

    GPIOTE needs to have a higher priority than RTC1, which has '1', so you'll need GPIOTE prio to '0'.

    This can be done by creating a $board_name.overlay file (nrf9160_pca10090ns.overlay if using ncs tag v1.2.0, nrf9160dk_nrf9160ns.overlay on current master) holding your configuration:

    &gpiote {
        status = "okay";
        interrupts = <49 0>;
    };

     

    I tested the above with the zephyr/samples/basic/button, where I added this to the button callback:

    void button_pressed(struct device *gpiob, struct gpio_callback *cb,
    		    u32_t pins)
    {
    	printk("Button pressed at %" PRIu32 "\n", k_cycle_get_32());
    	printk("GPIOTE ISR Prio: %d\n", NVIC_GetPriority(GPIOTE1_IRQn));
    	printk("RTC1 ISR Prio: %d\n", NVIC_GetPriority(RTC1_IRQn));
    }

     

    And it now prints this:

    Button pressed at 26472
    GPIOTE ISR Prio: 1
    RTC1 ISR Prio: 2
    

     

    A side note: In DTS, the number is offset by '1' compared to what is read out from the NVIC (NVIC_GetPriority(...)). 0 in DTS -> 1 when you read NVIC directly.

     

    Could you try this and see if it works better?

    You can also consider to use a system workqueue when handling larger non-timing critical logic in interrupt handlers.

     

    Kind regards,

    Håkon

Children
Related