I am running into an Hard Fault Exception while copying some data on a micro-controller from one struct to another. I tried different implementations which should do all the same. See my code lines:
memcpy(&msg.data, data, 8);
memcpy(&msg.data, data, sizeof(*data));
memcpy(&msg.data, data, sizeof(msg.data));
msg.data = *data; // Hard Fault
The first three lines are working pretty fine. The last one ends with an Hard Fault Exception. The assembly for the lines with memcpy
is the same. The assembly for the direct assignment differs:
memcpy(&msg.data, data, sizeof(msg.data));
800c480: f107 030c add.w r3, r7, #12
800c484: 330b adds r3, #11
800c486: 2208 movs r2, #8
800c488: 6879 ldr r1, [r7, #4]
800c48a: 4618 mov r0, r3
800c48c: f7f4 f82e bl 80004ec <memcpy>
msg.data = *data; // Hard Fault
800c490: 687b ldr r3, [r7, #4]
800c492: f107 0217 add.w r2, r7, #23
800c496: cb03 ldmia r3!, {r0, r1}
800c498: 6010 str r0, [r2, #0]
800c49a: 6051 str r1, [r2, #4]
I am using the GNU Arm Embedded Toolchain 5.4.1 20160919.
Here is a minimal code example which (hopefully) shows the the problem. The data structure msg_t
must use the packed
attribute to match some hardware registers. On the micro-controller this codes ends in a Hard Fault at the line with msg.data = *data;
#include <stdint.h>
#include <string.h>
#include <stdio.h>
typedef struct canData_s {
uint8_t d1;
uint8_t d2;
uint8_t d3;
uint8_t d4;
uint8_t d5;
uint8_t d6;
uint8_t d7;
uint8_t d8;
} canData_t;
#pragma pack(push, 1)
typedef struct msg_s {
uint32_t stdId;
uint32_t extId;
uint8_t ide;
uint8_t rtr;
uint8_t dlc;
canData_t data; // 8 Bytes
uint8_t navail; // not available
uint32_t timestamp;
} msg_t;
#pragma pack(pop)
void setData(canData_t *data) {
msg_t msg;
msg.data = *data;
// Do something more ...
printf("D1:%d", msg.data.d1);
// ...
}
int main() {
canData_t data;
memset(&data, 0, 8);
setData(&data);
}
Why does copying the structure by a direct assignment fail?