Where is the bootloader?

Hi all,

I wrote a little sketch to examine the flash memory in an Uno R3 board:

#include <avr/pgmspace.h>

void setup()
{
	Serial.begin(115200);

	uint32_t address;

	for (address = 0x7E00; address < 0x8000; address += 256) {
		hexdump(address, 256);
		Serial.print("\r\n");
	}

}


void hexdump(uint32_t address, uint32_t bytes)
{
	#define bufsiz 32
	char *hexbuf = 0;
	char *ascbuf = 0;
	const char *datamask = "%02X ";
	const char *addrmask = "\r\n%04X: ";

	uint8_t data;
	uint16_t ptr;

	uint32_t x;

	hexbuf = (char *) malloc((bufsiz) * sizeof(char));
	ascbuf = (char *) malloc((bufsiz) * sizeof(char));

	if(!(hexbuf && ascbuf)) {
		Serial.print("Buffer malloc failed\n");
		return;
	}

	for (ptr = 0; ptr < bufsiz; ptr++) {
		hexbuf[ptr] = 0;
		ascbuf[ptr] = 0;
	}

	Serial.print("      +0 +1 +2 +3 +4 +5 +6 +7   +8 +9 +A +B +C +D +E +F");

	for(x = address; x < address + bytes; x++) {

		if ((x & 0x0f) == 0) {
			sprintf(hexbuf, addrmask, x);
			Serial.print(hexbuf);
			ptr = 0;
		}

		data = pgm_read_byte(x);

		ascbuf[ptr++] = ((data > 31) && (data < 128)) ? data : '.';

		sprintf(hexbuf, datamask, data);
		Serial.print(hexbuf);

		if ((((x + 1) & 0x07) == 0) && ((x & 0x0f) != 0x0f)) {
			Serial.print("- ");
		}

		if (ptr == 16) {
			Serial.print("  ");
			Serial.print(ascbuf);
		}
	}

	Serial.print("\r\n");

	free(hexbuf);
	free(ascbuf);
}

void loop()
{
}

…and running it produces this output:

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
7E00: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7E10: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7E20: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7E30: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7E40: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7E50: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7E60: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7E70: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7E80: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7E90: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7EA0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7EB0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7EC0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7ED0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7EE0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7EF0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …

+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F
7F00: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7F10: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7F20: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7F30: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7F40: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7F50: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7F60: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7F70: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7F80: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7F90: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7FA0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7FB0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7FC0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7FD0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7FE0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …
7FF0: 00 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 …

Why don’t I see the bootloader code?

When I dump the beginning of (flash) memory, I see the dump program itself. Is the boot area protected somehow?

Thanks…

– Roger

Running your code without modifications:

      +0 +1 +2 +3 +4 +5 +6 +7   +8 +9 +A +B +C +D +E +F
7E00: 11 24 85 E0 80 93 81 00 - 82 E0 80 93 C0 00 88 E1   .$..............
7E10: 80 93 C1 00 86 E0 80 93 - C2 00 80 E1 80 93 C4 00   ................
7E20: 84 B7 14 BE 81 FF D0 D0 - 8D E0 C8 D0 25 9A 86 E0   ............%...
7E30: 20 E3 3C EF 91 E0 30 93 - 85 00 20 93 84 00 96 BB    .<...0... .....
7E40: B0 9B FE CF 1D 9A A8 95 - 81 50 A9 F7 DD 24 D3 94   .........P...$..
7E50: A5 E0 EA 2E F1 E1 FF 2E - A4 D0 81 34 21 F4 81 E0   ...........4!...
7E60: BE D0 83 E0 24 C0 82 34 - 11 F4 84 E1 03 C0 85 34   ....$..4.......4
7E70: 19 F4 85 E0 B4 D0 8A C0 - 85 35 A1 F4 92 D0 08 2F   .........5...../
7E80: 10 E0 10 93 01 02 00 93 - 00 02 8B D0 90 E0 98 2F   .............../
7E90: 88 27 80 2B 91 2B 88 0F - 99 1F 90 93 01 02 80 93   .'.+.+..........
7EA0: 00 02 73 C0 86 35 29 F4 - 84 E0 99 D0 80 E0 71 D0   ..s..5).......q.
7EB0: 6D C0 84 36 09 F0 43 C0 - 7C D0 E0 91 00 02 F0 91   m..6..C.|.......
7EC0: 01 02 83 E0 80 93 57 00 - E8 95 C0 E0 D1 E0 69 D0   ......W.......i.
7ED0: 89 93 80 91 02 02 81 50 - 80 93 02 02 88 23 B9 F7   .......P.....#..
7EE0: 78 D0 07 B6 00 FC FD CF - 40 91 00 02 50 91 01 02   x.......@...P...
7EF0: A0 E0 B1 E0 2C 91 30 E0 - 11 96 8C 91 11 97 90 E0   ....,.0.........

      +0 +1 +2 +3 +4 +5 +6 +7   +8 +9 +A +B +C +D +E +F
7F00: 98 2F 88 27 82 2B 93 2B - 12 96 FA 01 0C 01 D0 92   ./.'.+.+........
7F10: 57 00 E8 95 11 24 4E 5F - 5F 4F F1 E0 A0 38 BF 07   W....$N__O...8..
7F20: 49 F7 E0 91 00 02 F0 91 - 01 02 E0 92 57 00 E8 95   I...........W...
7F30: 07 B6 00 FC FD CF F0 92 - 57 00 E8 95 27 C0 84 37   ........W...'..7
7F40: B9 F4 37 D0 46 D0 E0 91 - 00 02 F0 91 01 02 31 96   ..7.F.........1.
7F50: F0 93 01 02 E0 93 00 02 - 31 97 E4 91 8E 2F 19 D0   ........1..../..
7F60: 80 91 02 02 81 50 80 93 - 02 02 88 23 61 F7 0E C0   .....P.....#a...
7F70: 85 37 39 F4 2E D0 8E E1 - 0C D0 85 E9 0A D0 8F E0   .79.............
7F80: 96 CF 81 35 11 F4 88 E0 - 19 D0 23 D0 80 E1 01 D0   ...5......#.....
7F90: 63 CF 98 2F 80 91 C0 00 - 85 FF FC CF 90 93 C6 00   c../............
7FA0: 08 95 A8 95 80 91 C0 00 - 87 FF FC CF 80 91 C6 00   ................
7FB0: 08 95 F7 DF F6 DF 80 93 - 02 02 F3 CF E0 E6 F0 E0   ................
7FC0: 98 E1 90 83 80 83 08 95 - 80 E0 F8 DF EE 27 FF 27   .............'.'
7FD0: 09 94 E7 DF 80 32 09 F0 - F7 DF 84 E1 DA CF 1F 93   .....2..........
7FE0: 18 2F DF DF 11 50 E9 F7 - F4 DF 1F 91 08 95 FF FF   ./...P..........
7FF0: FF FF FF FF FF FF FF FF - FF FF FF FF FF FF FF FF   ................

You may have a lock bit set. One of them disables the program from reading the bootloader (page 295):

SPM is not allowed to write to the Boot Loader section, and LPM executing from the Application section is not allowed to read from the Boot Loader section. If Interrupt Vectors are placed in the Application section, interrupts are disabled while executing from the Boot Loader section.

On the 328/328P the bootloader ends at 0x3FFF.

On the 168A/168PA it ends at 0x1FFF.

The information is in the datasheet.

Try running this sketch to establish what your lock byte is, and report that here:

http://www.gammon.com.au/forum/?id=11633

johnwasser: On the 328/328P the bootloader ends at 0x3FFF.

That's words, John. On a 32 Kb processor the bootloader would have to end at 0x7FFF bytes.

[quote author=Nick Gammon link=topic=126955.msg954673#msg954673 date=1350093386] Try running this sketch to establish what your lock byte is, and report that here:

http://www.gammon.com.au/forum/?id=11633 [/quote]

OK, I had to do it in a round-about way. I took the 328P out of the UNO I was using and put it into an ArduinoISP board in order to read it via the ISP as your program does.

Here's the result:

Atmega chip detector. Entered programming mode OK. Signature = 1E 95 0F Processor = ATmega328P Flash memory size = 32768 LFuse = FF HFuse = DE EFuse = FD Lock byte = CF Clock calibration = A2 Bootloader in use: Yes EEPROM preserved through erase: No Watchdog timer always on: No Bootloader is 512 bytes starting at 7E00

Bootloader:

7E00: 11 24 84 B7 14 BE 81 FF F0 D0 85 E0 80 93 81 00 7E10: 82 E0 80 93 C0 00 88 E1 80 93 C1 00 86 E0 80 93 7E20: C2 00 80 E1 80 93 C4 00 8E E0 C9 D0 25 9A 86 E0 7E30: 20 E3 3C EF 91 E0 30 93 85 00 20 93 84 00 96 BB 7E40: B0 9B FE CF 1D 9A A8 95 81 50 A9 F7 CC 24 DD 24 7E50: 88 24 83 94 B5 E0 AB 2E A1 E1 9A 2E F3 E0 BF 2E 7E60: A2 D0 81 34 61 F4 9F D0 08 2F AF D0 02 38 11 F0 7E70: 01 38 11 F4 84 E0 01 C0 83 E0 8D D0 89 C0 82 34 7E80: 11 F4 84 E1 03 C0 85 34 19 F4 85 E0 A6 D0 80 C0 7E90: 85 35 79 F4 88 D0 E8 2E FF 24 85 D0 08 2F 10 E0 7EA0: 10 2F 00 27 0E 29 1F 29 00 0F 11 1F 8E D0 68 01 7EB0: 6F C0 86 35 21 F4 84 E0 90 D0 80 E0 DE CF 84 36 7EC0: 09 F0 40 C0 70 D0 6F D0 08 2F 6D D0 80 E0 C8 16 7ED0: 80 E7 D8 06 18 F4 F6 01 B7 BE E8 95 C0 E0 D1 E0 7EE0: 62 D0 89 93 0C 17 E1 F7 F0 E0 CF 16 F0 E7 DF 06 7EF0: 18 F0 F6 01 B7 BE E8 95 68 D0 07 B6 00 FC FD CF 7F00: A6 01 A0 E0 B1 E0 2C 91 30 E0 11 96 8C 91 11 97 7F10: 90 E0 98 2F 88 27 82 2B 93 2B 12 96 FA 01 0C 01 7F20: 87 BE E8 95 11 24 4E 5F 5F 4F F1 E0 A0 38 BF 07 7F30: 51 F7 F6 01 A7 BE E8 95 07 B6 00 FC FD CF 97 BE 7F40: E8 95 26 C0 84 37 B1 F4 2E D0 2D D0 F8 2E 2B D0 7F50: 3C D0 F6 01 EF 2C 8F 01 0F 5F 1F 4F 84 91 1B D0 7F60: EA 94 F8 01 C1 F7 08 94 C1 1C D1 1C FA 94 CF 0C 7F70: D1 1C 0E C0 85 37 39 F4 28 D0 8E E1 0C D0 85 E9 7F80: 0A D0 8F E0 7A CF 81 35 11 F4 88 E0 18 D0 1D D0 7F90: 80 E1 01 D0 65 CF 98 2F 80 91 C0 00 85 FF FC CF 7FA0: 90 93 C6 00 08 95 80 91 C0 00 87 FF FC CF 80 91 7FB0: C0 00 84 FD 01 C0 A8 95 80 91 C6 00 08 95 E0 E6 7FC0: F0 E0 98 E1 90 83 80 83 08 95 ED DF 80 32 19 F0 7FD0: 88 E0 F5 DF FF CF 84 E1 DE CF 1F 93 18 2F E3 DF 7FE0: 11 50 E9 F7 F2 DF 1F 91 08 95 80 E0 E8 DF EE 27 7FF0: FF 27 09 94 FF FF FF FF FF FF FF FF FF FF 04 04

MD5 sum of bootloader = FB F4 9B 7B 59 73 7F 65 E8 D0 F8 A5 08 12 E7 9F

First 256 bytes of program memory:

0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 10: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 20: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 30: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 40: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 50: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 60: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 70: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 80: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 90: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF A0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF B0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF C0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF D0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF E0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF F0: FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF

how does it look? The bootloader dump looks like it matches the .hex file:

:107E0000112484B714BE81FFF0D085E080938100F7 :107E100082E08093C00088E18093C10086E0809377 :107E2000C20080E18093C4008EE0C9D0259A86E02C :107E300020E33CEF91E0309385002093840096BBD3 :107E4000B09BFECF1D9AA8958150A9F7CC24DD24C4 :107E500088248394B5E0AB2EA1E19A2EF3E0BF2EE7 :107E6000A2D0813461F49FD0082FAFD0023811F036 :107E7000013811F484E001C083E08DD089C08234E0 :107E800011F484E103C0853419F485E0A6D080C0E4 :107E9000853579F488D0E82EFF2485D0082F10E0AE :107EA000102F00270E291F29000F111F8ED06801E7 :107EB0006FC0863521F484E090D080E0DECF843638 :107EC00009F040C070D06FD0082F6DD080E0C81688 :107ED00080E7D80618F4F601B7BEE895C0E0D1E017 :107EE00062D089930C17E1F7F0E0CF16F0E7DF06D8 :107EF00018F0F601B7BEE89568D007B600FCFDCFD4 :107F0000A601A0E0B1E02C9130E011968C91119780 :107F100090E0982F8827822B932B1296FA010C0160 :107F200087BEE89511244E5F5F4FF1E0A038BF0790 :107F300051F7F601A7BEE89507B600FCFDCF97BE46 :107F4000E89526C08437B1F42ED02DD0F82E2BD052 :107F50003CD0F601EF2C8F010F5F1F4F84911BD097 :107F6000EA94F801C1F70894C11CD11CFA94CF0C13 :107F7000D11C0EC0853739F428D08EE10CD085E9AC :107F80000AD08FE07ACF813511F488E018D01DD067 :107F900080E101D065CF982F8091C00085FFFCCF94 :107FA0009093C60008958091C00087FFFCCF809118 :107FB000C00084FD01C0A8958091C6000895E0E648 :107FC000F0E098E1908380830895EDDF803219F02E :107FD00088E0F5DFFFCF84E1DECF1F93182FE3DFCA :107FE0001150E9F7F2DF1F91089580E0E8DFEE27F6 :047FF000FF270994CA :027FFE00040479

(edit to add): The 328P dumped above was programmed with the stock Optiboot code that comes with the Arduino 1.0.1 package using an Atmel AVRISP MKII programmer connected to the UNO board, then clicking "Tools / Burn Bootloader" from the IDE.

This is the configuration (from "boards.txt") that the IDE is using to burn the device:

uno.name=Arduino Uno uno.upload.protocol=arduino uno.upload.maximum_size=32256 uno.upload.speed=115200 uno.bootloader.low_fuses=0xff uno.bootloader.high_fuses=0xde uno.bootloader.extended_fuses=0x05 uno.bootloader.path=optiboot uno.bootloader.file=optiboot_atmega328.hex uno.bootloader.unlock_bits=0x3F uno.bootloader.lock_bits=0x0F uno.build.mcu=atmega328p uno.build.f_cpu=16000000L uno.build.core=arduino uno.build.variant=standard

johnwasser: On the 328/328P the bootloader ends at 0x3FFF.

On the 168A/168PA it ends at 0x1FFF.

The information is in the datasheet.

Don't you mean 0x7FFF?

Lock byte = CF

As expected, that programs BLB1 mode 3.

SPM is not allowed to write to the Boot Loader section, and LPM executing from the Application section is not allowed to read from the Boot Loader section. If Interrupt Vectors are placed in the Application section, interrupts are disabled while executing from the Boot Loader section.

Those you cannot read the bootloader.

You would need to make it FF to be able to read the bootloader programmatically.


MD5 sum of bootloader = FB F4 9B 7B 59 73 7F 65 E8 D0 F8 A5 08 12 E7 9F

Based on my data on this page:

http://www.gammon.com.au/forum/?id=11633

... you have this bootloader installed:

optiboot_atmega328.hex
19b917aeec553ea1e47333cd9b1bbc5a *optiboot_atmega328.hex
Loader start: 7E00, length: 512
MD5 sum = FB F4 9B 7B 59 73 7F 65 E8 D0 F8 A5 08 12 E7 9F
Board name in IDE: Arduino Uno

[quote author=Nick Gammon link=topic=126955.msg954717#msg954717 date=1350098558]

Lock byte = CF

As expected, that programs BLB1 mode 3.

[/quote]

Yup! Just figured that out here. In my "boards.txt" file, the uno.bootloader.lock_bits parameter is set to "0x0F" which clears BLB11 and BLB12.

According to the datasheet, those bits cleared results in:

SPM is not allowed to write to the Boot Loader section, and LPM executing from the Application section is not allowed to read from the Boot Loader section. If Interrupt Vectors are placed in the Application section, interrupts are disabled while executing from the Boot Loader section.

And then setting BLB12 high (i.e. changing the lock bit pattern from 0x0F to 0x2F) made the bootloader visible.

So, the Arduino IDE is clearing that bit when a "Burn Bootloader" is done (no doubt to protect that area from being overwritten and scaring the pants off a noob).

Thanks for the help and ideas... the mention of the lock bits is what helped me figure it out.

Thanks again!

-- Roger