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
  • Since you already have a fixed data type for the elements, you could do:

    enum {
        NUM_ENTRIES = 20,
        NUM_OTHER_ENTRIES = 40,
    };
    Queue my_queue;
    QueueEntry my_entries[NUM_ENTRIES];
    
    Queue my_other_queue;
    QueueEntry my_other_entries[NUM_OTHER_ENTRIES];
    
    void init_queue(Queue *q,QueueEntry entries[],unsigned num_entries) {
        QueueEntries *p;
        unsigned i;
    
        memset(q,0,sizeof(*q));
        q->first = NULL;
        q->last = NULL;
        q->num_entries = num_entries;
        // Chain together all entries in a list of unused.
        q->free = p = entries;
        for (i = 1; i < num_entries; i++,p++) {
            p->next = p+1;
        }
        p->next = NULL;
        ...
    }
    
    void main() {
        init_queue(&my_queue,my_entries,NUM_ENTRIES);
        init_queue(&my_other_queue,my_other_entries,NUM_OTHER_ENTRIES);
        ...
    }
    


    Two statically allocated queues of different length but with correct align.

Reply
  • Since you already have a fixed data type for the elements, you could do:

    enum {
        NUM_ENTRIES = 20,
        NUM_OTHER_ENTRIES = 40,
    };
    Queue my_queue;
    QueueEntry my_entries[NUM_ENTRIES];
    
    Queue my_other_queue;
    QueueEntry my_other_entries[NUM_OTHER_ENTRIES];
    
    void init_queue(Queue *q,QueueEntry entries[],unsigned num_entries) {
        QueueEntries *p;
        unsigned i;
    
        memset(q,0,sizeof(*q));
        q->first = NULL;
        q->last = NULL;
        q->num_entries = num_entries;
        // Chain together all entries in a list of unused.
        q->free = p = entries;
        for (i = 1; i < num_entries; i++,p++) {
            p->next = p+1;
        }
        p->next = NULL;
        ...
    }
    
    void main() {
        init_queue(&my_queue,my_entries,NUM_ENTRIES);
        init_queue(&my_other_queue,my_other_entries,NUM_OTHER_ENTRIES);
        ...
    }
    


    Two statically allocated queues of different length but with correct align.

Children