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
"I encounterd a serious problem about LDRD instruction."
Not at all. You encountered a serious problem about your C skills. Why did you even involve any char array for that data queue? And why isn't there any code to initialize that DataQueue, since the default zero-initialization of global variables will not give you any values for m_maxData, ReadEmpty or WriteFull?
A basic assumption when you are encountering serious problems should be that you have done something wrong - not that there are anything wrong with the tools. The C language standard and the compiler manual will contain the "contract" between you and the programming language/compiler. If you go outside of that contract, then you are on your own. Whenever you are about to make a type cast, it's time to really consider what is covered by that contract - it does not allow "any type" to "any type" conversions to be performed and still give a working program. Some situations can be directly caught and forbidden by the compiler, but other type cast situations will instead result in unexpected runtime behavior.