J'utilise arm gcc (CooCox) pour programmer une découverte STM32F4, et j'ai lutté avec un problème endian
J'échantillonne avec un ADC 24 bits via SPI. Puisque trois octets arrivent, MSB a d'abord eu l'idée de les charger dans une union pour les rendre (j'espérais quand même!) Un peu plus faciles à utiliser.
typedef union
{
int32_t spilong;
uint8_t spibytes [4];
uint16_t spihalfwords [2];} spidata;
spidata analogin0;
Je charge les données en utilisant des lectures spi dans analogin0.spibytes [0] - [2], avec [0] comme MSB, puis je les recrache via USART à un mégabaud, 8 bits à la fois. Pas de problème.
Les problèmes ont commencé lorsque j'ai essayé de transmettre les données à un DAC 12 bits. Ce DAC SPI veut des mots de 16 bits, qui consistent en un préfixe de 4 bits commençant au MSB, suivi de 12 bits de données.
Les premières tentatives ont consisté à convertir le complément à deux que l'ADC m'a donné pour compenser le binaire, en xorant analogin0.spihalfwords [0] avec 0x8000, en décalant le résultat sur les 12 derniers bits, puis en ajoutant le préfixe arithmétiquement.
Incroyablement frustrant, jusqu'à ce que je remarque que pour analogin0.spibytes [0] = 0xFF et et analogin0.spibytes [1] = 0xB5, analogin0.halfwords [0] était égal à 0xB5FF et non 0xFFB5 !!!!!
Après avoir remarqué cela, j'ai arrêté d'utiliser les opérations arithmétiques et le demi-mot, et je suis resté fidèle à la logique au niveau du bit et aux octets
uint16_t temp=0;
.
.
.
// work on top 16 bits
temp= (uint16_t)(analogin0.spibytes[0])<<8|(uint16_t)(analogin0.spibytes[1]);
temp=temp^0x8000; // convert twos complement to offset binary
temp=(temp>>4) | 0x3000; // shift and prepend with bits to send top 12 bits to DAC A
SPI_I2S_SendData(SPI3,temp); //send to DACa (16 bit SPI words)
... et cela a bien fonctionné. Quand je jette un œil à temp après la première ligne de code, son 0xFFB5, et non 0xB5FF, donc tout va bien
Donc, pour les questions ...
Le cortex est nouveau pour moi. Je ne me souviens pas que PIC ait jamais échangé des octets en int16, même si les deux plates-formes sont peu endiennes. Est-ce correct?
Existe-t-il une manière plus élégante de gérer cela? Ce serait formidable si je pouvais simplement mettre l'ARM7 en mode big-endian. Je vois de nombreuses références au Cortex M4 étant bi-endian, mais toutes les sources semblent s'arrêter de me dire comment . Plus précisément, comment placer le STM32f407 en mode big-endian , encore mieux s'il peut être fait en gcc. Est-ce juste une question de réglage du bit approprié dans le registre AIRCR? Y a-t-il des ramifications, telles que la nécessité de définir le compilateur pour qu'il corresponde, ou des erreurs mathématiques plus tard avec des bibliothèques incohérentes ??