How can this possibly work after a reset?

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

I have an ATmega2560 on an Arduino board that I've been playing with. For some reason, avrdude won't tell me how the fuses are set: it says all 24 of them are 0, which doesn't make a lot of sense.

Anyway, the Atmel datasheet says (page 59) that a reset begins execution from the Reset Vector. The exact location of the Reset Vector depends on the fuses, which I can't read, but the default value of BOOTRST is 1, in which case the Reset Vector is zero

So I'm looking at the .hex file that the Arduino IDE created for upload to the board, and it starts out like this (spaces added for clarity):

:10 0000 00 0C9472000C9486000C9486000C948600 6C

If you're not familiar with Intel .hex format, the 32 digits in the middle of the line are 16 bytes of data that are to be written at the address 0000 second from the left.

So it looks like the first instruction is 0C94, which, according to the best of my hand-disassembly capabilities, works out to ADD R9, R4. The next instruction would then be 7200, which is ANDI R0, $20.

That's some really weird vector code--that is, not a vector at all--and it leads me to believe that I have a framing error here, especially since 94 looks like it could be the beginning of a JMP instruction, although if it were, the fourth digit would need to be C or D, not 2.

What's going on here? How does this Reset Vector stuff work with the avrdude upload of the Arduino .hex file?

Thanks,
Dan Wiebe

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

Well, if you can't read fuses, try the signature. If no signature, erase the board, including fuses, and start over.

If that does not work, then check that you have the proper clock and that your programming clock rate is not too high.

Not sure what you mean by "How does this Reset Vector stuff work?". The compiler will put a jump, of some kind, at the reset vector location. The machine starts executing code at the vector address, so the first thing it does is jump to the main().

Be aware, however, that c does a whole bunch of hidden initialization that is executed first. So, the reset vector will really jump to where the initialization starts.

If you want to see how the code works, run the simulator and watch in the disassembled version of the code. That is far better than trying to work out what is buried in an intel hex file. Stuff is not in that file in the order it is executed.

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

Are you using the arduino bootloader as the programmer in the avrdude command? If so, it will not report fuses to avrdude.

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

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

You are most likely reading the high and low bytes wrong. Try 940c instead of 0c94.

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

ka7ehk wrote:
Be aware, however, that c does a whole bunch of hidden initialization that is executed first. So, the reset vector will really jump to where the initialization starts.

Yup, I'm expecting that. I figure I'll write a program for the Arduino, once I figure out what's going on, that will suck out that library code and squirt it over the serial port to the dev host so that I can look at it.

Quote:
If you want to see how the code works, run the simulator and watch in the disassembled version of the code. That is far better than trying to work out what is buried in an intel hex file. Stuff is not in that file in the order it is executed.

Which simulator are you talking about?

My whole project, at the moment, is writing a simulator of my own that offers the sort of functionality that a test-driven developer needs, because the future project I have in mind will require some fairly fiddly software. I looked around at various emulators, but so far everything I've found is aimed at manual debugging, not automated testing. But maybe you've got one that would save me a lot of work.

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

larryvc wrote:
Are you using the arduino bootloader as the programmer in the avrdude command? If so, it will not report fuses to avrdude.

Huh.

No, I'm using stk-sumpin-sumpin-2. (Not on that computer right now.) Not that I really understand what that means, though.

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

Jepael wrote:
You are most likely reading the high and low bytes wrong. Try 940c instead of 0c94.

Omigosh, you gotta be frickin' kidding me. That's perfect. I can't believe I didn't think of that.

Some sobering implications there, though...

Anyway, thanks a lot.

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

Jepael wrote:
You are most likely reading the high and low bytes wrong. Try 940c instead of 0c94.

Okay, so 940C0072 (I assume the last two bytes ought to be reversed if the first two bytes are), given the opcode pattern

1001 010k kkkk 110k
kkkk kkkk kkkk kkkk

specified on page 83 of the instruction-set manual, disassembles to

JMP $72

That's certainly a vector, but a surprisingly short one.

Here's another line from the .hex file (again with illustrative spaces added):

:10 0070 00 0C9486000C9486000C9486000C948600 E8

(Notice the repetition: apparently every interrupt vector points to the same place...and that place is another problem similar to the one I have now.)

So...locations 0072 and 0073 will be set to 0086, if we stick to the 16-bit little-endian rule.

But 0086 is not a legal AVR instruction at all. More likely, it's the address for the jump vector starting above at location 0070.

I have a feeling here that I'm interpreting the addresses incorrectly somehow. Do you know what's going on?

Thanks again,
Dan

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

Quote:
Okay, so 940C0072 (I assume the last two bytes ought to be reversed if the first two bytes are), given the opcode pattern

1001 010k kkkk 110k
kkkk kkkk kkkk kkkk

specified on page 83 of the instruction-set manual, disassembles to

JMP $72

It is right.
0c947200 is a 32-bit instruction "jmp 0x72".
Why do you think you are interpreting the addresses incorrectly ?

Last Edited: Sun. Jun 24, 2012 - 09:04 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was referring to the simulator in AVR Studio 4 or 6.

Jim

 

Until Black Lives Matter, we do not have "All Lives Matter"!

 

 

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

That .hex file was probably generated from an intermediate .elf file which contains all sorts of debugging and section information accessible through the toolchain - avr-size, avr-readelf, avr-objdump. The latter does disassembly:

avr-objdump -S myelf.elf

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

Visovian wrote:
Quote:
Okay, so 940C0072 (I assume the last two bytes ought to be reversed if the first two bytes are), given the opcode pattern

1001 010k kkkk 110k
kkkk kkkk kkkk kkkk

specified on page 83 of the instruction-set manual, disassembles to

JMP $72

It is right.
0c947200 is a 32-bit instruction "jmp 0x72".
Why do you think you are interpreting the addresses incorrectly ?

Because when I manually JMP $72, taking $72 as meaning absolute flash address 0x00000072, I land on an illegal instruction 0086. (And it looks to me like I'm landing misframed in the middle of a jump table, trying to execute one of the jump addresses.) I haven't found yet what the AVR does when it hits an illegal instruction, but my Arduino board handles the .hex file just fine, so I'm thinking I'm understanding something wrong.

Either "0C947200" from the .hex file shouldn't be interpreted as 0x940C0072 in memory, or I'm doing the disassembly wrong somehow, or address 0x72 doesn't really refer to memory location 0x72, is modified by some implicit offset or multiplier I don't know about...something like that, I'm thinking.

Maybe, since each instruction is two or four bytes long, there's an implicit zero bit at the end of every address, so that 0x72 actually refers to byte 0xE4. I'm going to try that and see what happens.

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

The AVR references flash as word addresses. This should complete the picture.

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

Kartman wrote:
The AVR references flash as word addresses. This should complete the picture.

Yah--that's much better. Thanks.

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

Quote:
I figure I'll write a program for the Arduino, once I figure out what's going on, that will suck out that library code and squirt it over the serial port to the dev host so that I can look at it.

Um. There is no library code loaded on an Arduino. There is a bootloader, whose source is available...

The Arduino MEGA2560 happens to have a "monitor" included in the bootloader, as well as bootloading functionality. If you connect to its usb serial port at 115200bps, and type "!!!", you'll get put into a command mode where you can do things like display memory. (type "?" for help.)

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

Get the eval version of codevision, write some simple C, or load one of its example programs,, compile it and look the .lst file - you will see the preamble, the vector table, how it starts etc. it even has some comments in it

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

If you have Arduino I assume there's a copy of avr-objdump buried in there somwhere? If so then observe - using the hex you quoted in the first post with spaces (including the one at the end of the line) removed. I could use an editor and paste the data but "copy con" is the way real programmers create files - you end input with Ctrl-Z:

E:\>copy con some.hex
:100000000C9472000C9486000C9486000C9486006C

^Z
        1 file(s) copied.

E:\>avr-objdump -s -m avr some.hex

some.hex:     file format ihex

Contents of section .sec1:
 0000 0c947200 0c948600 0c948600 0c948600  ..r.............

E:\>avr-objdump -S -j .sec1 -m avr some.hex

some.hex:     file format ihex


Disassembly of section .sec1:

00000000 <.sec1>:
   0:   0c 94 72 00     jmp     0xe4    ;  0xe4
   4:   0c 94 86 00     jmp     0x10c   ;  0x10c
   8:   0c 94 86 00     jmp     0x10c   ;  0x10c
   c:   0c 94 86 00     jmp     0x10c   ;  0x10c

This simply creates a file from the data (you probably already have that!) then gets avr-objdump to disassemble it for you. I can never remember the name of the default section that is assumed (.sec1) so just using -s will reveal that. Then knowing it is .sec1 you can ask for that one in particular (-j .sec1) to be disassembled (-S) and there you go.