This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

LDRD instruction confused me, please help

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

Parents
  • "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.

Reply
  • "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.

Children
No data