=====Manipulation de registres matériels par champ de bits=====
Modifier une variable logiciel par champ de bits s'effectue sans problème par le biais suivant :
struct {
bool flag1 :1;
unsigned char flag2 :2;
bool flag3 :1;
bool flag4 :1;
unsigned char flag5 :3;
unsigned char flag6 :6;
} Flags0;
Maintenant, on souhaite que ces données soient stockées dans un registre dont les données survivent à un reset du microtrôleur.
En prenant le cas d'un microcontrôleur ARM, il est possible de stocker ces données dans le registre ''GPREG0'' (à l'adresse ''0x4002404**4**'') accessible par la macro ''%%LPC_RTC->GPREG0%%''.
Mais la modification du flag ''flag6'' va modifier uniquement l'adresse ''0x4002404**5**'' :
ldr r3, [pc, #92] ; Chargement de 0x40024044
movs r2, #40 ; Chargement de la donnée 40 sur un octet
strb r2, [r3, #1] ; Ecriture de 40 dans 0x40024044 + 1
Et là, c'est le drame. Le microcontrôleur va se mettre à écrire n'importe quoi dans le registre ''GPREG0'' puisque la seule instruction qu'il sait traiter correctement pour ce registre est un accès par le début du registre (''0x4002404**4**'').
La seule solution est de passer par une écriture complète du registre. Par exemple :
union UGPreg0 {
struct {
bool flag1 :1;
unsigned char flag2 :2;
bool flag3 :1;
bool flag4 :1;
unsigned char flag5 :3;
unsigned char flag6 :6;
} Flags0;
uint32_t bits;
};
static unsigned char getFlag6() {
UGPreg0 uGPreg0;
uGPreg0.bits = LPC_RTC->GPREG0;
return uGPreg0.Flags0.flag6;
}
static void setFlag6(unsigned char val) {
UGPreg0 uGPreg0;
uGPreg0.bits = LPC_RTC->GPREG0;
uGPreg0.Flags0.flag6 = val;
LPC_RTC->GPREG0 = uGPreg0.bits;
}