Identifying Mega128 or Mega64 at run time.

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

I need to create some code that will run in either a Mega128 or a Mega64 with bootloader. The bootloaders match the processor but the application needs to be able to jump to the correct bootloader location by determining which processor it is running in. The RAMPZ register is the only control I see that is different between the processors, so I intend to write a value there and see if it can be read back. Does anyone have previous experience trying this method or any other method that can identify the current processor?

Dave Raymond

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

The first time the bootloader executes on the AVR, you could have it write a a unique value to the EEPROM based on if it was the ATmega128 or ATmega64 bootloader running. The application would then read the EEPROM value to determine which AVR it was executing on.

or

You could instead program the proper byte in the EEPROM when programming the FLASH with the bootloader code.

or

The bootloader could write a unique value, indicating ATmega128 or ATmega64 into a periperhal's register (timer, USART, etc.) before starting your application. Your application would always read this register before initializing the periperhal.

The first method has the advantage of not having to remember to program the EEPROM during FLASH programming.

Last Edited: Fri. Jan 13, 2006 - 10:19 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Each device has a device code.

Quote:
For the ATmega64 the signature bytes are:
1. 0x000: 0x1E (indicates manufactured by Atmel)
2. 0x001: 0x96 (indicates 64KB Flash memory)
3. 0x002: 0x02 (indicates ATmega64 device when 0x001 is 0x96)

Quote:
For the ATmega128 the signature bytes are:
1. $000: $1E (indicates manufactured by Atmel)
2. $001: $97 (indicates 128KB Flash memory)
3. $002: $02 (indicates ATmega128 device when $001 is $97)

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

True, but they exist in a seperate address space that I I don't think application code can read.

Quote:
All Atmel microcontrollers have a three-byte signature code which identifies the device.
This code can be read in both serial and parallel mode, also when the device is locked.
The three bytes reside in a separate address space.

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

Quote:
Is it really safe to store a so important information in EEPROM?

Good point. I added another option to my original post.

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

I may be wrong, but I don't see how the bootloader can read the signature bytes.

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

Yahbut, all youse guys--remember that OP asked about checking at run time.

Off the top of my head, how about a small sequence that writes 0x55 or some other pattern of one or more bytes to an area of EEPROM that doen't exist on the Mega64. If you cannot read back what you wrote, then it is a Mega64.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

The more I think about it, the more I like this idea. Of, course, it's my idea...

Quote:
The bootloader could write a unique value, indicating ATmega128 or ATmega64 into a periperhal's register (timer, USART, etc.) before starting your application. Your application would always read this register before initializing the periperhal for itself.

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

If your application is written in assembly, you could then set aside any SRAM address to pass this information to the application. If written in C, you must be careful of the C startup code and how SRAM is initialized before jumping to main(). This is why I suggest using a common (R/W) peripheral register to have the bootloader pass a byte to the application.

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

How do you get to the bootloader?

Quote:
The bootloaders match the processor but the application needs to be able to jump to the correct bootloader location by determining which processor it is running in

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Quote:

Lee, if the compiler allow you to access a non-existent EEPROM location,

We don't need any wimpy compiler. :) If C, set a pointer to whatever address you like. Or mess with EEARx directly. Or do a little ASM fragment.

Quote:

when you try to do it, the EEPROM address counter will rollover and you will finally read an irrelevant location.

Interesting. The behavior would obviously need to be checked. OK, the Mega64 has 2k; the Mega128 4k of EEPROM. So if you write the test pattern at [say] address 3k, where will it show up? If it doesn't read back at 3k, you have a Mega64. If it shows up at 1k, then the address wrapped and you have a Mega64.

Anyway, I thought of a better way that is very non-destructive and doesn't care whether the addresses of EEPROM wrap or not. It assumes that your bootloader (or part of it) is, in fact, >>in<< the bootloader area of flash. So find a convenient routine located in the bootloader area. Load up a void pointer (in C) with the address of the function. Examine the high byte and see where it lives. One can also call a function that looks at the return address on the stack.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Quote:
The bootloaders match the processor

OK so you already know which processor is being used, following on from what Lee is suggesting AND provided you have, say, 2 spare bytes in the bootloader area, you could make the last 2 bytes contain the bootloader version, ie "0064", "0128" or whatever in ASCII. Therefore read 0xfffe,0xffff if it does not contain "0064", then it is not a m64. Do the same at 0x1fffe,0x1ffff etc.

John Samperi

Ampertronics Pty. Ltd.

https://www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

Thanks to all. I like Lee's idea the best and am going to use a variation. If the bootloader exists in the Mega64 boot area, then it is a Mega64. I do not need to see if it has any particular code, just that it is not erased.

Dave Raymond

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

Quote:

Do the same at 0x1fffe,0x1ffff etc.

Not quite as easy is that, is it? Trickier accessing constants in flash above 64kb, right? [Never done it; osmosis only]

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Or just look at word address 0 & 1, and 32768 & 32769 in FLASH, if they are the same then it's a mega64, if not, it's a mega128. The likelihood of a legitimate program generating code/data equivalent to the reset vector is minimal. Add to that the fact that it's the same code running on a 64 as a 128, those words, at 32768 & 32769, should read as 0xFFFF on a mega128, since they will be unused.

Writing code is like having sex.... make one little mistake, and you're supporting it for life.

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

While you cant read the signature bytes, you can read the lock bits and fuses from the application.
Perhaps your fuse settings differ on the 64 and 128, so you can use that to determine the chip type.
Otherwise, load the calibration byte with the chip ID at programming time, then read the OSCCAL register in the application to get it. That's assuming you're not needing it to calibrate the internal oscillator ofcourse.

/Jesper
http://www.yampp.com
The quick black AVR jumped over the lazy PIC.
What boots up, must come down.

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

What about writing a magic signature somewhere at the beginning of the bootloader code.
Your application just have to scan a few bytes at the potential locations to find the magic code.

Werner

... the only thing you cannot unscramble is eggs...

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

You can probe the implementation of the EEADR I/O register:

     ldi r16,0xFF
	  out EEARH,r16
	  in  r16,EEARH

You'll get 0x01=512b on a M16, 0x03=1k on M32, 0x07=2k on M64, 0x0F=4k on CAN128. I just tested. And it's even documented behaviour.

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

Quote:

You'll get 0x01=512b on a M16, 0x03=1k on M32, 0x07=2k on M64, 0x0F=4k on CAN128...

Cool. Same idea as my "writing tag sequence to EEPROM", but obviously less invasive. Real clean for distinguishing between two AVRs that have >256 byte of EEPROM but different sizes.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Or, if M64/M128 behave like M16, and the bootloaders have the same entrypoints (just 64k apart), one can just use a JMP or CALL to the high (128k-n) address.
The M16, at least, ignores the high bits of its instruction counter. as in "Not Implemented"

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

@Giorgos_K:
Silicon.
Your other assumptions are correct.

RAMPZ: I thought of this too, but scrapped the idea: The beauty of EEARH is really that the datasheet explicitly states that the topmost bits will be 0, and so it's a fully documented difference. For RAMPZ it's different: All that is stated in the M64 datasheet is that 'this address should never be read'.

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

KKP's EEARH idea is the best one yet. The problem arose when our vendor accidentally built 1000 units with a Mega128 instead of a Mega64. We create a hex file with bootloader concatenated to simplify the production programming, which until yesterday did not have a working signature check. It does now! The program fits in the Mega64 and our production test procedures do not confirm that the bootloader works so there was no indication that the processor was wrong. After we shipped many units the problem was discovered. Once again software has to fix a hardware problem! The bootloader for a Mega64 will not work in a Mega128 so I have to create two versions, but I do not want to have to create two versions of the application code.
Thanks again to all.

Dave Raymond

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

KKP wrote:
You can probe the implementation of the EEADR I/O register:

     ldi r16,0xFF
	  out EEARH,r16
	  in  r16,EEARH

You'll get 0x01=512b on a M16, 0x03=1k on M32, 0x07=2k on M64, 0x0F=4k on CAN128. I just tested. And it's even documented behaviour.

what of the mega8 which also has 512Bytes of EEPROM? It would return 01 as would the M16?