Big Endian or Little Endian

Go To Last Post
21 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I want to ask that Atmega32 is Big Endian or Little Endian?

How we came to know that by using code?

Thanks.

harman

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is little endian. One way to find out is:

uint16_t n = 0x1234;
uint8_t * p = (uint8_t *)&n;

int main(void) {
    PORTB = p[0];
    PORTB = p[1];
}

Run that and you will see 0x34 written first and then 0x12 afterwards. If it had been big endian it would be 0x12 then 0x34.

 

Of course this is just avr-gcc and it chooses to store uint16_t in low byte, high byte order. I guess another C compiler for AVR might choose to use big endian (except that none do).

 

EDIT: Forgot to say that I suppose the true test is to compile an opcode like:
 

 rjmp here
here:

The opcode for that is 0xC000. If you look at that stored in code flash it will be 0x00 and the 0xC0, not the other way around.

Last Edited: Thu. Nov 3, 2016 - 12:47 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I am not getting that last statements about opcode.

harman

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The AVR is a microcontroller. At the end of the day it just executes opcodes that your program into it. Atmel tell you there are about 130+ powerful instructions but in reality a lot are duplicates so there's about 75 distinct opcodes. They are all documented (including the duplicates) in this manual:

 

http://www.atmel.com/Images/Atme...

 

If you look through the alphabetic list there you will come across (for example) RJMP = Relative Jump:

 

 

As you can see from the description of the opcode there it will be 0xC??? where ??? represents some relative offset to jump. As I say, if you used:

 rjmp here
here:

then the offset part is 000 so the complete opcode is 0xC000. It is stored into the flash of the AVR. The CPU sequentially fetches such 16 bit words and executes them. But if you read the flash byte by byte you will find that the order of the bytes in this case is 0x00 then 0xC0 (that is low byte then high byte) rather then 0xC0 then 0x00 (high byte then low byte) so this make it "little endian".

 

I seem to remember (though I'd have to run some code to verify) but the ONE place the AVR does not operate in a little endian way is when it pushes a function return address onto the stack. It's true that the PUSHs themselves are low byte then high byte but the way a stack works "backwards" means that if you examine the two (or three) return address bytes in RAM you will find high to low. So if the opcode:

 rcall foo
here:

where used, where "here" is location 0x1234. Then the CPU would PUSH 0x34 then 0x12 so in memory you would find 0x12 then 0x34 in big endian order. But this is simply because of the backward nature of stacks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Little Endian means the higher order bytes of multibyte values are stored in the higher addresses. You can see in various aspects of the design that AVR is little endian. The opcodes were already mentioned, but also:

 

Instructions that use register pairs use little endian convention, for example the result of MUL goes to r0 (low byte) and r1 (high byte).

Peripheral registers that are 16 bit also have addresses according to the little endian convention (high byte is in the high address).

The stack pointer is also organized this way.

 

But there is one exception: return addresses of subroutines are pushed in the stack in such way that they end up in big endian format.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How  I am going to see output means result of program on Atmel studio 7 for endianness.We can see result in C on output screen,so how it can be seen on Atmel Studio?

harman

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Run the simulator.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I got the concept of little endian and big endian.Only stuck in  program .and output.

harman

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As I am new on Atmel Studio I dont know how to see output like in C.

harman

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

#include <avr/io.h>
uint16_t n = 0x3;
uint8_t * p = (uint8_t *)&n;

int main(void)
{
 
        PORTB = p[0];
        PORTB = p[1];
    }

 

 

How I am going to check result for this code?? for endianness

harman

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just tell me how to check output??

harman

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

sp_usa1 wrote:
As I am new on Atmel Studio I dont know how to see output like in C.
You can't - it's a microcontroller. If you want to write programs like:

$ cat test10.c
#include <stdio.h>

int main(void) {
    int i;
    for (i = 0; i < 10; i++) {
        printf("i = %d\n", i);
    }
    return 0;
}

$ gcc test10.c -o test10
$ ./test10
i = 0
i = 1
i = 2
i = 3
i = 4
i = 5
i = 6
i = 7
i = 8
i = 9
$

then as you can see here, it's best done on a PC - you get to see an instant result.

 

To achieve the same on a micro like an AVR you first have to think of some kind of output device you want to connect. Popular choices are things like an LCD display or a UART link to a PC (usually over USB). In the latter case you then do something like:

$ cat avr.c
#include <stdio.h>
#include <avr/io.h>

void uart_init(void) {
    UBRRL = 51; // 9600 baud on 8MHz
    UCSRB = (1 << TXEN) | (1 << RXEN); // UART on
}

int uart_putchar(char c, FILE *stream) {
    // wait until clear to send
    while (!(UCSRA & (1 << UDRE)));
    UDR = c;

    return 0;
}

int uart_getchar(FILE *stream) {
    // wait for character to arrive
    while (!(UCSRA & (1 << RXC)));

    return UDR;
}

FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);

int main(void) {
    int i;
    uart_init();
    stdout = stdin = &uart_str;

    for (i = 0; i < 10; i++) {
        printf("i = %d\n", i);
    }
    return 0;
}

I haven't tested that (or even tried to compile it) but that is about the minimum of what you need in a micro to make the UART work. As I wrote it, it relies on the micro running at 8MHz. If it isn't it won't work. I also have issues about how to get the TXD/RXD signals to the PC and display them there.

 

When I wrote the above:

uint16_t n = 0x1234;
uint8_t * p = (uint8_t *)&n;

int main(void) {
    PORTB = p[0];
    PORTB = p[1];
}

I rather assumed one would build that, program it in to an AVR, connect to the AVR with an ICE debugger and then single-step the code to see what actually goes to "PORTB" for the two writes.

 

If you don't have an ICE (or a micro that can use one) then I guess the alternative is to head off down the UART or LCD route.

 

But why, we've told you it is little endian - don't you believe us? ;-)

Last Edited: Thu. Nov 3, 2016 - 04:28 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Clawson said: "But why, we've told you it is little endian - don't you believe us? ;-)"  I would add, why does it matter? 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
stack gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I rather imagine the course tutor has posed the question "is AVR little/big endian and how do you prove it?" ;-)

 

I still think this proves it:

$ cat endian.S
    rjmp here
here:

$ avr-gcc -mmcu=avr1 -nostartfiles endian.S -o endian.elf
$ avr-objcopy -O binary endian.elf endian.bin
$ hexdump -C endian.bin 
00000000  00 c0                                             |..|
00000002

 

Last Edited: Thu. Nov 3, 2016 - 05:11 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just create an assembly project in Atmel Studio, then paste this code:

 

call	far_label

.org	0x1234
far_label:
ret

Then build it an run the debugger. See how the address 0x1234 is represented in the program flash memory as part of the call instruction encoding.

 

Now, be honest with us: you're the "flash 3 LEDs" guy, right? angry

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

#Clawson Your explanation is inef for understanding.Thanks.

harman

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Flash 3 Leds? I am asking about endianess concept.

harman

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks Clawson.

harman

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes Ofcourse .only I just want to check my logic regarding endianess.Btw Thanks for explaning.

harman

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#include <avr/io.h>
uint16_t n = 0x3;
uint8_t * p = (uint8_t *)&n;
int main(void)
{
 
        PORTB = p[0];
        PORTB = p[1];
    }

This one is easy. Step through it with the simulator. First, it will set PORTB to either 3, or 0. If it's 3, then AVR is little endian. If it's 0, then AVR is big endian.

 

Why does it matter? It matters in communication with some outside system. If you're outputting a binary representation of 5280, and your AVR sends A0, 14 as a little endian machine, but the outside system is big endian and expects 14, A0; your probe will crash into Neptune instead of...

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks

harman