Zephyr work queue and interrupt

Hello,

We are developing an application using nrf52832 and the ncs 1.8.0.

Since our solution is battery operated we have configures application to sleep by default and wake-up on the interrupt.

In our case, this interrupt is PWM like pulses. So, once we receive the interrupt we wake-up the system and then start processing the interrupt. Since this is PWM like pulses, we have train of interrupts. And our ISR processes this interrupt (basically calculating the pulse width of pwm).

Now, when interrupt is being processed in ISR we need to make some operations based on the pulse width calculated in the ISR. To start this processing, we want to start a thread when first interrupt arrives. So far we tried:
1. Starting a thread from the ISR on first interrupt. However, this fails since thread invocation is not allowed in the ISR.
2. Submit a system work queue from ISR, which in turn starts the thread. This works, but it seems kernel takes time to schedule this work queue (since ISR is always running). It takes extended time to start the thread (in seconds), which is obviously not accepted.
3. Start a timer from ISR and once it expired, start a thread from timer handler. However, this also fails since it's same as case-1. Starting the thread from ISR context.

In work around to this? Is there any example that does something similar?

TIA!

  • Hi,

    Not sure what's the signal frequency and the accuracy needed for your application here, but using PPI+TIMER+GPIOTE is likely the better option here. Here is some code that you can use as a template. https://github.com/sigurdnev/ncs-playground/blob/master/samples/pulse_detector/src/main.c (orginally based on the code in this post PPI Configuration to Count Pulses  )

  • Hi Sigurd,

    Thanks for the reply.

    For our case, we need to know the pulse duration between every PWM pulse and make some necessary decisions. Our PWM duration is in milli seconds range (10-100).

    We already have a code developed and tested that can calculate every PWM pulse duration and calculate the moving average and diff of pules. Currently, how we do this is, we start a thread first that does processing of this Pulse difference data and then we enable the interrupt. This works fine. PPI example, more or less does same thing.

    However, since we have a battery operated device, we are in deep sleep mode by default and we want our system to wake-up when first interrupt arrives and at the same time we want to start that processing thread. However, as I mentioned above we can't start the thread from the interrupt context and if I submit a system Queue from the interrupt context, it kicks of the thread after several seconds.

    We are particularly looking for a way to get around starting a thread before the interrupt arrives. And we want our worker thread to initiate as soon as first interrupt arrives.

    TIA!

  • embeddedER said:
    We are particularly looking for a way to get around starting a thread before the interrupt arrives. And we want our worker thread to initiate as soon as first interrupt arrives.

    Maybe you can use a semaphore. At the start of the processing function:

    k_sem_take(&waiting_for_irq, K_FOREVER);

    in the irq:

    k_sem_give(&waiting_for_iq);

  • Hi Sigurd,

    Thanks. semaphore is what I was thinking to use for synchronization, however, it will still need my thread to be created at the start and then it will always be running in wait state. Since, most of the time we are in deep sleep, I was thinking to start the thread only when needed and then stop it completely (rather then waiting) when not needed.

    Does thread waiting for semaphore in deep sleep consume more power?

    TIA!

  • Hello!

    I assume that by deep sleep you are referring to System OFF mode?

    In that case no threads are running while in System OFF mode and on wakeup the system is reset, so waiting for a semaphore in deep sleep wouldn't make much sense.

    If you are referring to normal sleep/idle mode, then waiting for a semaphore would not consume more power than just idling, and would be the recommended way to wait for an interrupt in a power constrained system.

    Best regards,

    Einar

Related