1

I am running into a strange behaviour with my code. The following works without problems on an Arduino Nano but it seems to crash on a DUE

void putData64(byte* packet, int pos, uint64_t data)
{
    uint64_t* h= (uint64_t*) (packet+pos+2);
    *h= data;
}

the problematic line seems to be the second one (*h= data) as commenting it out lets the program run without problems.

Similar, the following lines cause a problem on a DUE but run fine on a Nano:

char* data;
// ... data is filled with something
uint64_t* t= (uint64_t*) (data+1);
uint64_t test= *t;

Is there something I am missing?

2
  • 1
    Probably a memory alignment problem. – Majenko Apr 25 '19 at 12:41
  • What are you trying to do? If you want to use bytes and byte pointers, that is okay. If you want to use 64-bit and pointers to it, that is also okay. But you have mixed the two. Why would you want to point halfway to a 64-bit value. I suggest to start over. – Jot Apr 25 '19 at 13:28
1

I concur with Majenko's comment: it's probably a memory alignment problem. I don't know the specifics of the Due, but when you access memory in chunks of 32 bit data words on a 32 bit CPU, it can happen that the architecture requires the data words to be aligned to 32 bit (i.e. 4 byte) boundaries. This means that the address of an uint32_t or uint64_t should be a multiple of 4. Maybe even 8 for a uint64_t, you will have to check.

The only solution to this issue is to fill the packet byte by byte:

void putData64(byte* packet, int pos, uint64_t data)
{
    union {
        uint64_t integer;
        byte bytes[8];
    } h = { .integer = data };
    for (int i = 0; i < 8; i++) {
        packet[pos+2+i] = h.bytes[i];
    }
}

Note that the AVR (in the Nano) is an 8 bit architecture with no alignment constraints whatsoever.

3
  • Thank you. I was aware of the fact of 8bit vs 32bit. I haven't tried your code but it seems right. What did the trick for me in the end was the following: void putData64(byte* packet, int pos, uint64_t data) { uint32_t* out= (uint32_t*) (packet+pos+2); uint32_t* in= (uint32_t*) data; *(out++)= *(in++); *(out++)= *(in++); } – user2912328 Apr 26 '19 at 7:28
  • @user2912328: You mean in = (uint32_t*) &data? Note that, although this could work, it is quite fragile. Unless you can prove that packet+pos+2 is always a multiple of 4, there is a risk that out ends up being an incorrectly aligned (and thus invalid) pointer. If you have no guarantees on the alignment of packet+pos+2, the only valid solution is to copy the data byte by byte. – Edgar Bonet Apr 26 '19 at 11:26
  • yes you are right about both points. Missing & and multiple of 4 – user2912328 Apr 26 '19 at 12:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.