I'm thinking about a method, which works fine on a lot of platforms, but which happens to be kind of actively defeated by the XMEGA hardware.
So, the general dilemma I have is: either I need to escalate my methods (hack around the limitation), or, probably more wisely -- I need to find an alternative method that's more common and general.
The exact situation is this: I have a periodic timer interrupt. Every, say, 256th interrupt, I want to fire an additional low-priority operation.
The operation could potentially run for a long time, so:
1. Interrupts are enabled during it. (Including the timer interrupt, in which case it momentarily ends up on the stack twice.)
2. It's blocked with an "in-function" flag.
The heavy-weight method would be a full task switch, so it runs as an alternate main(), and the various low-priority tasks (including main() itself proper) run whenever. But I'd rather not write or import an RTOS here, that's way overkill...
So what's the matter? The XMEGA has an interrupt controller which apparently cannot be defeated (the status registers are read only). All it's watching for, is that RETI instruction at the end of the ISR.
Simply enabling interrupts, works perfectly fine on an ATMEGA, which has simple interrupt control. It even works on a PC*, give or take what commands you have to send to the PIC to acknowledge the interrupt.
*Old PCs, as in MS-DOS era. Embedded MCUs have more than eclipsed the old PC in capabilities now; I think of vintage PCs more as historic examples of quirky, bulky embedded systems, that happen to have a couple fairly rich peripherals on them (notably, relatively large RAM, graphical output, and disk I/O).
What approach to follow?
It seems to me, a tail call would do just fine. Push the destination function address on the stack, then RETI. The interrupt flag clears, the destination is jumped to, and any interrupt can fire. I don't think this is something I can convince GCC to do, though... sure, it'll do that optimization automatically in a function, but in an ISR?
I could write the ASM, no problem. Not worried about that. But that's admitting I need a hack. As far as I know, this is an uncommon method/problem/situation, but it doesn't feel so uncommon that that kind of hack should be required to solve it.
I don't want to set a flag and check it in main(), because that requires a polling loop. If I ever execute blocking functions in main(), that goes in the crapper. And I already intend on doing just that, and I'd rather not muck up those blocking functions with polling thrown in everywhere...
I could trigger a low-priority interrupt; if there were software interrupts, that'd have potential. There's a dozen peripherals I'm not using at the moment, which could serve as an interrupt source; but that's not very general. What if I end up needing one?
Same goes for pin change interrupts. I do happen to have free GPIOs I could use for this, but that seems hacky as well.
Tim