[SOLVED] Data sent over SPI (float, char) becomes garbled when received on Due

Hello, happy new year.

I have a sketch that has been working properly on Uno.
But the same exact sketch is not working properly on Due.
Specifically, the data (float, char) that is sent by nRF24L01 radio, appears garbled when received on Due.

This is part of the same project that I had mentioned earlier.
Please see here for reference.
http://forum.arduino.cc/index.php?topic=289018.0

I am sending the following struct which includes IMU data plus some chars as a message,

typedef struct{
byte PIPE;
float YAW;
float PCH;
char MSG[15]; 
}
A_t;
A_t RFL_STRCT;

And receiving it with the following receive function.

void NRF_RECEIVE(){

if ( radio.available(&pipe_num) )  {

        radio.read( &RFL_STRCT, sizeof(RFL_STRCT) );

        RFL_YAW_STR = String(RFL_STRCT.YAW);
        RFL_PCH_STR = String(RFL_STRCT.PCH);
        RFL_PRX_MSG = String(RFL_STRCT.MSG);

        Serial.print("RFL_YAW_STR: ");
        Serial.println(RFL_YAW_STR);
        Serial.print("RFL_PRX_MSG: ");
        Serial.println(RFL_PRX_MSG);

}

On the UNO, I receive the data properly formatted as expected, for example like so;
RFL_YAW_STR: -168.25
RFL_PCH_STR : 132.65
RFL_PRX_MSG: GTRK,

But on the DUE, I get the same exact data showing up garbled or wrongly terminated/formatted.
RFL_YAW_STR: 0.00
RFL_PCH_STR : 227634315264.00
RFL_PRX_MSG: K,

The sketch is only changed where necessary, so that it compiles and runs on Due, which it does.
But is there something more, that is specific to the Due that has to be changed?

Thanks for your input!

Make sure you have the data order set correctly on both ends. If the SPI is sending the MSB first and the receiver expects the LSB first you will get that kind of corruption.

[In this context, the "B" in LSB and MSB refers to "byte" not "bit".]

On the Uno, the SPI data order is set in the SPCR control register, the bit is called DORD.

I can't find if there's an equivalent setting in the Due's datasheet.

Both processors are little-endian, so multi-byte data items are stored in memory with the LSB first. The Due datasheet makes this clear. The Uno's datasheet doesn't seem to mention it but other forum postings make this claim.

It's also not clear if both chips use the same floating-point format. I think this is driven more by the compiler than the chip itself.

Hello @MorganS

ok, this is getting more complicated than I expected...

Another person on github mentioned the possibility that
arm gcc aligns structure members differently than avr does.

What do you think ?

I will have to do some investigating, but will let you know how things go.

BTW, I expected Due to essentially run the same arduino code that runs on Uno,
with a few extra features added. Was that a miss-understanding on my part,
or is the documentation on here miss-leading?

Thanks again

Yes, the sketch is the same code but the underlying infrastructure is totally different. It's like a Swiss Army knife versus a regular knife. Except the Swiss Army one has some of the tools welded shut (like the RTC and the Ethernet interface) and you're going to cut yourself if you try to use some of the other tools.

useKnife() may look like the same function but the actions to achieve that are totally different between the two knives.

Looking again at the example data you showed, it looks like it "ate" 3 bytes because the "K" is still there at the end. Perhaps the byte is stored on the Due in a 32-bit space and the struct has to include those bytes? I'm guessing. Try it without the byte. That will test the byte-alignment theory. Then put it back by explicitly declaring it as uint32_t on both ends.

When communicating with different architectures, don't use a struct. Send bytes individually or create a higher-level protocol that will encapsulate those differences. A protocol like HTTP (which you're using to read this) is an example of a protocol that allows totally different architectures to communicate.

Ok, I also got similar advice on github, which was the answer in this case.

As you suggest too, structure memory representation is platform specific and you have to care for proper serializing when transporting via network. arm gcc aligns structure members differently than avr does.

I added this into the structure definition to avoid aligning:

typedef struct __attribute__((packed)) {
...

Which makes it show up correctly!