CORRECCIÓN: Como Ben (y otros comentaristas) han señalado, borrar la bandera de estado en el código principal es un problema. Las escrituras en campos de bits se implementan normalmente como lectura-modificación-escritura, donde (en tu caso) se lee el byte completo, luego se activa o desactiva un bit, y luego se vuelve a escribir el byte modificado. En pseudo-código, ISRstatus.ISR0 = 0 se convertiría en:
char temp = ISRstatus;
temp &= ~0x01;
ISRstatus = temp;
El problema aquí es que una interrupción puede llegar en medio de esta secuencia. Por ejemplo, digamos que la bandera ISR0 está activada y la interrupción 5 llega. Lo que sucede es:
<interrupt 0>
ISRstatus |= 0x01; //Not really atomic, but it doesn't matter here
<exit interrupt 0>
if (ISRstatus.ISR0)
{
char temp = ISRstatus;
temp &= ~0x01;
<interrupt 5>
ISRstatus |= 0x20; //Not really atomic, but it doesn't matter here
<exit interrupt 5>
ISRstatus = temp;
}
En este ejemplo, ISRstatus debería ser igual a 0x20 después de la sentencia if, pero en su lugar es igual a 0x00. La bandera ISR5 se perdió.
La forma de solucionarlo es desactivar las interrupciones al escribir en la variable global en el código principal. (Las lecturas son seguras siempre que se cargue toda la estructura a la vez, como debería ser para una estructura de 8 bits).
El estándar C no garantiza ningún orden o empaquetamiento particular de los campos de bits. Esto significa que usar campos de bits para acceder a datos almacenados en un formato específico (como campos de registro o de cabecera de paquete) no es portable. Si sólo hay un compilador para tu CPU, la portabilidad no será un problema, así que puedes salirte con la tuya.
Mi interpretación de la norma es que los campos de bits están pensados para ser utilizados exactamente de la forma en que tú los estás utilizando. Sólo hay que tener en cuenta las limitaciones.
EDIT v2: Es probable que el compilador no permita que un campo de un solo bit cruce el límite de una unidad de almacenamiento. El manual de tu compilador debería tener más información, pero puede que necesites un poco de ensayo y error para averiguar los casos extremos. Dado que lo único que te importa son los datos en los campos individuales y no su disposición dentro de la unidad de almacenamiento, esto no debería importar.
Dicho esto, la portabilidad no suele ser una gran preocupación para el código de interrupción, y es poco probable que un compilador cambie la forma en que maneja los campos de bits en una versión más reciente.