Big Endian for i.MX27: found the problem

Found the big endian problem: it looks like the memory controller bug.

with the following GCC 4.2.4 arguments (optimization switched off):

/home/armadeus-be/buildroot/build_armv5te/staging_dir/usr/bin/armeb-linux-uclibc
-gcc -g  -O0  -fno-strict-aliasing  -fno-common -ffixed-r8 -msoft-float  -mbig-e
ndian -D__KERNEL__ -DTEXT_BASE=0xAFF00000 -I/home/armadeus-be/buildroot/project_
build_armv5te/apf27/u-boot-1.3.4/include -fno-builtin -ffreestanding -nostdinc -
isystem /home/armadeus-be/buildroot/build_armv5te/staging_dir/usr/bin-ccache/../
lib/gcc/armeb-linux-uclibc/4.2.4/include -pipe  -DCONFIG_ARM -D__ARM__ -march=ar
mv5te -mabi=apcs-gnu -Wall -Wstrict-prototypes -fno-stack-protector -c -o env_co
mmon.o env_common.c

the generated code writes a byte  to some  memory access ([fp, #-13]), and then reads from the same address:

uchar env_get_char (int index)
{
 108:   e1a0c00d        mov     ip, sp
 10c:   e92dd800        push    {fp, ip, lr, pc}
 110:   e24cb004        sub     fp, ip, #4      ; 0x4
 114:   e24dd008        sub     sp, sp, #8      ; 0x8
 118:   e50b0014        str     r0, [fp, #-20]
        uchar c;

        /* if relocated to RAM */
        if (gd->flags & GD_FLG_RELOC)
 11c:   e1a03008        mov     r3, r8
 120:   e5933004        ldr     r3, [r3, #4]
 124:   e2033001        and     r3, r3, #1      ; 0x1
 128:   e20330ff        and     r3, r3, #255    ; 0xff
 12c:   e3530000        cmp     r3, #0  ; 0x0
 130:   0a000004        beq     148 <env_get_char+0x40>
                c = env_get_char_memory(index);
 134:   e51b0014        ldr     r0, [fp, #-20]
 138:   ebfffffe        bl      a0 <env_get_char_memory>
 13c:   e1a03000        mov     r3, r0
 140:   e54b300d        strb    r3, [fp, #-13]
 144:   ea000003        b       158 <env_get_char+0x50>
        else
                c = env_get_char_init(index);
 148:   e51b0014        ldr     r0, [fp, #-20]
 14c:   ebffffbc        bl      44 <env_get_char_init>
 150:   e1a03000        mov     r3, r0
 154:   e54b300d        strb    r3, [fp, #-13]

        return (c);
 158:   e55b300d        ldrb    r3, [fp, #-13]
}
 15c:   e1a00003        mov     r0, r3
 160:   e24bd00c        sub     sp, fp, #12     ; 0xc
 164:   e89da800        ldm     sp, {fp, sp, pc}

here’s the GDB session output. A value of  0x62 was stored by strb command, and a completely different value was returned by ldrb:

(gdb) add-symbol-file u-boot 0xaff00000
add symbol table from file "u-boot" at
	.text_addr = 0xaff00000
(gdb) target remote localhost:3333
start_armboot () at board.c:304
/home/armadeus-be/buildroot/project_build_armv5te/apf27/u-boot-1.3.4/lib_arm/board.c:304:8383:beg:0xaff01630
(gdb) b env_get_char
Breakpoint 1 at 0xaff2b8c8: file env_common.c, line 191.
(gdb) c

Breakpoint 1, env_get_char (index=0) at env_common.c:191
(gdb) del
(gdb) display/i $pc
(gdb) display/x $r3
(gdb) x/w $r11
0xafe9fddc:	0xaff2b8c4
(gdb) x/w 0xafe9fdcc
0xafe9fdcc:	0xaff41404
(gdb) display/w 0xafe9fdcc
(gdb) ni
3: x/xw 2951347660  0xafe9fdcc:	0xaff41404
2: /x $r3 = 0xafe9ffdc
1: x/i $pc  0xaff2b8cc <env_get_char+24>:	ldr	r3, [r3, #4]
(gdb)
3: x/xw 2951347660  0xafe9fdcc:	0xaff41404
2: /x $r3 = 0x1
1: x/i $pc  0xaff2b8d0 <env_get_char+28>:	and	r3, r3, #1	; 0x1
(gdb)
3: x/xw 2951347660  0xafe9fdcc:	0xaff41404
2: /x $r3 = 0x1
1: x/i $pc  0xaff2b8d4 <env_get_char+32>:	and	r3, r3, #255	; 0xff
(gdb)
3: x/xw 2951347660  0xafe9fdcc:	0xaff41404
2: /x $r3 = 0x1
1: x/i $pc  0xaff2b8d8 <env_get_char+36>:	cmp	r3, #0	; 0x0
(gdb)
3: x/xw 2951347660  0xafe9fdcc:	0xaff41404
2: /x $r3 = 0x1
1: x/i $pc  0xaff2b8dc <env_get_char+40>:	beq	0xaff2b8f4 <env_get_char+64>
(gdb)
3: x/xw 2951347660  0xafe9fdcc:	0xaff41404
2: /x $r3 = 0x1
1: x/i $pc  0xaff2b8e0 <env_get_char+44>:	ldr	r0, [r11, #-20]
(gdb)
3: x/xw 2951347660  0xafe9fdcc:	0xaff41404
2: /x $r3 = 0x1
1: x/i $pc  0xaff2b8e4 <env_get_char+48>:	bl	0xaff2b84c <env_get_char_memory>
(gdb)
3: x/xw 2951347660  0xafe9fdcc:	0xaff41404
2: /x $r3 = 0x62
1: x/i $pc  0xaff2b8e8 <env_get_char+52>:	mov	r3, r0
(gdb)
3: x/xw 2951347660  0xafe9fdcc:	0xaff41404
2: /x $r3 = 0x62
1: x/i $pc  0xaff2b8ec <env_get_char+56>:	strb	r3, [r11, #-13]
(gdb)
3: x/xw 2951347660  0xafe9fdcc:	0x62f41404
2: /x $r3 = 0x62
1: x/i $pc  0xaff2b8f0 <env_get_char+60>:	b	0xaff2b904 <env_get_char+80>
(gdb)
3: x/xw 2951347660  0xafe9fdcc:	0x62f41404
2: /x $r3 = 0x62
1: x/i $pc  0xaff2b904 <env_get_char+80>:	ldrb	r3, [r11, #-13]
(gdb)
3: x/xw 2951347660  0xafe9fdcc:	0x62f41404
2: /x $r3 = 0x4
1: x/i $pc  0xaff2b908 <env_get_char+84>:	mov	r0, r3
(gdb)

So,  the byte write operation happened in little endian, and the byte read was done in big endian mode. Looks like a bug in mx27 chip?

Advertisements

, , ,

  1. #1 by Martin on September 11, 2009 - 2:14 pm

    Hi folks,

    seems that we have here the same problem also with the i.MX25. byte-writes are going to wrong addresses, read is ok.
    00 writes to 03
    01 writes to 02
    02 writes to 01
    03 writes to 00

    • #2 by Yuri on November 6, 2009 - 5:23 pm

      Perhaps to get correct big-/little- endian operations SDRAM byte mask signals DM / DQS should be connected properly, say, for big-endian DM0 should correspond D[31:24], and for little-endian, DM0 should correspond D[7:0].

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: