Не знаю, как насчет 640-й, но некоторые Меги не поддерживают побайтную запись флеш. Т.е. с каждым байтом будет переписываться вся страница из почти пустого буфера, т.е. 0хFF. В итоге мы увидим полностью затертую память.
Делал на 644 самопрограммирование по COM-порту из стандартного набора на асме
постранично, и все работало!
Размещается прога в секторе smallboot.
Чтобы перешить сам загрузчик, надо исполнять подобную программу из общей памяти. Вот и все

Код
.equ PAGESIZEB = 256;PAGESIZEB is page size in BYTES, not words
.org SMALLBOOTSTART
.equ spm_pagebuf=$110; 256bytex
.equ spm_numpages=$10A
.equ spm_crc1=$10B
.equ spm_crc2=$10C
.equ spm_crc3=$10D
.equ spm_crc4=$10E
com_spi:
cli
rcall com__read
cpi tmp,'F'
breq spi_flsh
jmp 0; suxxxxxxxxxxxxxx!!!!!!!!
spi_flsh:
rcall com__read
sts spm_numpages,tmp
clr zh
clr zl
lds cnt1,spm_numpages
spm_rdda1:
push cnt1
ldiy spm_pagebuf
ldi tmp,0xCB
rcall com__write
clr cnt
spm_rdda:
rcall com__read
st y+,tmp
djnz cnt,spm_rdda
ldiy spm_pagebuf
rcall Write_page
inc zh
pop cnt1
djnz cnt1,spm_rdda1
ldi tmp,0xCB
rcall com__write
jmp 0
Write_page:
; Page Erase
ldi tmp, (1<<PGERS) | (1<<SPMEN)
rcall Do_spm
; re-enable the RWW section
ldi tmp, (1<<RWWSRE) | (1<<SPMEN)
rcall Do_spm
; transfer data from RAM to Flash page buffer
ldi cnt, 0 ;init loop variable 256
Wrloop:
ld r0, Y+
ld r1, Y+
ldi tmp, (1<<SPMEN)
rcall Do_spm
adiw ZH:ZL, 2
subi cnt, 2;use subi for PAGESIZEB<=256
brne Wrloop
dec zh
; execute Page Write
ldi tmp, (1<<PGWRT) | (1<<SPMEN)
call Do_spm
; re-enable the RWW section
ldi tmp, (1<<RWWSRE) | (1<<SPMEN)
call Do_spm
; read back and check, optional
Return:
in tmp, SPMCSR
sbrs tmp, RWWSB; If RWWSB is set, the RWW section is not ready yet
ret
rjmp Return
Do_spm:
; check for previous HW ops complete
Wait_spm:
in tmp1, SPMCSR
sbrc tmp1, SPMEN
rjmp Wait_spm
Wait_ee:
sbic EECR, EEPE
rjmp Wait_ee
; SPM timed sequence
out SPMCSR, tmp
spm
ret
com__write: lds tmp1,ucsr0a sbrs tmp1,udre0 rjmp com__write sts udr0,tmp ret
com__read: lds tmp1,ucsr0a sbrs tmp1,rxc0 rjmp com__read lds tmp,udr0 ret