Question

I have one high priority interrupt which sends USB data, and one lower priority task which already fetches the next data to be send.

Sometimes the high priority interrupt requires some data that is still being fetched, and in that case I need to instruct the MCU to finish the lower priority task before continuing execution in the high priority interrupt.

I can't figure out how to make this work. Is it possible to raise the priority of the background task higher using NVIC_SetPriority, and immediately call NVIC_SetPendingIRQ from the USB task, and after that lower it again? Or what would be the simplest way to make this work?

Was it helpful?

Solution

How much time do you have to answer the data request, and how long does it take to prefetch for the next one? If the prefetch time is short, I would reverse your priority on your interrupts - this keeps the buffer filled for the data request interrupt.

Otherwise there isn't a clean way to do what you want bare-metal - this is what Operating Systems are for. If you are in an OS, the data request interrupt routine can request a signal from the prefetch interrupt routine and return from interrupt and wait for the data request interrupt routine to send a signal that it has completed a block.

Bare-metal, you could try having the prefetch routine call the data request interrupt after each buffer is ready. The DRIR then does a series of checks when it wakes up

  • Was I woken by a Data Request?
    • yes: Do I have data to send?
      • yes: Send data, clear interrupt request, return from interrupt
      • no: Increment "blocks needed" counter by 1, clear interrupt request, return from interrupt
    • no: must have been woken by a Prefetch complete, is "blocks needed" zero?
      • yes: buffer has data, but not needed yet, return
      • no: Send 1 block of data, decrement "blocks needed" until it hits zero or buffer is empty, return

There isn't any guarantee you will get the data out in time, but at least this way there's a chance for the lower priority interrupt to finish.

BTW, I don't think the NVIC can force a currently-executing interrupt to stop for a different higher-priority one. The priorities really matter when the interrupts occur at the same time (or occur when interrupts are already masked, ie when servicing another interrupt).

Many operating systems provide a two-step interrupt process where the direct interrupt routine is minimal as possible to clear the interrupt, and it notifies a separate interrupt thread to handle the longer, detailed parts of the request. See http://en.wikipedia.org/wiki/Interrupt_handler

Since the direct interrupt routine is small&fast, it allows for priorities to be assigned to the respective interrupt threads to control execution order.

OTHER TIPS

I don't know if you have a good reason to run RX and TX in two different contexts, but usually this could be very simply implemented in only one context. However, if you really want to follow your original design, you need to introduce some kind of a mechanism to synchronize operations of these two contexts. Normally, if you're running the RTOS, you would use event flag, binary semaphore or some other similar service which is provided by the given RTOS.

You would not want (and could not) send any data before you receive some, right? That's why you would need to wait for a notification (in TX context) which is to be set from RX context after the data was received.

Having done this kind of tunneling without employing this technique would go out of sync very soon.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top