Estoy usando el brazo gcc (CooCox) para programar un STM32F4discovery, y he estado luchando con un problema de endian
Estoy tomando muestras con un ADC de 24 bits a través de SPI. Como están entrando tres bytes, MSB primero tuve la idea de cargarlos en una unión para hacerlos (¡esperaba, de todos modos!) un poco más fáciles de usar.
typedef union
{
int32_t spilong;
uint8_t spibytes [4];
uint16_t spihalfwords [2];} spidata;
spidata analogin0;
Cargo los datos usando lecturas de spi en analogin0.spibytes[0]-[2], con [0] como el MSB, luego los escupo vía USART a un megabarril, 8 bits a la vez. Sin problemas.
Los problemas comenzaron cuando intenté pasar los datos a un DAC de 12 bits. Este DAC SPI quiere palabras de 16 bits, que consisten en un prefijo de 4 bits que comienza en el MSB, seguido de 12 bits de datos.
Los primeros intentos fueron convertir los dos complementos que me dio la ADC para compensar el binario, mediante xor-ing analogin0.spihalfwords[0] con 0x8000, desplazando el resultado a los 12 bits inferiores, y luego agregando el prefijo en aritmética.
Increíblemente frustrante, hasta que noto que para analogin0.spibytes[0]=0xFF y y analogin0.spibytes[1]=0xB5, analogin0.halfwords[0] era igual a 0xB5FF y no 0xFFB5!!!!!
Después de notar esto, dejé de usar operaciones aritméticas y la media palabra, y me apegué a la lógica de bits y los bytes
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)
...y esto funcionó bien. Cuando miro la temperatura después de la primera línea del código, es 0xFFB5, y no 0xB5FF, así que todo está bien.
Así que, para las preguntas...
-
La corteza es nueva para mí. No recuerdo que el PIC haya cambiado de byte en los int16, aunque ambas plataformas son Little Endian. ¿Esto es correcto?
-
¿Hay una forma más elegante de manejar esto? Sería genial si pudiera poner el ARM7 en modo big-endian. Estoy viendo muchas referencias a que la Corteza M4 es bi-endiana, pero todas las fuentes parecen no llegar a decirme cómo . Más específicamente, ¿cómo pongo el STM32f407 en modo big-endian incluso mejor si se puede hacer en GCC. ¿Es sólo cuestión de poner el bit apropiado en el registro del AIRCR? ¿Hay alguna ramificación, como tener que ajustar el compilador para que coincida, o errores matemáticos posteriores con bibliotecas inconsistentes?