I'm using arm gcc (CooCox) to program an STM32F4discovery, and I've been wrestling w/ an endian problem
I'm sampling with a 24 bit ADC via SPI. Since three bytes are coming in, MSB first I had the idea of loading them into a union to make them (I hoped, anyway!) a little easier to use.
typedef union
{
int32_t spilong;
uint8_t spibytes [4];
uint16_t spihalfwords [2];} spidata;
spidata analogin0;
I load the data using spi reads into analogin0.spibytes[0]-[2], with [0] as the MSB, then I spit them out via USART at a megabaud, 8 bits at a time. No problems.
The problems started when I tried to pass the data in to a 12 bit DAC. This SPI DAC wants 16 bit words, which consist of a 4 bit prefix starting at the MSB, followed by 12 bits of data.
Initial attempts were to convert the twos complement the ADC gave me to offset binary, by xor-ing analogin0.spihalfwords[0] with 0x8000, shifting the result to the bottom 12 bits, and then adding the prefix on arithmetically.
Incredibly frustrating, until I notice that for analogin0.spibytes[0]=0xFF and and analogin0.spibytes[1]=0xB5, analogin0.halfwords[0] was equal to 0xB5FF and not 0xFFB5!!!!!
After noticing this, I stopped using arithmetic operations and the halfword, and stuck to bitwise logic and the 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)
... and this worked fine. When I peek at temp after the first line of code, its 0xFFB5, and not 0xB5FF, so all is good
So, for questions ...
Cortex is new to me. I can't recall PIC ever byte swapping in int16's, even though both platforms are little endian. Is this correct?
Is there a more elegant way to handle this? It would be great if I could just put the ARM7 into big-endian mode. I'm seeing many references to Cortex M4 being bi-endian, but all the sources seem to stop short of actually telling me how. More specifically, how do I place the STM32f407 into big-endian mode, even better if it can be done in gcc. Is this JUST a matter of setting the appropriate bit in the AIRCR register? Are there any ramifications, such as having to set the compiler to match, or math screwups later with inconsistent libraries??
__REV()
and__REV16()
for reversing bytes. \$\endgroup\$