As part of my application, I need to be able to update the code on my mega 2560 in the field with a download from the internet.
I have found this code in the AT Mega 2560 data sheet
;-the routine writes one page of data from RAM to Flash
; the first data location in RAM is pointed to by the Y pointer
; the first data location in Flash is pointed to by the Z-pointer
;-error handling is not included
;-the routine must be placed inside the Boot space
; (at least the Do_spm sub routine). Only code inside NRWW section can
; be read during Self-Programming (Page Erase and Page Write).
;-registers used: r0, r1, temp1 (r16), temp2 (r17), looplo (r24),
; loophi (r25), spmcrval (r20)
; storing and restoring of registers is not included in the routine
; register usage can be optimized at the expense of code size
;-It is assumed that either the interrupt table is moved to the Boot
; loader section or that the interrupts are disabled
..equ PAGESIZEB = PAGESIZE*2 ;PAGESIZEB is page size in BYTES, not words
.org SMALLBOOTSTART
Write_page:
; Page Erase
ldi spmcrval, (1<<PGERS) | (1<<SPMEN)
call Do_spm
; re-enable the RWW section
ldi spmcrval, (1<<RWWSRE) | (1<<SPMEN)
call Do_spm
; transfer data from RAM to Flash page buffer
ldi looplo, low(PAGESIZEB) ;init loop variable
ldi loophi, high(PAGESIZEB) ;not required for PAGESIZEB<=256
Wrloop:
ld r0, Y+
ld r1, Y+
ldi spmcrval, (1<<SPMEN)
call Do_spm
adiw ZH:ZL, 2
sbiw loophi:looplo, 2 ;use subi for PAGESIZEB<=256
brne Wrloop
; execute Page Write
subi ZL, low(PAGESIZEB) ;restore pointer
sbci ZH, high(PAGESIZEB) ;not required for PAGESIZEB<=256
ldi spmcrval, (1<<PGWRT) | (1<<SPMEN)
call Do_spm
; re-enable the RWW section
ldi spmcrval, (1<<RWWSRE) | (1<<SPMEN)
call Do_spm
; read back and check, optional
ldi looplo, low(PAGESIZEB) ;init loop variable
ldi loophi, high(PAGESIZEB) ;not required for PAGESIZEB<=256
subi YL, low(PAGESIZEB) ;restore pointer
sbci YH, high(PAGESIZEB)
Rdloop:
elpm r0, Z+
ld r1, Y+
cpse r0, r1
jmp Error
sbiw loophi:looplo, 1 ;use subi for PAGESIZEB<=256
brne Rdloop
; return to RWW section
; verify that RWW section is safe to read
Return:
in temp1, SPMCSR
sbrs temp1, RWWSB ; If RWWSB is set, the RWW section is not ready yet
ret
; re-enable the RWW section
ldi spmcrval, (1<<RWWSRE) | (1<<SPMEN)
call Do_spmr
jmp Return
Do_spm:
; check for previous SPM complete
Wait_spm:
in temp1, SPMCSR
sbrc temp1, SPMEN
rjmp Wait_spm
; input: spmcrval determines SPM action
; disable interrupts if enabled, store status
in temp2, SREG
cli
; check that no EEPROM write access is present
Wait_ee:
sbic EECR, EEPE
rjmp Wait_ee
; SPM timed sequence
out SPMCSR, spmcrval
spm
; restore SREG (to enable interrupts if originally enabled)
out SREG, temp2
ret
I am trying to convert this to code I can use in my arduino project under wiring. My first question is the register. It looks like spmcrval
is register 20, but how can I access that register from within my arduino project?
I have found constants like SPMEN
in the arduino header, but not these register names.
Also, feel free, if you wish, to avoid the drama and say, "Here's the C source code," which will be worth a certain amount of hero worship.
Everything appears to use avrdude and so I'm trying to parse that as well.
-
github.com/jandrassy/ArduinoOTA/blob/master/examples/Advanced/…Juraj– Juraj ♦2021年06月25日 17:48:52 +00:00Commented Jun 25, 2021 at 17:48
1 Answer 1
Only from bootloader section is it possible to write to flash on ATmega2560. Optiboot 8 has a do_spm function to write to flash. It is accesible over a header file available in examples in the Optiboot GithHub repository.
After the updated application binary is written to free part of the flash by the running application it is necessary to copy the updated application to run location from address 0. This must be done again by the bootloader.
Optiboot builds in MCUdude Mega Core and Mighty Core have Optiboot enhanced with my copy_flash_pages function which copies the pages and then resets the MCU.
My ArduinoOTA library uses do_spm and copy_flash_pages function to store and apply uploaded sketch binary. The InternalStorage object can be used to apply a downloaded binary too.
-
1What I'm seeing handles the downloads. Is there something here that installs those downloads into the Mega 2560? I am pushing from a tablet.Thom– Thom2021年06月25日 18:56:35 +00:00Commented Jun 25, 2021 at 18:56
-
1it is a self update. calling InternalStorage.apply replaces the sketch with the downloaded binary2021年06月25日 19:43:11 +00:00Commented Jun 25, 2021 at 19:43
-
posted another question here: arduino.stackexchange.com/questions/85142/… about how to change a serial port to the one used by HC-05. can't find an example, but it seems basic.Thom– Thom2021年07月12日 16:28:18 +00:00Commented Jul 12, 2021 at 16:28