cancel
Showing results for 
Search instead for 
Did you mean: 

Pointer to struct inside a union throws hard fault.

PR.19
Associate II

struct {

unsigned char oned;

unsigned char twod;

}test;

hspi2.Instance->DR = *((uint16_t *)&(test.oned));

struct {

unsigned char oned;

unsigned char twod;

}test;

this works fine.

however,

typedef union {

 struct {

  uint8_t idType;

  uint32_t id;

  uint8_t dlc;

  uint8_t data0;

  uint8_t data1;

  uint8_t data2;

  uint8_t data3;

  uint8_t data4;

  uint8_t data5;

  uint8_t data6;

  uint8_t data7;

 } frame;

 uint8_t array[14];

} uCAN_MSG;

uCAN_MSG txMessage;

hspi2.Instance->DR=(*((uint16_t *)&(txMessage.frame.data0)));

throws a hard fault although evaluating the expression in watch windows shows proper value. pl help

3 REPLIES 3

This is on a Cortex-M0 or M0+?

Try

 struct __attribute__((packed)) {

...

}

JW

PR.19
Associate II

This code is from a CAN-SPI library for STM32F3 controller which i'm trying to implement in a Cortex M0.

I added  __attribute__((packed)) to struct and now the issue seems to be resolved.

Danish1
Lead II

You don't say which stm32 processor you're using.

One possibility, particularly if you're using stm32f0 or stm32l0, is that the failure is due to an unaligned access. I think the Cortex M0 cannot do unaligned memory accesses. I think they will lead to a hard fault.

You might wonder why I think accessing data0 will cause an unaligned access failure, where your first test didn't.

Well I think you were just lucky in your first test, and it just so happened that "test" was sufficiently well aligned to allow a 16-bit access on "oned" (but I believe it will fail if you try to access "twod" this way - to say nothing of the undefined result of accessing beyond the end of "test")

As you haven't specified that the struct "frame" is packed, the compiler will automatically align things correctly.

So "frame" will be aligned on a 4-byte boundary (because the largest alignment requirement is for "id").

And "id" will be aligned on a 4-byte boundary. This will place 3 bytes of padding between "idType" and "id"

Consequently dlc is on a 4-byte boundary so data0 ends up on an odd address.

And cortex M0 cannot do a 16-bit access to an odd address.

Hope this helps,

Danish