There is some progress, but yep I had to look again and again into AVR assembler RJMP instruction description
http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_RJMP.htm while I had to write small disassembly utility to be able understad this hardcoded RJMP statements in example
picoboot avrdude implementation
avrdude: eneurobootlight: flash address: oryginal appstart: 0xC00E changed appstart: 0xCFEE reset vector: 0xCFDF virtual reset vector addr: 0x1FC0
avrdude: eneurobootlight: paged write: page: 0 address: 0x0000 bytes: 64
avrdude: eneurobootlight: frame bytes: 0xDF 0xCF 0x10 0x00 flash data: 0xCFDF
avrdude: eneurobootlight: frame bytes: 0x00 0x00 0x01 0x01 flash addr: 0x0000
Compiled sample AVR code (classic Hello AVR I'd like to use to test bootloader-diode blinking on PB1 ATTiny85 pin ay 1Hz at 8MHz clock) created code like shown above for first flash page, where at address 0x0000 reset vector was: 0xC00E, which means (thanks to disassemblers and Atmel AVR instruction set documentation linked above):
$ avr-rjmp 0xC00E
AVR assembler RJMP code: 0xC00E rjmp: +0x001E (+28)
So, nothing fancy- so far so good-classic AVR MPU code-oryginal reset verctor jumps somwhere to main program as RJMP instruction is: 0xC00E decoded above.
However, as we can see by analysis of what
picoboot does the trick and change this oryginal restet vector during avrdude programming to point to his own code, but... lets see what we get when we'll try disassemble this
It changes this application reset vector code from oryginal 0xC00E, to...
0xCFDF, which means:
$ avr-rjmp 0xCFDF
AVR assembler RJMP code: 0xCFDF rjmp: -0x0040 (-66)
Yes, jump 66 bytes back, but... we are at first flash program memory adress 0x0000
We know from bootloader complation that bootloader code is placed at adress 0x1FBE
avr-gcc -mmcu=attiny85 -DF_CPU=1000000 -nostdlib -x assembler-with-cpp -c eneurobootlight.S -o eneurobootlight.o
avr-gcc -mmcu=attiny85 -DF_CPU=1000000 -nostdlib -Wl,-section-start=.bootloader=0x1fbe -o eneurobootlight.elf eneurobootlight.o
So, it puzzled me for a few hours
this RJMP -66 means and why someone hardcoded it as 0xCFDF in avrdude interface code?
const uint8_t reset_vec_lo = 0xdf; /* rjmp BootStart */
const uint8_t reset_vec_hi = 0xcf; /* rjmp BootStart */
Hopefully, I realized that, since ATTiny85 has 8KB flash program memory, so it is: 8120 bytes, which in hex is: 0x2000,
so when we apply this strange 0xCFDF (RJMP -66) instruction send by avrdude, which means that from address where it starts we need substract -0x0040 , we get: 0x2000 -0x0040=
0x1FC0 , so very close to place where our bootloader is already programmed in MPU:
0x1FBE .
How close is it?
Two bytes before place where new reset vector RJMP redirects us after succesfull MPU programming:
0x1FC0 = 0x1FBE +2 (rjmp)
So, now this part of bootloader code explains everything: VirtualReset is at adress: 0x1FBE and BootStart: at 0x1FC0, since instruction:
rjmp BlinkLED
is exactly 2 bytes in flash program memory and is replaced by bootloader with uploaded application during avrdude programming
.section .bootloader,"ax",@progbits
VirtualReset:
rjmp BlinkLED ; will be overwritten by programmer
BootStart:
sbis UART_Port-2, UART_Rx ; Rx high = start bootloader
rjmp VirtualReset ; jump to application code
clr FCS
sbi UART_Port-1, UART_Tx ; set Tx pin to output mode
; continuous loop for commands from programmer
; when upload is finished, programmer resets chip & starts app
So, sick-it remainds me LOGO programming on Commodore64 by... writting directly into its RAM assembler code and this is exactly what is done during avrdude flash programming, where modified RJMP instruction is calculated
/* calculate new rjmp for appstart */
vrst_vec_addr = m->size - BOOTLOADER_SIZE;
appstart = 0xc000 |
( (vrst_vec_addr/2) + (appstart & 0x0FFF) );
Unfortunatelly,
0xC000 is hardcoded in this sample
picoboot code, so... it is not clear that it is part of RJMP binary two byte code
Now, it should be easy change bootloader code, since we know howto calculate new bootloader position and.. howto (hard)code this new reset vector code in the case bootloader size will change if we have other requirements too.
BTW: If someone found this information usefull in his custom avrdude based bootloader project, feel free to... donate fraction of bitcoin at one of my Bitcoin adresses below, since I need to take a deep breath and
after this
picoboot code investigation, so it probably can save someone a lot of time