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
  • If i used IAR compiler to compile this program, it's OK.

    No, it's not OK in any sensible meaning of the word.

    That program, as written, is terminally sick. The fact it doesn't die quite as horribly and immediately if built by a different compiler, or with different flags, doesn't make the program itself any healthier. It just means its manifest illness will express itself in a different way. Or do you really believe getting garbage results instead of an immediate hard fault is in any sense of the word "OK"?

    Every single line of that program which you commented as "It's OK" actually causes undefined behaviour. In case you don't recognize that term: that's the worst kind of error a C program can have while still being compilable at all.

    Your fixation on the instruction being used by the compiler is misleading you. It's not the compiler, nor the compiled code that's the problem here. It's the source code that's grossly incorrect.

Reply
  • If i used IAR compiler to compile this program, it's OK.

    No, it's not OK in any sensible meaning of the word.

    That program, as written, is terminally sick. The fact it doesn't die quite as horribly and immediately if built by a different compiler, or with different flags, doesn't make the program itself any healthier. It just means its manifest illness will express itself in a different way. Or do you really believe getting garbage results instead of an immediate hard fault is in any sense of the word "OK"?

    Every single line of that program which you commented as "It's OK" actually causes undefined behaviour. In case you don't recognize that term: that's the worst kind of error a C program can have while still being compilable at all.

    Your fixation on the instruction being used by the compiler is misleading you. It's not the compiler, nor the compiled code that's the problem here. It's the source code that's grossly incorrect.

Children
No data