Endianness of Data...

Forgive me if this is a noob question, but this is my first chip bringup from scratch. I'm trying to bring up an ARM7 (ADuC7021), and am having a problem with the endianness of data, and I'm not sure how to fix it.

My problem is this: if I call an internal function SD_OutputString("Bootloader.."), I get the following output on my serial port: "tooBdaol..re". In other words, it seems to be storing the string in reverse endian format.

The code in question is very simple:

void SD_OutputString(const char *pTxt) { while (*pTxt != 0) { SD_OutputChar(*pTxt); pTxt++; } }

main() { SD_OutputString("Bootloader.."); }

I'm using arm-elf-gcc / arm-elf-ld to compile and link the code. My Makefile has the following lines:

CPPFlags = -Wall -mcpu=arm7tdmi -mbig-endian LDFlags = -T ld_flash.cmd -nostartfiles -mbig-endian

Does anyone know why my data is being stored in reverse order?


Reply to
Loading thread data ...

Interesting ... the code seems to work.

Please compile again with the added switch


to get assembly listings.

It seems that the compiled code accesses the string in word-size pieces instead of byte loads.

The listing will also show if the compiler or assembler mis-switches the string contents when translating.

Tauno Voipio
tauno voipio (at) iki fi
 Click to see the full signature
Reply to
Tauno Voipio

The dissasembly (did an objdump -D) is as follows:

00000000 : 0: 5b504420 blpl 1411088 4: 426f6f74 rsbmi r6, pc, #464 ; "Boot" 8: 6c6f6164 stfvse f6, [pc], #-400 ; "load" c: 65725d0a ldrvsb r5, [r2, #-3338]! ; "er" 10: 00000000 andeq r0, r0, r0

where 426f6f74 ==> "Boot" where 6c6f6164 ==> "load"

etc, so it seems that the data is in fact stored in the correct order.

000100c8 : 100c8: e1a0c00d mov ip, sp 100cc: e92dd800 stmdb sp!, {fp, ip, lr, pc} 100d0: e24cb004 sub fp, ip, #4 ; 0x4 100d4: e24dd004 sub sp, sp, #4 ; 0x4 100d8: e50b0010 str r0, [fp, #-16] 100dc: e51b3010 ldr r3, [fp, #-16] 100e0: e5d33000 ldrb r3, [r3] 100e4: e3530000 cmp r3, #0 ; 0x0 100e8: 0a000007 beq 1010c 100ec: e51b3010 ldr r3, [fp, #-16] 100f0: e5d33000 ldrb r3, [r3] 100f4: e1a00003 mov r0, r3 100f8: ebffffdd bl 10074 100fc: e51b3010 ldr r3, [fp, #-16] 10100: e2833001 add r3, r3, #1 ; 0x1 10104: e50b3010 str r3, [fp, #-16] 10108: eafffff3 b 100dc 1010c: e89da808 ldmia sp, {r3, fp, sp, pc}

I'm not fluent in assembler though, so I'm not sure exactly what it's doing here. The C code is pretty straight forward though -- I'm not sure how it can misinterpret it.


Reply to

I'll comment the code:

The above code creates a stack frame and sets fp to top of it

This stores pTxt from r0 to a local word in stack

This loads the byte *pTxt into r3

This tests the byte for '\0' and jumps to exit if yes

This loads *ptxt again and sets it up as argument to SD_OutputChar

Here we call the output function

Bump pTxt

Loop back to while at 100dc

Tear down the stack frame, return

As far as I see, the code is correct. I'm still suspicious
on the set up of the data section.
 Click to see the full signature
Reply to
Tauno Voipio

Isn't it so much fun to work with Little-Endian processors?!?


"Big-Endian byte order is known as 'normal', 'intuitive', or 'obvious'. Little-Endian is sometimes called 'perverse', 'annoying', 'dysfunctional', or 'stupid'. These designations do not, of course, imply any bias or preference."

Christopher R. Hertel, "Implementing CIFS" 2004

Reply to
Everett M. Greene

I'm loading the data through a JTAG debugger. Currently everything is in RAM. (The goal is to get to a point where I can write the code into flash through the serial port, but I'm not there yet). The code runs, which means that the endianess is correct for the code at least... However, now that you mention it, it may be that the debugger is switching the endian when loading (and that I should be compiling little endian). I'll look into the debugger manual to see if I can find anything.

Thank you very much for your time. I really appreciate it. These things can be very frustrating if you don't know what you're doing.

Reply to

Are you sure it's big endian? The data sheet at

formatting link
says it's little endian.

-- Paul

Reply to
Paul Black

Not so fast. The program is obviously compiled correctly, and you have a pure byte-wise output loop, so here endianness does not matter.

The output you see is typical for data written into memory with the wrong endianness and in four-byte chunks (=using 32bit accesses).

To fix this, when you download your string data with the JTAG debugger, (a) either the debugger must be set to byte-transfer mode, (b) or it must be configured to the correct endianness.

As Paul Black already stated, your processor memory is organized little-endian. If you plan to define String constants or other data in your C program, you must definitely set the correct endianness.

BTW, there is no "right" or "proper" endianness. For the machine and proper function of a program is in the end completely irrelevant -- you just need to make sure your compiler and processor use the same.

Some processors (e.g. see PowerPC, PowerISA 2.05, Book III-S) can even be configured at run-time to access memory big-endian (PPC native mode) or little-endian (e.g. for PCI address space), this is set with a flag in the memory descriptor or the machine state register.

Reply to
Hagen Patzke

byte-wise output loop, so here

The key question is whether the processor used has been configured to be big-endian - I bet it hasn't (assuming the device even allows it - if it doesn't then there is no way you can run big-endian code). ARM7 uses word-invariant endianness, which means that the endian of word accesses is unchanged between little and big-endian. Therefore an ARM program compiled for big-endian will run in little endian as it uses 32-bit instructions, but all 8- and

16-bit accesses will be incorrect, like the OP noticed.


Reply to
Wilco Dijkstra

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.