This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

SAM7X calling function from interrupt

Note: This was originally posted on 5th November 2008 at http://forums.arm.com

I am trying to use a timer interrupt to "Set up" a function call. INstead of setting a flag in the interrupt and then polling that flag I would like the interrupt to call a function as soon as teh interrupt is done, but not during the interrupt.

I tried setting a software (swi) interrupt to fire during the timer interupt, but the problem was that it called the software int immediatley during the timer IRQ and not after. I thought the swi was a lower priotrity int then the timer IRQ (set to priority 7), But I guess not...am I wrong????

Is ther a way to do this?
Possibley use a lower priority IRQ to call a function by "Setting" that IRQ during a higher priority IRQ ?
  • Note: This was originally posted on 6th November 2008 at http://forums.arm.com

    Jacob,

    thanks for the reply:


    "One way to achieve what you're trying to do with the SVC is to trigger another interrupt during your interrupt routine; this will execute once you return, but higher-priority interrupts will execute first. Judging by what you've said, I don't think that's really what you're trying to achieve."



    You are correct.  I think the best way to handle this to to be able to trigger a lower priority interrupt during a higher priority one.  So that as soon as the higher one is complete the lower one will fire.

    The higher priority interrupt is a  timer IRQ priority 7.  SO how and what kind of interrupt can I trigger during my timer IRQ?

    THanks,
    Fred
  • Note: This was originally posted on 6th November 2008 at http://forums.arm.com

    Jacob,

    Can you point me in the right direction to get info on setting up a DFC ?  I am not familiar.
  • Note: This was originally posted on 6th November 2008 at http://forums.arm.com

    I think you've misunderstood...

    You could trigger a higher-priority interrupt during your routine and your routine would still run until it completes. Specifically, it will run until it unmasks the interrupts, which is usually when it exits IRQ (or FIQ) mode.

    I don't recommend setting up another interrupt to run your other code as it's not a terribly clean solution. In particular, that routine will still block other interrupts if you don't have interrupt nesting, so whilst it provides a kind of "yield" functionality, any significant processing you do in the DFC will still affect your interrupt latency.

    If you really want to trigger another interrupt, you will need to use a peripheral on your processor to do that. I can't help you with the specifics, but it's very rare for processors to have a simple "trigger an interrupt" peripheral, so you'll probably need to use another timer (or re-use the one you have).

    I would recommend using a task queue of some kind to register a DFC for execution in system mode; this is a simple solution and is effective in most applications.

    For example, your main (non-IRQ) loop could look like this:

    while (1)
    {
    waitForInterrupt();  // This will typically put the processor in a low-power mode until an interrupt is received.
    // An interrupt is received and (maybe) adds a task to a DFC list.
    runNextDFC();  // This can be interrupted.
    // Note that the implementation of the DFC list must be thread-safe, even if this is implemented by simply masking interrupts whilst it is being modified.
    }
  • Note: This was originally posted on 6th November 2008 at http://forums.arm.com

    In this case, you simply want a list of function pointers. When you want to register a DFC, you add a function pointer to the list. When you run one, you remove it from the list.

    Things to consider:

    The list can be a simple array, but you'll need extra variables to indicate free slots and the like. If I were you, I'd use either a linked list or an array-based circular buffer. Google will have plenty of information on both.

    If you aren't familiar with function pointers, try Google. There's tons of information on the web.

    Your DFCs will probably need some data, so you may need another list of data to provide to the functions. This is entirely dependent on your application, however.


    Good luck :-)
  • Note: This was originally posted on 6th November 2008 at http://forums.arm.com

    Hello there,

    It sounds like you're trying to set up a delayed function call such that your interrupt handler doesn't take very long (and thus doesn't affect the latency of other interrupts too much). Is that assumption correct? It sounds like an OS in which the task scheduler is run on a timer tick.

    There are a number of ways that you can achieve what you're trying to do. A common solution to this problem is to have a DFC (delayed function call) queue. When an interrupt is triggered, your interrupt routine will clear the interrupt and do any necessary maintenance, then add a task to the queue which processes the data. Be careful with this, as the queue can potentially fill up if your timer tick is too fast for your DFC to keep up, so you'll have to tune your system somehow (whether by hand or automatically at run-time).

    Alternatively, if you simply want to have nested interrupts you can switch to system mode in the interrupt handler (for example). You'll need to be careful with processor state (such as the stack pointer) here.

    A note about SWI and SVC:

    A SWI is not really an interrupt, but is more like an exception. It cannot be masked, and is always triggered by an explicit instruction, rather than by an external event of some kind. In fact, the "SWI" instruction has changed and is now called "SVC" in order to reflect this. I think "SVC" stands for "supervisor call"; it allows user-mode code to call functions in supervisor mode via a fixed exception handler (to allow security restrictions to be enforced).

    Note that most assemblers will generally accept either SWI or SVC instructions, but for all intents and purposes they are one and the same and assemble to the same code.

    If you trigger a SVC (SWI) during an IRQ (or FIQ), it will immediately call the SVC handler, just as if an abort or other exception had occurred. If an undefined instruction was encountered during your interrupt routine, you wouldn't expect the core to handle it after the interrupt routine completes, would you? Well, it's the same effect here.

    A note about interrupts:

    The ARM7 core only knows about two interrupts: IRQs and FIQs. It has no notion of interrupt priority, as that is dealt with in the interrupt controller and that is not part of the core. Typically, the interrupt controller will issue the highest priority interrupt to the core, but once an interrupt is running the core will not stop it to service a higher-priority one. You can set up nested interrupts by explicitly unmasking interrupts during your routine, but it's not usually worthwhile and I don't think that's what you're trying to do. (Nesting FIQs into IRQs is probably more common, but that's much easier to do as the core banks the stack pointer and processor state for you.)

    One way to achieve what you're trying to do with the SVC is to trigger another interrupt during your interrupt routine; this will execute once you return, but higher-priority interrupts will execute first. Judging by what you've said, I don't think that's really what you're trying to achieve.

    ----

    There's a lot of information there, but interrupt handling is quite a complex topic. If you could provide more information about exactly what you're aiming to do I might be able to provide more specific information, but it's useful to understand how these things work.