... if they're trampled by a push operation then using one of these as a scratch area while you do the push would not work very well.
... write your ISR handler in assembler, have this save your I/O register in your temp register and then call a 'C'/C++ function for whatever logic you want to code in higher level languages. You sound as if you're comfortable writing in assembler, but if you aren't you could get a starting point by listing the assembler generated for your existing handler.
Excellent suggestion, thanks for the tips! I am not comfortable writing in assembler, so I am going to list the assembler generated and work from there :-) . But, I am comfortable living life on the edge! So I'm going to try it.
My intention is to get the heck out of the way of the compiler as quickly as possible, so I'm thinking I might need 2 assembly instructions: 1 to read the register, the other to save it to a C variable (ie, RAM).
I notice that my idea is not so far fetched, as a matter of fact I found this link:
http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html . The ISR_NAKED is what I want. So, my idea is the following, pseudo-code:
ISR(PCINT0_vect, ISR_NAKED)
{
asm (read_in_register_to_r0)
asm (store_to_ram)
// The following function call will preserve the registers on the stack. Since I haven't
// mucked with any but r0 thus far in my ISR, I should be ok. The function call will
// also restore the necessary registers.
C_function_call();
asm (reti);
}
I notice that the ISR pushes a whole bunch of registers on the stack. Function calls do not necessarily save the same large set. I assume that's because the compiler is smart enough to know that a function may not stomp on all the registers, so it's judicious in its saving. Thus, it seems to me the ISR is storing such a large set because it doesn't have any foreknowledge of what it should or should not preserve, so it paints with a large brush.
But if the *only* thing my ISR does is as listed: 1. my assembly, 2. call a C function, 3. return, then I assume that the heavy lifting of pushing and popping the necessary registers, if handled solely by the C function call in the ISR, should be sufficient. There are no other dragons lying about out, are there? Again, assuming my ISR is just that lean.
Right now my ISR looks like this:
ISR(PCINT0_vect) {
portD.PCint();
}
...so it's doing two bunches of push/pop operations: The entry into the ISR, and the entry into the function call, which is overkill.
...Just checking my assumptions...