See this post first.
The reason my program fails is because interrupts are disable inside the BLS. Running interrupts in the BLS requires a different lock bit setting than the standard arduino. The arduino boot loader doesn’t use any interrupts, so this lock bit setting is ok.
Since interrupts are disabled inside the BLS, when my program calls the LPM instruction, my timer interrupt never fires. Hence the program never returns from the LPM instruction. It probably continues to execute the boot loader code until it crashes, restarts, starts my program, etc., continuing like this in an endless loop.
As a confirmation of the disabled interrupts and to validate my code, I modified the instruction after the LPM in the BLS to a “RET”, then ran my program without using the timer interrupt. I discovered it now works, with and without the lock bits set.
Here is the section of the boot loader code that I modified:
pgm_read_byte: 3de2: 00 23 and r16, r16 3de4: 39 f4 brne SkipRead ;.+14 (0x3df4) 3de6: 94 91 lpm r25, Z+ waituart: //we need to insert this return command here 3de8: 08 95 ret // 3de8: 80 91 c0 00 lds r24, UCSR0A ;0x00C0 3dec: 85 ff sbrs r24, 0b00000101 ;5 3dee: fc cf rjmp waituart ;.-8 (0x3de8)
To accomplish this, I downloaded the entire flash from my arduino (with both my program and a standard boot loader installed). Then I opened the file (Intel Hex format) in a hexeditor program, searched for the LPM instruction, and changed the following four bytes (“9491” to “0895”):
Note, I also needed to change the 2 checksum bytes at the end of the line because avrdude complains when we attempt the upload the modified hex code:
avrdude.exe: input file C:\Users\James\168.hex auto detected as Intel Hex
avrdude.exe: ERROR: checksum mismatch at line 991 of "C:\Users\James\168.hex"
avrdude.exe: checksum=0x99, computed checksum=0x0d
avrdude.exe: write to file 'C:\Users\James\168.hex' failed
Luck for me, avrdude also computes and displays the correct checksum, so this was easy to accomplish.
So the answer to my question is, “Yes, maybe.” An LPM instruction in the BLS can read the BLS, it just can’t do it with the method I attempted.
BTW, I’m a little annoyed with my new ATMEL-ICE (~$40). When using debugWire with an arduino, calls into the BLS are prevented, as ATMEL Studio depicts the BLS as solid “FF FF FF…”. However, when you return from the debug session, the bootloader is still there. Furthermore, it seems to take a magical combination of nearly hidden menu selections to get in and out of debug mode. You end up scaring yourself about once per debug session, thinking you bricked the chip. The combination of ATMEL Studio 6.2, debugWire and arduino is very fragile.