But reading PORTB and writing it back (to PORTB) can cause RMW issues when a PORTB output bit (0...3) is also used.
Exactly. That's why I've written that real situation is not that bad - there's no fundamental reason to force one to write to PORTB.
The following solution does not use any temporary variables, and it just reads PORTB to clear the mismatch condition, using a simple asm instruction...
Fortunately, when one uses interrupt on change, one usually also checks in ISR which input caused the interrupt - unlike in the simple example of Mince
demonstrating only the rules of IOC application. Reading PORTB and using this information prevents optimizer intervention, so there's no need to use assembly (though writing whole ISR in assembly does have its advantages
BTW, in the present form of asking
's example, both
of the statements accesing PORTB are superfluous, as the conditionals checking bits 4 & 5 already fulfill the requirement of clearing the mismatch condition.
As for the structure of ISR and clearing mismatch condition in a loop, it depends on application how the interrupt should be serviced. Sometimes it's better to end the mismatch condition before any other code to avoid risk of skipping meaningful changes on inputs. And in some cases it makes sense to check if the mismatch condition wasn't a momentary disturbance, like a noise flicker - this also should mostly be done before any other action.