Hi, I have one pretty long function (about 0.5ms) that I want to be executed on time, even if other long functions (less important) are running in my main loop. So my Idea was to write this function in an interrupt, that can be interrupted by my other, short interrupts (communication etc.) I am trying to use the IENABLE and IDISABLE macros for the interruptable interrupt, but they don't seem to have any effect (or even cause crashes) I'm using STR91FAM with uvision3 and ARM-ELF-GCC Any ideas?
Rumkugel wrote: > I am trying to use the IENABLE and IDISABLE macros for the interruptable > interrupt, but they don't seem to have any effect (or even cause > crashes) > > I'm using STR91FAM with uvision3 and ARM-ELF-GCC You will have to understand ARM's interrupt mechanism. Simply reenabling interrupts will not work as you might expect. Too long to explain here. http://infocenter.arm.com/help/topic/com.arm.doc.dui0203i/Cacbhjjj.html#Bgbeacfi -- Marcus http://www.doulos.com/arm/
The macros I use for IENABLE and IDISABLE look like this:
1 | #define IENABLE asm(" MRS LR, SPSR"); /* Copy SPSR_irq to LR */ \ |
2 | asm("STMFD SP!, {LR} "); /* Save SPSR_irq */ \ |
3 | asm("MSR CPSR_c, #0x1F "); /* Switch to SYS mode with IRQ enabled*/ \ |
4 | asm("STMFD SP!, {LR} ") ; /* Save SYS mode LR */ |
5 | |
6 | #define IDISABLE asm("LDMFD SP!, {LR}") ; /* Restore SYS mode LR */ \ |
7 | asm("MSR CPSR_c, #0x92") ; /* Switch to IRQ mode with IRQ disabled*/ \ |
8 | asm("LDMFD SP!, {R0}") ; /* Restore SPSR_irq to R0 */ \ |
9 | asm("MSR SPSR_cxsf, R0") ; /* Copy R0 to SPSR_irq */ |
I was thinking about putting my 0.5ms function in an extra interrupt, which I trigger from out of another interrupt (every 2ms). Inside the software-interrupt I tried to use the macros mentioned like this:
1 | void SW_IRQHandler(void) |
2 | {
|
3 | // switch to system mode with IRQ enabled
|
4 | //IENABLE;
|
5 | |
6 | // clear software interrupt
|
7 | VIC1->SWINTCR |= (1 << 15); |
8 | |
9 | // halfmsfunction();
|
10 | |
11 | // switch to IRQ mode with IRQ disabled
|
12 | //IDISABLE;
|
13 | |
14 | // write any value to VIC1 VAR
|
15 | VIC1->VAR = 0xFF; |
16 | }
|
Unfortunately this doesn't work.
Rumkugel wrote: > I was thinking about putting my 0.5ms function in an extra interrupt, > which I trigger from out of another interrupt (every 2ms). What you are trying to do seems overly complicated. As others have suggested, it may even be better calling this function from your super-loop. If the function takes that long to execute I am sure there is already a significant jitter so that deferring the function call adds a negligible overhead. At least you could put that function call into the original interrupt. > Inside the software-interrupt I tried to use the macros mentioned like > this: [...] But what about other interrupts? After IENABLE() any IRQ can now interrupt your SW_IRQHandler(). Are these aware of this and properly save/restore the context? -- Marcus http://www.doulos.com/arm/
I would love to find a way other than nested interrupts... Here's my problem: -Every time a new SPI-package is complete (every 2ms) my 0.5ms routine has to be executed. -Multiple short interrupts are needed for communication etc. -The main loop should be free, so that another developer can simply place his routines (possibly long ones) in there without worrying about my 0.5ms routine being executed The first and second point are no problem and is already running. Now I'm working on the second point, which turns out to be pretty tricky to me, especially since this is all new to me and I have no idea of Assembler. Any Ideas would be very much appreciated
Rumkugel wrote: > -The main loop should be free, so that another developer can simply > place his routines (possibly long ones) in there without worrying about > my 0.5ms routine being executed This cannot work with an interrupt driven system. First of all the "other routines" will have to wait anyway if this 0.5ms routine executes as the super-loop will be preempted. Second, the issue gets actually worse since other developers have no control over when exactly this happens. -- Marcus http://www.doulos.com/arm/
It is no problem if the "other routines" are interrupted. They would not be time-critical anyway. The idea is just to be able to use the remaining controller capacity for some unrelated calculations, which should not disturb the original program. So I was thinking about a hierarchy like this: short interrupts (highest priority) 0.5ms Routine (high priority, time critical) Other big routines (very low priority) The upper part is already working, if the 0.5ms is placed in the super-loop, but now I need a hierarchy level underneath this function. This is why I was thinking about moving it into an interruptible interrupt.
Rumkugel wrote: > So I was thinking about a hierarchy like this: > > short interrupts > (highest priority) > > 0.5ms Routine > (high priority, time critical) > > Other big routines > (very low priority) OK, the picture becomes clearer now. But why this double-nesting of a SPI(?) interrupt triggering a Software Generated Interrupt (SGI, ARM's official term to avoid confusion with SWI/SVC). Just give your SPI interrupt the lowest priority and try to understand how nested interrupts work in ARM based systems. Or use a canned solution. Where do these macros come from? Are you sure that you won't have to do anything else? Look at example code. -- Marcus http://www.doulos.com/arm/
I got those Macros from an Application Note (AN2593), although I have to admit that I do not quite understand everything. It seems like all the descriptions I find on how to implement nested interrupts include Assember code, which I know very little about. I tried to do exactly what you suggested, by putting the function in the SPI interrupt and giving it the lowest priority, but the whole nesting thing doesn't seem to work. Thanks for your help, by the way
Rumkugel wrote: > I got those Macros from an Application Note (AN2593) This takes care of only part of the problem. > It seems like all the descriptions I find on how to implement nested > interrupts include Assember code That is because you need assembler code for implementing nested interrupts on ARM cores (Cortex-M variants being an exception of course). Get yourself a book about ARM processors and start reading -- or a training. Alternatively hire someone to implement this part for you. > I tried to do exactly what you suggested, by putting the function in the > SPI interrupt and giving it the lowest priority, but the whole nesting > thing doesn't seem to work. Of course not. This was only for simplifying the whole thing. Good luck Marcus http://www.doulos.com/arm/
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
Log in with Google account
No account? Register here.