Big Endian for i.MX27: bug test code

a piece of assembler code which proves the bug in big-endian mode:

/*
 *  IMX27 Big-endian test
 *  File: imx27-betest.S
 *  Stanislav Sinyagin ssinyagin@k-open.com
 */

#ifdef __ARMEB__
#error This file must be compiled in little-endian mode
#endif

         /* Delay a bit */
        .macro DELAY_FOR cycles, reg0
        ldr     \reg0, =\cycles
        subs    \reg0, \reg0, #1
        subne   pc,  pc, #0xc
        .endm
	/* wait for coprocessor write complete */
        .macro CPWAIT reg
        mrc  p15,0,\reg,c2,c0,0
        mov  \reg,\reg
        sub  pc,pc,#4
        .endm

.globl _start
_start:

	/*
	 * set the cpu to SVC32 mode
	 */
	mrs	r0,cpsr
	bic	r0,r0,#0x1f
	orr	r0,r0,#0xd3
	msr	cpsr,r0

	/*
	 * invalidate I/D cache/TLB and drain write buffer
	 */
	mov r0, #0
	mcr p15, 0, r0, c7, c7, 0	/* invalidate I cache and D cache */
	mcr p15, 0, r0, c8, c7, 0	/* invalidate TLBs */
	mcr p15, 0, r0, c7, c10, 4      /* Drain the write buffer */

	/*
	 * disable MMU stuff and caches
	 */
	mrc p15, 0, r0, c1, c0, 0
	bic	r0, r0, #0x00002300	/* clear bits 13, 9:8 (--V- --RS) */
	bic	r0, r0, #0x00000087	/* clear bits 7, 2:0 (B--- -CAM) */
	orr	r0, r0, #0x00000002	/* set bit 2 (A) Align */
	orr	r0, r0, #0x00001000	/* set bit 12 (I) I-Cache */
	mcr p15, 0, r0, c1, c0, 0

	/* initialize the first 64 bytes at 0xA3000000 */
	ldr r0, =0xA3000000
	ldr r1, =16
	ldr r2, =0x11223344
	1:
	str r2, [r0], #4
	subs r1, r1, #1
	bne 1b

	/* Invalidate cache */
tci_loop:
	mrc p15, 0, r15, c7, c14, 3
	bne tci_loop	

	mov r0, #0
	mcr p15, 0, r0, c7, c7, 0	/* invalidate I cache and D cache */
	mcr p15, 0, r0, c8, c7, 0	/* invalidate TLBs */
	mcr p15, 0, r0, c7, c10, 4   /* Drain the write buffer */

	/* set big endian */
	mov r0, #0
	mrc	p15, 0, r0, c1, c0
	orr	r0, r0, #0x80
	mcr	p15, 0, r0, c1, c0
	CPWAIT  r0

	DELAY_FOR 0x4000, r0

	/* We are in big endian mode. */
	ldr r0, =0xA3000000
	mov r2, r0
	mov r1, #0xFF
	strb r1, [r0], #4
	str r1, [r0], #4
	ldrb r1, [r2]
	strb r1, [r0], #4
	str r1, [r0], #4

	/* loop forever */
	1:
	nop
	b 1b

Compiled into a.out:

  arm-linux-as imx27-betest.S

Uploaded into u-boot and executed:

BIOS> setenv ipaddr 192.168.1.5; setenv serverip 192.168.1.40; tftpboot 0xA0000000 a.out; go 0xA0000000
FEC ETHERNET: Link is up - 100/Full
TFTP from server 192.168.1.40; our IP address is 192.168.1.5
Filename 'a.out'.
Load address: 0xa0000000
Loading: #
done
Bytes transferred = 803 (323 hex)
## Starting application at 0xA0000000 ...

Reset the board and examined the memory:

BIOS> md 0xA3000000 20
a3000000: 112233ff 000000ff 11223311 00000011    .3"......3".....
a3000010: 11223344 11223344 11223344 11223344    D3".D3".D3".D3".
a3000020: 11223344 11223344 11223344 11223344    D3".D3".D3".D3".
a3000030: 11223344 11223344 11223344 11223344    D3".D3".D3".D3".
a3000040: 115e2008 121000c0 122008cc 02004084    . ^....... ..@..
a3000050: 11108200 000802c8 20040000 00800088    ........... ....
a3000060: 10101048 0000308c 11c90004 33800088    H....0.........3
a3000070: 12044144 11860108 1100284c 20680588    DA......L(....h
BIOS>

Results:

[0xa3000000]: The byte 0xFF was written into the least significant byte, although, according to big endian mode, it should’ve been written into the most significant byte.

[0xa300000c]: ldrb has read the most significant byte, as it’s supposed to do in big-endian mode.

Advertisements

, ,

  1. Leave a comment

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: