C'est fou ce qu'on peut apprendre des macros de GCC!
Bon, ceci sort du cadre de mon journal mais je voulais aussi afficher des statistiques/renseignements sur le projet, par exemple le nom du fichier d'entête, l'architecture, les fonctionnalités additionnelles, l'ordre des octets, etc. Après avoir "chipoté" quelques heures de plus, voici ce que j'ai fini par utiliser:
echo -e "#include <avr/io.h>\nvoid main() {}" | sort | \
avr-gcc -E -dM -Os -DF_CPU=16000000 -mmcu=atmega2560 - | \
sed -rn \
-e '/AVR_IOXXX/s/.*\s+"([^"]+)"$/MCU header: 1円/p' \
-e '/__AVR_LIBC_VERSION_STRING__/s/.*\s+"([0-9\-\.]+)"$/AVR libc: version 1円/p' \
-e '/__AVR_DEVICE_NAME__/s/.*\s+(\w+)$/device name: 1円/p' \
-e '/__AVR_ARCH__/s/.*\s+(\w+)$/architecture: avr1円/p' \
-e '/SIGNATURE/{N;N;s/#define\s+SIG\w+//g;s/\n/,/g;s/^/signature:/gp}' \
-e '/RAMSIZE/s/.*\s+([0-9]+)$/RAM size: 1円 bytes/gp' \
-e '/E2SIZE/s/.*\s+([0-9]+)$/EEPROM size: 1円 bytes/gp' \
-e '/__SIZEOF_(SHORT|INT|LONG|FLOAT|POINTER|SIZE_T)__/s/.*__SIZEOF_(\w+)__\s+([0-9]+)$/\L1円 size: 2円 bytes/gp' \
-e '/__BYTE_ORDER__/s/.*__ORDER_(\w+)_ENDIAN__/byte ordering: \L1円 endian/gp' \
-e '/_AVR_HAVE_(MUL|MOVW|E?LPMX?|E?JMP_E?CALL|RAMP[DXYZ])/{s/.*HAVE_(\w+)__.*$/1円/g;H}' \
-e '${x;s/\n|_/ /g;s/^/features:/gp}'
C'est imbitable, hein? C'est normal. Comment ça fonctionne? avr-gcc -E invoque le préprocesseur sans compiler quoi que ce soit. La source est une simple fonction main() avec le fichier d'en-tête minimal, io.h. Dans tout ce bazar, sort est essentiel! Ensuite, vient l'analyse:
la macro __AVR_IOXXX__ contient le nom du fichier d'en-tête spécifique au processeur,
décortiquer __AVR_LIBC_VERSION_STRING__ et ne prendre que la chaîne correspondant à la version de avr-libc,
faire pareil avec __AVR_DEVICE_NAME__ et __AVR_ARCH__,
la signature est répartie sur 3 lignes, du style #define SIGNATURE_[012] 0x[0-9]+; on jumelle ces trois lignes en ne retenant que les valeurs hexadécimales,
les macros RAMSIZE et E2SIZE sont décortiquées comme __AVR_DEVICE_NAME__,
extraire les tailles pour des types intéressants (short, int, float, etc.) en rappelant le nom du type, gentiment converti en minuscules (\L)
faire de même pour l'agencement avec __BYTE_ORDER__, dont on ne retient que le terme du milieu (peut être "LITTLE", "BIG" ou "PDP")
extraire les fonctionnalités __AVR_HAVE_XXX__ et les joindre sur une seule ligne.
Toutes ces transformations sont aussi préfixées par une étiquette. Voici ce que ça donne, par exemple pour un ATmega2560:
architecture: avr6
device name: atmega2560
MCU header: iomxx0_1.h
AVR libc: version 2.1.0
byte ordering: little endian
signature: 0x1E, 0x98, 0x01
float size: 4 bytes
int size: 2 bytes
long size: 4 bytes
pointer size: 2 bytes
short size: 2 bytes
size_t size: 2 bytes
features: ELPM ELPMX JMP CALL1 LPMX MOVW MUL RAMPZ
Dans un autre fil, j'ai avoué que je sed souvent à la difficulté. Ben voilà.
1 Noter que les valeurs JMP et CALL sont liées par un underscore avec la macro _AVR_HAVE_JMP_CALL__. J'ai simplement remplacé dans la foulée ce dernier par un espace, comme le marqueur de fin de ligne.
[^] # Re: Idée pour les autres MCU
Posté par FantastIX . En réponse au journal Un utilitaire pour formater la sortie de avr-objdump. Évalué à 3.
C'est fou ce qu'on peut apprendre des macros de GCC!
Bon, ceci sort du cadre de mon journal mais je voulais aussi afficher des statistiques/renseignements sur le projet, par exemple le nom du fichier d'entête, l'architecture, les fonctionnalités additionnelles, l'ordre des octets, etc. Après avoir "chipoté" quelques heures de plus, voici ce que j'ai fini par utiliser:
echo -e "#include <avr/io.h>\nvoid main() {}" | sort | \
avr-gcc -E -dM -Os -DF_CPU=16000000 -mmcu=atmega2560 - | \
sed -rn \
-e '/AVR_IOXXX/s/.*\s+"([^"]+)"$/MCU header: 1円/p' \
-e '/__AVR_LIBC_VERSION_STRING__/s/.*\s+"([0-9\-\.]+)"$/AVR libc: version 1円/p' \
-e '/__AVR_DEVICE_NAME__/s/.*\s+(\w+)$/device name: 1円/p' \
-e '/__AVR_ARCH__/s/.*\s+(\w+)$/architecture: avr1円/p' \
-e '/SIGNATURE/{N;N;s/#define\s+SIG\w+//g;s/\n/,/g;s/^/signature:/gp}' \
-e '/RAMSIZE/s/.*\s+([0-9]+)$/RAM size: 1円 bytes/gp' \
-e '/E2SIZE/s/.*\s+([0-9]+)$/EEPROM size: 1円 bytes/gp' \
-e '/__SIZEOF_(SHORT|INT|LONG|FLOAT|POINTER|SIZE_T)__/s/.*__SIZEOF_(\w+)__\s+([0-9]+)$/\L1円 size: 2円 bytes/gp' \
-e '/__BYTE_ORDER__/s/.*__ORDER_(\w+)_ENDIAN__/byte ordering: \L1円 endian/gp' \
-e '/_AVR_HAVE_(MUL|MOVW|E?LPMX?|E?JMP_E?CALL|RAMP[DXYZ])/{s/.*HAVE_(\w+)__.*$/1円/g;H}' \
-e '${x;s/\n|_/ /g;s/^/features:/gp}'
C'est imbitable, hein? C'est normal. Comment ça fonctionne?
avr-gcc -Einvoque le préprocesseur sans compiler quoi que ce soit. La source est une simple fonctionmain()avec le fichier d'en-tête minimal,io.h. Dans tout ce bazar,sortest essentiel! Ensuite, vient l'analyse:__AVR_IOXXX__contient le nom du fichier d'en-tête spécifique au processeur,__AVR_LIBC_VERSION_STRING__et ne prendre que la chaîne correspondant à la version deavr-libc,__AVR_DEVICE_NAME__et__AVR_ARCH__,#define SIGNATURE_[012] 0x[0-9]+; on jumelle ces trois lignes en ne retenant que les valeurs hexadécimales,RAMSIZEetE2SIZEsont décortiquées comme__AVR_DEVICE_NAME__,\L)__BYTE_ORDER__, dont on ne retient que le terme du milieu (peut être "LITTLE", "BIG" ou "PDP")__AVR_HAVE_XXX__et les joindre sur une seule ligne.Toutes ces transformations sont aussi préfixées par une étiquette. Voici ce que ça donne, par exemple pour un ATmega2560:
architecture: avr6
device name: atmega2560
MCU header: iomxx0_1.h
AVR libc: version 2.1.0
byte ordering: little endian
signature: 0x1E, 0x98, 0x01
float size: 4 bytes
int size: 2 bytes
long size: 4 bytes
pointer size: 2 bytes
short size: 2 bytes
size_t size: 2 bytes
features: ELPM ELPMX JMP CALL1 LPMX MOVW MUL RAMPZ
Dans un autre fil, j'ai avoué que je
sedsouvent à la difficulté. Ben voilà.La documentation se trouve ici: https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html
1 Noter que les valeurs JMP et CALL sont liées par un underscore avec la macro
_AVR_HAVE_JMP_CALL__. J'ai simplement remplacé dans la foulée ce dernier par un espace, comme le marqueur de fin de ligne.