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

Grouping ISRs by priority for overlaying

Just out of curiosity. Is there a way to tell the linker that ISRs have the same priority and thus cannot interrupt each other and can safely be overlayed?

P.S.: And what is the correct passive form of 'to overlay'?

  • Is there a way to tell the linker that ISRs have the same priority and thus cannot interrupt each other and can safely be overlayed?

    I do not think so, (there is no automatic grouping of 'using') but a very intersting idea

    Erik

  • There are linker controls to manually specify the overlaying...

  • I know those and make intense use of them, but aren't interrupts always root nodes?

    Can I create a virtual function that calls them, which really only exists in the call tree and not in the code?

    Should I write a function for each priority level that calls all the ISRs of the same priority? But I'd expect ISRs are subject to a number of special treatments by the compiler and linker. I'm afraid the effects could be quite destructive.

  • Hey, you're right. I use a register bank for each priority level. The using keyword would be an excellent indicator for the linker. I didn't even think about this.

  • I emulated the effect for register bank 1:

    void foo(void) using 1 {
    }
    

    I added the following to my overlays, to make foo a root node and append all the ISRs with the same using directive.

    * ! foo,
    foo ! (ISR_hsk_timer0, ISR_hsk_isr5, ISR_hsk_isr6, ISR_hsk_isr9)
    

    The effect was very minimal:

    Before: Program Size: data=61.3 xdata=246 const=231 code=15429
    After:  Program Size: data=61.0 xdata=246 const=231 code=15425
    

    In hindsight, it's obvious. I think I've only got a single ISR with local variables around. There's not much to optimise. But this might actually allow using more of them, creating more readable code.

  • The effect was very minimal:

    Which, particularly on an 8051, rather strongly hints at an alternative approach following the "Well, don't do that, then!" pattern: just don't use local variables in ISRs, and there will be no need to worry about how best to organize their overlay strategry.

    Interrupts should always be kept as simple as possible. The need for local variables indicates that that principle may have been violated already. RAM consumption that's hard to reduce could be seen as adequate "punishment" for such a transgression.

  • It wouldn't be a proper Keil forum thread unless either Hans or Erik have gone out of their way to add an unnecessary comment that doesn't add anything to the conversation but still allows them to post.

    It's usually just bait to get people to respond so they can pretend to be the victims of an attack and then leverage it put other people down and make them feel better about themselves. Happens all the time around here.

  • You missed Mr Indeed man who really (and I do mean really) likes to feel smug with frequent RTFMs.

  • Too bad, because there exist valid reasons for using local in ISRs. So I still think this actually has some merit. I also think I could gain a little performance here and there by using locals instead of operating entirely on globals and SFRs.

    E.g. the 3 bits I won, are from the four ISRs backing up RMAP (an SFR paging bit on the XC800), before they reset it. I could use a global bit manually, but well ... it's just bad style so I wouldn't do this unless I actually ran out of bits.

    The most compelling example is a result register of the AD-converter. It won't start the next conversion in its queue until it has been read. However I have to store the result somewhere a generic pointer points to. As we all know generic pointers are awfully slow, and it might (and often does) point to XDATA.
    So the first thing I do is copy the result register into a local variable, so the next AD conversion can start.

  • #ifdef ISR_GROUP_1
    extern U8 Variable_for_group_1
    #endif

  • That's what I meant with that sentence:
    I could use a global bit manually, but well ... it's just bad style so I wouldn't do this unless I actually ran out of bits.

    But that's really just doing the overlaying for the compiler. I think I'll actually implement this. I already have a script that generates my overlaying instructions and updates the .uvproj. I'll extend it to do this for me.

  • I expanded my overlay generating script to do this:

    Before:   Program Size: data=61.3 xdata=246 const=231 code=15429
    After:    Program Size: data=61.0 xdata=246 const=231 code=15425
    Scripted: Program Size: data=60.6 xdata=246 const=231 code=15408
    

    It's still not much, but it's something.