📄 bootm8v.bas
字号:
mov lo_byte,hex_reg 'Save in LS Byte register
rcall _char_to_byte 'Call routine to convert two characters to byte
mov hi_byte,hex_reg 'Save in MS Byte register
_verify_data_pair: 'Verify this data pair
brts _ver_end 'Do verify test only if VERIFY mode selected
ldi ser_reg, asc("!") 'Verify Error Flag
_ver_lo:
lpm 'Get the byte at this address
cp r0,lo_byte 'Compare to current LS byte
breq _ver_hi 'Branch if equal, otherwise send message
rcall _send_ser 'Call routine to send a character
_ver_hi:
inc ZL 'Increment the address to the high byte
lpm 'Get the byte at this address
dec ZL 'Decrement the address back to the low byte
cp r0,hi_byte 'Compare to current LS byte
breq _ver_end 'Branch if equal, otherwise send message
rcall _send_ser 'Call routine to send a character
_ver_end:
_store_word: 'Store current R1/R0 Word in page buffer at proper address
mov r0,lo_byte 'Save in R0, LS Byte of page write buffer
mov r1,hi_byte 'Save in R1, MS Byte of page write buffer
ldi spm_reg,1 'Load SPM Enable (SPMEN)
rcall _exec_spm 'Execute current SPM, return is in exec_spm
_check_byte_count: 'Check if this was the last word of the line
subi byte_cnt,2 'Decrement the Byte Count by two bytes
breq _read_checksum 'Done with this data, read checksum
subi ZL,$FE 'Not done, increment the low address byte by two
rjmp _read_data_pairs 'Go back and read the next two characters
_read_checksum: 'Byte count = record size, next is checksum for this line
rcall _char_to_byte 'Call routine to convert two characters to byte
breq _checksum_ok 'Must have added to zero, checksum is okay
_checksum_err: 'Checksum or other decoding error detected
ldi ser_reg, asc("C") 'Load "C" to send as Checksum error flag
rcall _send_ser 'Call routine to send a character
_checksum_ok:
'Done decoding and storing one complete input line, so check if this page is full
_chk_page_full: 'Check if this page is full
mov tmp_reg, ZL 'Load the address low byte into the temp reg
andi tmp_reg,((Pagesize - 1 )*2) 'AND with page size for this device, mask bits
cpi tmp_reg,((Pagesize - 1 )*2) 'Compare with page size for this device
brne _read_lines 'Page buffer is not full, read another line
_write_current_page: 'Write current page if the page buffer is full
andi ZL,$C0 'Page address in Z12 - Z6, ensure that Z5 - Z0 are 0
_erase_page: 'Erase Page,
ldi spm_reg,3 'Load Page Erase (PGERS) and SPM Enable (SPMEN)
rcall _exec_spm 'Execute current SPM
_write_page: 'Page address range is Z12-Z6 for Mega8
ldi spm_reg,5 'Load page write (PGWRT) and SPM Enable (SPMEN)
rcall _exec_spm 'Execute current SPM
_enable_page: 'Re-enable the Read-While-Write section
rcall _wait_spm 'Check if current write is complete
ldi spm_reg,11 'Set RWWSRE and SPMEN only
rcall _exec_spm 'Execute current SPM
_check_end_of_file: 'Check if this is the end of the file - T Flag
tst rec_size 'Test if record size is zero for this line
brne _read_lines 'Not the last page, continue to read in data lines
_exit_bootloader: 'Done, exit the bootloader code
ldi ser_reg, asc("D") 'Load "D" to send as done flag
rcall _send_ser 'Call routine to send a character
jmp $0000 'Jump to main program reset vector
'*******************************************************************************
'Send a serial character
_send_ser: 'Send a serial characater
sbis UCSRA,UDRE 'Check if USART data register is empty
rjmp _send_ser 'Not ready yet, wait
!out UDR,ser_reg 'Send serial register
ret
'*******************************************************************************
'Get one line from the serial port and store at start of SRAM
_receive_hex_line:
ldi XH,$01 'Set pointers to SRAM location $0100
ldi XL,$00 'Above all registers
ldi ser_reg, asc(".") 'No data now, so load "." to show progress
rcall _send_ser 'Call routine to send a character
_receive_hex_line_char: 'Get a character from UART and add to buffer
sbis UCSRA,RXC 'Check UART for a serial character received
rjmp _receive_hex_line_char 'No, check again...
in tmp_reg,UDR 'Store input character in temp register
' mov ser_reg, tmp_reg 'Echo this character for troubleshooting
' rcall _send_ser 'Call routine to send a character
cpi tmp_reg,13 'Compare with <CR>, input line terminator
breq _receive_hex_line_end 'Yes, line is finished, branch to end
st x+,tmp_reg 'Otherwise store value then increment buffer and
rjmp _receive_hex_line_char 'Go back and get next character
_receive_hex_line_end: 'This input line is finished, so
ret 'Done with this line, so return
'*******************************************************************************
'Get two characters from buffer, add to checksum and return with result in hex_reg
_char_to_byte:
ld hex_reg,x+ 'Load character into hex_reg, increment X
subi hex_reg,$41 'ASCII Value minus $41, "A"
brcc _char_to_byte1 'Branch if value was greater than $41
subi hex_reg,$F9 'Not greater, subtract $F9
_char_to_byte1:
subi hex_reg,$F6 'Subtract $F6
lsl hex_reg 'Shift this data
lsl hex_reg 'Left for four bits
lsl hex_reg 'To move it into the
lsl hex_reg 'High nibble
ld tmp_reg,x+ 'Get next character,
subi tmp_reg,$41 'ASCII Value minus $41, "A"
brcc _char_to_byte2 'Branch if value was greater than $41
subi tmp_reg,$F9 'Not greater, subtract $F9
_char_to_byte2:
subi tmp_reg,$F6 'Subtract $F6
add hex_reg,tmp_reg 'Add into hex register
add chk_sum,hex_reg 'Add it into the checksum for this line
ret
'*******************************************************************************
_exec_spm: 'Execute the current SPM instruction
brtc _exec_spm_end 'Do SPMs only if PROGRAMMING mode selected
!out spmcr,spm_reg 'Send to SPM Control Register
spm 'Do SPM instruction
_wait_spm: 'Check if current flash write is complete
in spm_reg,spmcr 'Get the SPM control Register
sbrc spm_reg,spmen 'Check if SPM Enable flag is clear
rjmp _wait_spm 'No, go back and wait for SPMEN flag cleared
_exec_spm_end: 'End of SPM routine
ret 'Flag cleared, Return
'*******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -