Wake up main thread on any interrupt

Hi,

Is there a way to make the main thread to execute after any interrupt? 

For now, I have something like this (ncs 2.7.0): 

in main thread : 

for(;;)
{
    // execute code
    k_sleep(K_FOREVER);
}

In each IRQ handlers (gpio, timers...) 

irq_handler
{
    k_wakeup(mainThreadID);
}

I think that this is error prone, as I can't be sure to fill all handlers, and it could be hard to maintain. Also, what about the native handler I didn't overwrite? 

Is there a way to have a general irq_handler or a hook that could be executed on ANY interrupt, in addition to other regular handlers?

The whole point here is to replace the WFE() instruction I had in a bare metal application.

Thank you for your help

Parents
  • You should be able to use thread suspend and resume as mentioned in this Zephyr documentation to achieve what you want.

    The template code can be something like below

    static struct k_thread *main_thread;
    
    void main(void)
    {
        main_thread = k_current_get();  // Get the main thread handle
    
        for (;;) {
            k_thread_suspend(main_thread);  // Suspend the thread
            ...  // whatever logic you want to continue here if any
        }
    }
    
    And in the irq handler you can do below
    void irq_handler(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
    {
        printk("Interrupt Triggered!\n");
    
        // Resume the main thread
        k_thread_resume(main_thread);
    }
    

  • Hi, thank you for your answer, I will try it, but it doesn't adress the question of an existing general irq_handler. It would be great to have this to be sure to not miss any event (the same way WFE() would not miss any event either).

    [EDIT]  either I use k_sleep/k_wakeup, semaphores or k_thread_suspend/k_thread_resume, it takes 10s for the main thread to execute after the wakeup. here is what I do

    -the main thread run a custom scheduler that pop event from a fifo

    -the main thread goes to sleep or same take or suspend

    -the different irq do a k_wakeup / give the semaphore / k_thread_resume

    -the main thread is supposed to resume right away, but takes 10s. 

    here is the logs with a timestamp like this [time_ms] : 

    [090135]  DIR/app/main:462 m_t
    [090135]  f5340/drv_ble_stack:33 bt
    [090136]  f5340/drv_ble_stack:33 bt
    [090136]  f5340/drv_ble_stack:33 bt
    [090137]  f5340/drv_ble_stack:33 bt
    [090137]  f5340/drv_ble_stack:33 bt
    [090138]  f5340/drv_ble_stack:33 bt
    [090139]  f5340/drv_ble_stack:33 bt
    [090139]  f5340/drv_ble_stack:33 bt
    [090661]  t/nrf5340/drv_timer:79 RTC0_IRQHandler
    [091861]  t/nrf5340/drv_timer:79 RTC0_IRQHandler
    [093061]  t/nrf5340/drv_timer:79 RTC0_IRQHandler
    [094261]  t/nrf5340/drv_timer:79 RTC0_IRQHandler
    [095461]  t/nrf5340/drv_timer:79 RTC0_IRQHandler
    [096662]  t/nrf5340/drv_timer:79 RTC0_IRQHandler
    [097862]  t/nrf5340/drv_timer:79 RTC0_IRQHandler
    [099062]  t/nrf5340/drv_timer:79 RTC0_IRQHandler
    [100140]  DIR/app/main:462 m_t
    [100140]  f5340/drv_ble_stack:33 bt
    [100141]  f5340/drv_ble_stack:33 bt
    [100142]  f5340/drv_ble_stack:33 bt
    [100142]  f5340/drv_ble_stack:33 bt
    [100143]  f5340/drv_ble_stack:33 bt
    [100143]  f5340/drv_ble_stack:33 bt
    [100144]  f5340/drv_ble_stack:33 bt
    [100144]  f5340/drv_ble_stack:33 bt

    "m_t" is when main thread is executed

    "bt" is a BLE action that the main thread execute when needed

    Every 1.2s, the RTC trigger an irq as exepected, and is supposed to wake up the main thread to execute a BLE action.

    But we see that the main thread does not  wake up before 10s, and then pop all BLE actions.

    Why does the main thread not waking up right away? 

    Thank you for your help

  • I also found that if I press a button, the main thread is executed right away : 

    [183536]  t/nrf5340/drv_timer:83 RTC0_IRQHandler
    [184736]  t/nrf5340/drv_timer:83 RTC0_IRQHandler
    [185793]  0/drv_internal_gpio:259 Interrupt received from PIN: 42
    [185794]  DIR/app/XSWIFI/main:470 m_t count 21
    [185794]  f5340/drv_ble_stack:32 bt
    [185795]  f5340/drv_ble_stack:32 bt
    [185805]  t/nrf5340/drv_timer:83 RTC0_IRQHandler
    [185936]  t/nrf5340/drv_timer:83 RTC0_IRQHandler
    [185941]  0/drv_internal_gpio:259 Interrupt received from PIN: 42
    [185942]  DIR/app/XSWIFI/main:470 m_t count 22

    So it seems that k_wakeup is doing what is expected within the gpio handler, but not the rtc0 handler.

    Here is a screenshot of a debug session on k_wakeup : 

    When RT0 handler is called, it breaks at line 1213 and 

    thread->base.thread_state is 128, which is _THREAD_QUEUED. So the function returns. But the thread should be suspended (see the callstack)
    Every 10 sec, it does not break here, and breaks at line 1223, which effectively wakes up the main thread.
    When I click a button, it breaks at line 1223 everytime. I don't think it is normal
    Any help is appreciated
    Regards
  • Ben_Squar3d said:
    So it seems that k_wakeup is doing what is expected within the gpio handler, but not the rtc0 handler.

    Missed to see that you are using RTC0 handler, If you are using BLE with softdevice controller (for difference check this external post)  then RTC0 is a reserved peripheral If you are not using BLE then the RTC0 is available for application to use and if that is the case for you that you are not using BLE and still this doesn't work, then we need to see in your zephyr.dts to see if it is used somewhere else.

Reply
  • Ben_Squar3d said:
    So it seems that k_wakeup is doing what is expected within the gpio handler, but not the rtc0 handler.

    Missed to see that you are using RTC0 handler, If you are using BLE with softdevice controller (for difference check this external post)  then RTC0 is a reserved peripheral If you are not using BLE then the RTC0 is available for application to use and if that is the case for you that you are not using BLE and still this doesn't work, then we need to see in your zephyr.dts to see if it is used somewhere else.

Children
  • Good call,

    It seems I am using softdevice as it is the default value (could you confirm this is the default value for nrf5340?). I have 2 questions :

    1) How can I switch to zephyr BLE stack just to try?  

    CONFIG_BT_LL_SW_SPLIT=y doesn't work : 
    CONFIG_BT_CTRL throw an error regarding the RNG feature... 
    [EDIT] I was putting this in the wrong prj.conf file, I moved it to the cpunet prj file and it is OK, but nothing changes, still the same issue
    2) Until now, we were performing a k_sleep(10ms) in the main, and the ble was working fine while the handler of RTC0 was already present : 
    mHWInterrupt is a quite complex function that handle a list of software timers and execute the callback of the expired timers. BLE and our timer module is working fine. How is it possible? 
    Thank you for your help
    [EDIT] So for it to be event more confusing, it seems we are using Zephyr BLE controller API such as bt_le_adv_start and bt_enable. This would explain why our BLE and our software timers are working
     
    So I would say we use the Zephyr BLE API. This is unclear. 
    Here is the zephyr.dts files (I provided the cpuapp and the cpunet dts)  : 
    Regards
  • Hi,

    Solution was found, I was using IRQ_DIRECT_CONNECT on RTC, and IRQ_CONNECT on gpio, that is why it was working with gpio and not RTC IRQ. IRQ_DIRECT_CONNECT makes scheduling decision to be optionnal.

    Thank you for your help.

Related