1. This forum section is a read-only archive which contains old newsgroup posts. If you wish to post a query, please do so in one of our main forum sections (here). This way you will get a faster, better response from the members on Motherboard Point.

Endianness of Data...

Discussion in 'Embedded' started by julvr, Nov 11, 2008.

  1. julvr

    julvr Guest

    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?



    John
     
    julvr, Nov 11, 2008
    #1
    1. Advertisements

  2. julvr

    Tauno Voipio Guest

    Interesting ... the code seems to work.

    Please compile again with the added switch

    -Wa,-ahlms=myfile.lst

    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, Nov 11, 2008
    #2
    1. Advertisements

  3. julvr

    julvr Guest

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


    00000000 <.rodata>:
    0: 5b504420 blpl 1411088 <.rodata+0x1411088>
    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 <SD_OutputString>:
    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 <SD_OutputString+0x44>
    100ec: e51b3010 ldr r3, [fp, #-16]
    100f0: e5d33000 ldrb r3, [r3]
    100f4: e1a00003 mov r0, r3
    100f8: ebffffdd bl 10074 <SD_OutputChar>
    100fc: e51b3010 ldr r3, [fp, #-16]
    10100: e2833001 add r3, r3, #1 ; 0x1
    10104: e50b3010 str r3, [fp, #-16]
    10108: eafffff3 b 100dc <SD_OutputString+0x14>
    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.

    John
     
    julvr, Nov 11, 2008
    #3
  4. julvr

    Tauno Voipio Guest

    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.

    Is this a ROM/RAM system where the initialization code sets
    up the .data section in RAM?

    How do you get the code and data to the target system?

    Can it be that you have the endianess crossed? An ARM
    core has an input which tells the endianess of the data bus.
     
    Tauno Voipio, Nov 11, 2008
    #4
  5. julvr

    julvr Guest

    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.
     
    julvr, Nov 11, 2008
    #5
  6. julvr

    Paul Black Guest

    Are you sure it's big endian? The data sheet at
    http://www.analog.com/static/import...9_7020_7021_7022_7024_7025_7026_7027_7028.pdf
    says it's little endian.
     
    Paul Black, Nov 11, 2008
    #6
  7. julvr

    Hagen Patzke Guest

    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.
     
    Hagen Patzke, Nov 11, 2008
    #7
  8. 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.

    Wilco
     
    Wilco Dijkstra, Nov 12, 2008
    #8
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.