I used keil mdk v5.1 for arm to develop my project. I encounterd a serious problem about LDRD instruction. Look at c codes below:
#include <stdint.h> char b[2]; char c[4]; char d[2]; typedef struct { uint32_t m_front; /* ¶ÓÍ· */ uint32_t m_rear; /* ¶Óβ */ uint16_t m_maxData; /* ¶ÓÁÐÖÐÔÊÐí´æ´¢µÄÊý¾Ý¸öÊý */ uint8_t (* ReadEmpty)(); /* ¶Á¿Õ´¦Àíº¯Êý */ uint8_t (* WriteFull)(); /* дÂú´¦Àíº¯Êý */ } DataQueue; void SystemInit() { } void main() { DataQueue* p = (DataQueue*)c; char* q = c; char* xx = b; char* yy = d; if (p->m_front == p->m_rear) { int i = 0; } }
disassembly of part of c codes is below
28: if (p->m_front == p->m_rear) 29: { 0x08000194 E9D04500 LDRD r4,r5,[r0,#0] 0x08000198 42AC CMP r4,r5 0x0800019A D101 BNE 0x080001A0 30: int i = 0; 0x0800019C 2400 MOVS r4,#0x00 31: }
I started a debug session. When I stepped over sentance "if (p->m_front == p->m_rear)", I found that program crashed(Hard fault error).
i thought that LDRD need value of r0 to a multiple of 4, but r0 value was 0x20000002 at this time.
so i have to add __align(4) keyword to make sure that address of "c" is multiple of 4 and everything is fine. you can see the codes below
#include <stdint.h> char b[2]; __align(4) char c[4]; char d[2]; typedef struct { uint32_t m_front; /* ¶ÓÍ· */ uint32_t m_rear; /* ¶Óβ */ uint16_t m_maxData; /* ¶ÓÁÐÖÐÔÊÐí´æ´¢µÄÊý¾Ý¸öÊý */ uint8_t (* ReadEmpty)(); /* ¶Á¿Õ´¦Àíº¯Êý */ uint8_t (* WriteFull)(); /* дÂú´¦Àíº¯Êý */ } DataQueue; void SystemInit() { } void main() { DataQueue* p = (DataQueue*)c; char* q = c; char* xx = b; char* yy = d; if (p->m_front == p->m_rear) { int i = 0; } }
i was confused if this was an bug of compiler? Please help me
There were many casting structure(packed or unpacked) such as DataQueue in my project. what should i do to prevent those crashes?
Get rid of all the "packed" attributes. They cause a whole lot of grief (including the unaligned accesses you're so worried about), for hardly any benefit.