Je me lance dans le piratage de microcontrôleurs et, bien que je sois très à l'aise avec les opérateurs bit à bit et que je parle directement au matériel, je trouve que le code qui en résulte est très verbeux et passe-partout. Le programmeur de niveau supérieur en moi veut trouver un moyen efficace mais efficace pour le nettoyer.Une macro préprocesseur C pour empaqueter des champs de bits dans un octet?
Par exemple, il y a beaucoup de drapeaux de réglage dans les registres:
/* Provided by the compiler */
#define SPIE 7
#define SPE 6
#define DORD 5
#define MSTR 5
#define CPOL 4
#define CPHA 3
void init_spi() {
SPCR = (1 << SPE) | (1 << SPIE) | (1 << MSTR) | (1 << SPI2X);
}
Heureusement, il y a des macros qui cachent port réel des opérations d'entrées-sorties (le côté gauche), il ressemble à une simple affectation. Mais toute cette syntaxe est pour moi désordonnée.
Les exigences sont:
- il n'a qu'à gérer jusqu'à 8 bits,
- les positions bit doivent pouvoir être transmis dans un ordre quelconque et
- ne devraient exiger que définis bits à passé.
La syntaxe je voudrais est:
SPCR = bits (SPE, SPIE, MSTR, SPI2X);
Le meilleur que je suis venu avec à ce jour est une macro/fonction combo:
#define bits(...) __pack_bits(__VA_ARGS__, -1)
uint8_t __pack_bits(uint8_t bit, ...) {
uint8_t result = 0;
va_list args;
va_start(args, bit);
result |= (uint8_t) (1 << bit);
for (;;) {
bit = (uint8_t) va_arg(args, int);
if (bit > 7)
break;
result |= (uint8_t) (1 << bit);
}
}
Cette compile 32 octets sur mon architecure particulier et prend 61-345 cycles pour exécuter (en fonction du nombre de les bits ont été passés).
Idéalement, cela devrait être fait en préprocesseur puisque le résultat est une constante, et les instructions de la machine de sortie devraient être juste une affectation d'une valeur de 8 bits à un registre.
Cela peut-il être amélioré?
C'est probablement ce que je ferais si pas pour les définitions de position de bit déjà définies par le support du compilateur spécifique à l'architecture (dans ce cas avr-gcc). Assez bête je pense. S'il y a n'importe où, ils doivent être utilisés autrement que comme un argument de gauche ... Je ne peux pas le trouver. Mais c'est ce que c'est. –
En outre, le code que j'ai vu jusqu'ici varie entre l'utilisation de 1 << formulaire XX, et l'utilisation de _BV (XX). _BV est une macro fournie qui fait (1 << n). Mais cela signifie encore trop de dactylographie. –
bonne idée. mais pour des raisons de sécurité, je voudrais ajouter quelques accolades autour de n #define BIT (n) (1 << (n)) vous savez, les macros peuvent être méchant. Imaginez quelqu'un utilisant la macro avec BIT (5-1) ... – Roland