Invalid payload - only on M0 [solved]

Started by andymcl, June 09, 2019, 10:13:28 PM

andymcl

I have a curious problem that only occurs when using my M0 (I only have 1 at the moment) as a receiver. I had a sketch working with a Moteino as sender and a Moteino as receiver. I changed the receiver to the M0 and I start getting "payload length" errors. The payload structure has remained the same in the sketch which compiled and loaded ok on all occasions.
In an attempt to debug I have fallen back to the RFM69 example send sketch and receive sketch with a payload only of nodeId but still get a payload length error. Since I have no other M0 to test I'm left more than a little puzzled.
I've attached the send sketch, receive sketch and the error message file.
Any suggestions? I can't imagine how the payload can be corrupted like this

TomWS

#1
I suspect that you are experiencing a difference between native data element sizes with your two processors.  If you want to exchange data between two processors of potentially different architectures, you need to:


  • make sure the data size is explicitly stated, ie, don't use 'int', but use 'int16_t'
  • if using a data structure to pass data, make sure it is 'packed', ie, natural 'C' structures will normally be sized and aligned to native data type.  For example, AVR is an 8 bit processor, I believe M0 is a 32 bit processor and structure elements will be normally aligned 32 bits unless you use 'pack' macros in the structure declaration.
  • if you're sending data elements larger than 8 bits, you MUST ensure that the endian-ness is either identical, or managed in pack/unpack code at the two ends of the link. ie, if you send want to exchange 32 data between two processors with different endian types, you should probably send four bytes in known order and at both ends explicitly place/retrieve the MSB in same element at both ends.  UPDATE: Note that this is not an issue in this particular case because the Arduino configuration of M0 sets the endian-ness (it's programmable on ARM processors) to match the AVR processor so common in Arduino platforms.

Examples of misalignment:
struct {
  int i;         // 16 bits on AVR, 32 bits on ARM M0
  int16_t j;  // ok on both, but will be aligned contiguously on AVR, but on a 32 bit boundary on M0
  uint8_t k; // size ok on both, but again, aligned contiguously on AVR, but on a 32 bit boundary on M0
  float     f;  // size ok in both cases as IEEE float is used in this compiler, but alignment would be wrong
} ex1;

// the following is ok on both AVR & M0 because of packed attribute and explicit sizing but will fail if endianess is different
struct {
  int32_t i;   
  int16_t j;  
  uint8_t k;
  float     f;   // size ok, but would cause a machine check on M0 due to misalignment of data type.  This MUST be on a fullword boundary.
}  __attribute__ ((packed)) ex2;

andymcl

You nailed it! I should have thought of that!
thanks for the assistance