Estoy usando arm gcc (CooCox) para programar un descubrimiento STM32F4, y he estado luchando con un problema endian
Estoy muestreando con un ADC de 24 bits a través de SPI. Como están llegando 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 spi en analogin0.spibytes [0] - [2], con [0] como MSB, luego los escupo a través de USART a megabaudios, 8 bits a la vez. No hay problemas.
Los problemas comenzaron cuando intenté pasar los datos a un DAC de 12 bits. Este SPI DAC 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 intentos iniciales consistieron en convertir los dos complementos que el ADC me dio para compensar el binario, al xoringar analogin0.spihalfwords [0] con 0x8000, desplazar el resultado a los 12 bits inferiores y luego agregar el prefijo en forma aritmética.
Increíblemente frustrante, hasta que me doy cuenta de que analogin0.spibytes [0] = 0xFF 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 quedé con la lógica bit a bit 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 de código, es 0xFFB5 y no 0xB5FF, así que todo está bien
Entonces, para preguntas ...
Cortex es nuevo para mí. No recuerdo el intercambio de bytes de PIC en int16, a pesar de que ambas plataformas son poco endian. ¿Es esto correcto?
¿Hay alguna forma más elegante de manejar esto? Sería genial si pudiera poner el ARM7 en modo big-endian. Veo muchas referencias de que Cortex M4 es bi-endian, pero todas las fuentes parecen detenerse antes de decirme cómo . Más específicamente, ¿cómo coloco el STM32f407 en modo big-endian , aún mejor si se puede hacer en gcc. ¿Es SOLO una cuestión de establecer el bit apropiado en el registro AIRCR? ¿Hay alguna ramificación, como tener que configurar el compilador para que coincida, o problemas matemáticos más tarde con bibliotecas inconsistentes?
__REV()
y__REV16()
para revertir bytes.Respuestas:
Los sistemas integrados siempre tendrán el problema big-endian / little-endian. Mi enfoque personal ha sido siempre codificar la memoria interna con el endianiness nativo y hacer cualquier intercambio correcto cuando los datos entran o salen.
Al cargar [0] como MSB, está codificando el valor como big-endian.
Esto indica que el procesador es little-endian.
Si, en cambio, carga el primer valor en [2] y vuelve a trabajar en [0], entonces ha codificado el número entrante como little-endian, esencialmente haciendo el intercambio a medida que ingresa el número. Una vez que esté trabajando con la representación nativa, puede volver a su enfoque original de usar operaciones aritméticas. Solo asegúrese de volverlo a big-endian cuando transmita el valor.
fuente
Con respecto a la recompensa "Realmente quiero saber sobre el modo big endian srm32f4", no hay modo big endian en este chip. STM32F4 hace todo el acceso a la memoria en little endian.
El manual del usuario http://www.st.com/web/en/resource/technical/document/programming_manual/DM00046982.pdf menciona esto en la página 25. Pero hay más. En la página 93 puede ver que hay instrucciones de intercambio endian. REV y REVB para bit inverso y inverso. REV cambiará la endianess para 32 bits y REV16 lo hará para datos de 16 bits.
fuente
Aquí hay un fragmento de código para una corteza M4, compilado con gcc
Desde C, la llamada puede ser:
No sé cómo hacerlo más rápido que esto :-)
fuente
Para CooCox STM32F429 esto está bien:
...
fuente