diff options
-rw-r--r-- | bootloader/bootloader.asm | 129 | ||||
-rwxr-xr-x | downloader/downloader.py | 53 | ||||
-rw-r--r-- | downloader/proto.txt | 52 |
3 files changed, 104 insertions, 130 deletions
diff --git a/bootloader/bootloader.asm b/bootloader/bootloader.asm index f8b609c..ff23d61 100644 --- a/bootloader/bootloader.asm +++ b/bootloader/bootloader.asm @@ -37,11 +37,10 @@ VERSION_MAJ EQU .0 VERSION_MIN EQU .1 DEVID_H EQU H'20' DEVID_L EQU H'82' -FSS EQU .16 -MESS_H EQU .0 -MESS_L EQU .64 +FSS EQU .16 ; writing is done 8 words at a time but 16 words get erased +MESS EQU .64 ; this limit is because of to combuff size and single byte len field for messages SUPPORTED_H EQU .0 -SUPPORTED_L EQU b'00011110' ; read/write flash, read/write eeprom +SUPPORTED_L EQU b'00000110' ; only read/write flash is supported by now ;; ERROR codes E_OK EQU .0 @@ -76,7 +75,7 @@ current_cmdlen EQU H'0070' csum EQU H'0071' flags EQU H'007D' -#define F_WEEP flags,0 +#define F_NEW_CMD flags,0 cnt2 EQU H'007E' cnt1 EQU H'007F' @@ -104,6 +103,9 @@ uart_tx_byte return send_answer + addlw .3 + movwf combuff + .1 + decf combuff + .1,w movwf cnt1 movlw combuff movwf FSR @@ -119,19 +121,6 @@ send_answer_next call uart_tx_byte return -get_cmdlen - addwf PCL,f - retlw .0 ; invalid - retlw .1 ; identify: <csum> - retlw .1 ; boot: <csum> - retlw .1 ; reset: <csum> - retlw .3 ; read flash: addr | <csum> - retlw .3 + .2*FSS ; write flash: addr | data | <csum> - retlw .5 ; read eeprom: addr | len | <csum> - retlw .5 ; write eeprom: addr | len | data | <csum> (minimal) - retlw .2 ; read config: nr | <csum> - retlw .4 ; write config: nr | word | <csum> - get_name addwf PCL,f nop @@ -197,6 +186,8 @@ uart_rx_byte ; process received command movf RCREG,w movwf INDF incf FSR,f + btfss F_NEW_CMD + goto wait_cmd_len movf current_cmdlen,f btfsc STATUS,Z goto new_cmd @@ -208,39 +199,43 @@ uart_rx_fe ; recover from framing error movf RCREG,w goto wait_new_cmd +wait_cmd_len + bsf F_NEW_CMD + goto wait_cmd + new_cmd ; got new command code movf combuff,w sublw CMD_MAX btfss STATUS,C goto invalid_cmd - movf combuff,w - call get_cmdlen + decfsz combuff + .1,w + goto load_cmdlen + goto invalid_cmd +load_cmdlen movwf current_cmdlen + decfsz current_cmdlen,f goto wait_cmd - -invalid_cmd ; received command code is not known +invalid_cmd ; received command code is not known or len is bogus movlw E_INV_CMD - movwf combuff + .1 - movlw .2 + movwf combuff + .2 + movlw .1 call send_answer goto wait_new_cmd exec_cmd ; command is correct and complete - ;; TODO: check csum -> csum for write eeprom will not be correct because - ;; it isn't finished yet....??? + ;; TODO: check csum movf combuff,w ; dispatch commands addwf PCL,f goto wait_new_cmd - goto cmd_identify - goto cmd_boot - goto cmd_reset - goto cmd_r_flash - goto cmd_w_flash - goto cmd_r_eeprom - goto cmd_w_eeprom - goto cmd_r_config - goto cmd_w_config - goto wait_new_cmd + goto cmd_identify ; identify + goto cmd_boot ; boot + goto cmd_not_impl ; reset + goto cmd_r_flash ; read flash segment + goto cmd_w_flash ; write flash segment + goto cmd_not_impl ; read eeprom + goto cmd_not_impl ; write eeprom + goto cmd_not_impl ; read config + goto cmd_not_impl ; write config ;; ** Command Handlers ******************** ;; ** identify ******* @@ -249,6 +244,9 @@ cmd_identify movf combuff,w call uart_tx_byte + movlw .22 + call uart_tx_byte + movlw E_OK call uart_tx_byte @@ -273,10 +271,7 @@ cmd_identify_send_name movlw FSS call uart_tx_byte - - movlw MESS_L - call uart_tx_byte - movlw MESS_H + movlw MESS call uart_tx_byte movlw SUPPORTED_L @@ -291,8 +286,8 @@ cmd_identify_send_name ;; ** boot ******* cmd_boot movlw E_OK - movwf combuff + .1 - movlw .2 + movwf combuff + .2 + movlw .1 call send_answer goto USERVECT @@ -308,39 +303,11 @@ cmd_w_flash call send_answer goto wait_new_cmd - ;; ** read eeprom ******* -cmd_r_eeprom - ;; call read_eeprom - movlw E_ADDR_INVALID - movwf combuff + .1 - movlw .2 - call send_answer - goto wait_new_cmd - - ;; ** write eeprom ******* -cmd_w_eeprom - btfss F_WEEP - goto cmd_w_eeprom_len - ;; call write_eeprom - movlw E_ADDR_INVALID - movwf combuff + .1 - movlw .2 - call send_answer - goto wait_new_cmd - -cmd_w_eeprom_len - movf combuff + .3,w - movwf current_cmdlen - bsf F_WEEP - goto wait_cmd - ;; ** not implemented commands ******* -cmd_reset -cmd_r_config -cmd_w_config +cmd_not_impl movlw E_NOT_IMPL - movwf combuff + .1 - movlw .2 + movwf combuff + .2 + movlw .1 call send_answer goto wait_new_cmd @@ -352,7 +319,7 @@ read_flash_segment movwf cnt1 movlw b'01011000' movwf STATUS - movlw combuff + .1 + movlw combuff + .2 movwf FSR movf INDF,w movwf EEADR @@ -379,8 +346,8 @@ read_flash_segment_next decfsz cnt1,f goto read_flash_segment_loop bcf STATUS,RP1 - clrf combuff + .1 ; = E_OK - retlw .2 + .2*FSS ; bytes to send + clrf combuff + .2 ; = E_OK + retlw .1 + .2*FSS ; bytes to send ;; flash write -------- write_flash_segment @@ -388,7 +355,7 @@ write_flash_segment movwf cnt1 movlw b'01011000' movwf STATUS - movlw combuff + .1 + movlw combuff + .2 movwf FSR movf INDF,w movwf EEADR @@ -397,7 +364,7 @@ write_flash_segment movwf EEADRH write_flash_segment_loop - incf FSR,f ; load data into EEDAT:EEDATH + incf FSR,f ; load code word into EEDAT:EEDATH movf INDF,w movwf EEDAT incf FSR,f @@ -423,13 +390,13 @@ write_flash_segment_next decfsz cnt1,f goto write_flash_segment_loop bsf STATUS,RP0 - clrw + clrw ; check if a write error occured btfsc EECON1,WRERR movlw E_FLASH_WERR bcf STATUS,RP1 bcf STATUS,RP0 - movwf combuff + .1 ; = E_OK - retlw .2 ; bytes to send + movwf combuff + .2 ; = E_OK + retlw .1 ; bytes to send ;; ------------------------------------- ;; ------------------------------------- diff --git a/downloader/downloader.py b/downloader/downloader.py index 9efb30e..f90eced 100755 --- a/downloader/downloader.py +++ b/downloader/downloader.py @@ -100,7 +100,7 @@ def calc_csum(str): cs ^= c return cs -def exec_command(dev, cmd, answer): +def exec_command(dev, cmd, param, answer): import struct return_codes = { 0: "OK", 1: "invalid command", 2: "bad checksum", @@ -108,21 +108,22 @@ def exec_command(dev, cmd, answer): 5: "address invalid", 6: "address prohibited", 7: "value out of bounds" } - cstr = bytearray(cmd) + cstr = bytearray(struct.pack('<BB', cmd, 0) + param) cstr.extend(struct.pack("<B", calc_csum(cstr))) + cstr[1] = len(cstr) dev.write(cstr) astr = bytearray() - astr += dev.read(3) - if len(astr) < 3: - print "ERROR: timeout while reading response header" + astr += dev.read(4) + if len(astr) < 4: + print "ERROR: timeout while reading response header (expected %d bytes, got %d)" % (4, len(astr)) sys.exit(4) if astr[0] != cstr[0]: print "ERROR: bootloader returned wrong command code" sys.exit(4) - ret = astr[1] + ret = astr[2] if ret != 0: rstr = "invalid return code" try: @@ -132,12 +133,16 @@ def exec_command(dev, cmd, answer): print "ERROR: bootloader returned %d: %s" % (ret, rstr) sys.exit(4) - answer_len = struct.calcsize(answer) + answer_len = astr[1] - 4 + if answer_len < struct.calcsize(answer): + print "ERROR: short answer %d bytes received: expected %s bytes" % (answer_len, struct.calcsize(answer)) + sys.exit(4) + if answer_len > 0: tmp = bytearray() tmp += dev.read(answer_len) if len(tmp) < answer_len: - print "ERROR: timeout while reading response" + print "ERROR: timeout while reading response (expected %d bytes, got %d)" % (answer_len, len(tmp)) sys.exit(4) astr += tmp @@ -146,12 +151,12 @@ def exec_command(dev, cmd, answer): print "ERROR: checksum error" sys.exit(4) - return struct.unpack_from(answer, astr, 2) + return struct.unpack_from(answer, astr, 3) ### Commands def identify(dev): - data = exec_command(dev, struct.pack('<B', 1), '<BB10sHBHH') + data = exec_command(dev, 1, '', '<BB10sHBBH') id = { 'ver_min': data[0], 'ver_maj': data[1], 'name': data[2], 'devid': data[3], 'fss': data[4], 'mess': data[5], 'supported': data[6] } @@ -166,35 +171,35 @@ def identify(dev): return id def boot(dev): - exec_command(dev, struct.pack('<B', 2), '<') + exec_command(dev, 2, '', '<') def reset(dev, id): - exec_command(dev, struct.pack('<B', 3), '<') + exec_command(dev, 3, '', '<') def read_flash_segment(dev, id, addr): - cmd = struct.pack('<BH', 4, addr) - return exec_command(dev, cmd, '<%dH' % id['fss']) + param = struct.pack('<H', addr) + return exec_command(dev, 4, param, '<%dH' % id['fss']) def write_flash_segment(dev, id, addr, data): - cmd = struct.pack('<BH%dH' % id['fss'], 5, addr, *data) - return exec_command(dev, cmd, '<') + param = struct.pack('<H%dH' % id['fss'], addr, *data) + return exec_command(dev, 5, param, '<') def read_eeprom(dev, id, addr, len): - cmd = struct.pack('<BHH', 6, addr, len) - return exec_command(dev, cmd, '<%dB' % len) + param = struct.pack('<HB', addr, len) + return exec_command(dev, 6, param, '<%dB' % len) def write_eeprom(dev, id, addr, data): - cmd = struct.pack('<BHH%dB' % len(data), 7, addr, len(data), *data) - return exec_command(dev, cmd, '<') + param = struct.pack('<HB%dB' % len(data), addr, len(data), *data) + return exec_command(dev, 7, param, '<') def read_config(dev, id, nr): - cmd = struct.pack('<BB', 8, nr) - data = exec_command(dev, cmd, '<H') + param = struct.pack('<B', nr) + data = exec_command(dev, 8, param, '<H') return data[0] def write_config(dev, id, nr, word): - cmd = struct.pack('<BBH', 9, nr, word) - return exec_command(dev, cmd, '<') + param = struct.pack('<BH', nr, word) + return exec_command(dev, 9, param, '<') ### Main diff --git a/downloader/proto.txt b/downloader/proto.txt index e85368e..17dec93 100644 --- a/downloader/proto.txt +++ b/downloader/proto.txt @@ -17,11 +17,13 @@ Command List: Description: ------------ -Every command consits of one byte command code, a fixed number of bytes as -arguments and ends with a XOR checksum over all bytes sent. All data is +Every command consits of one byte command code, one byte length which counts all +bytes of the command including the command code and checksum. The length is followed +by zero or more data and a XOR checksum over all bytes sent. All data is transferred LSB first (aka little endian). All addresses and words are 2bytes long. -Every answer to a command starts with the command code. One byte return value, -optionally some data and a checksum (XOR over all bytes received) +Every answer to a command starts with the command code a length field which counts all +bytes of the answer, one byte return value optionally some data and a checksum +(XOR over all bytes received). The return codes have the following meaning: code | Error @@ -38,10 +40,10 @@ The return codes have the following meaning: identify: ~~~~~~~~~ command: - 1 | <csum> (in this case <csum> will always be 1) + 1 | len=3 | <csum> answer: - 1 | <ret> | version | name | devid | fss | mess | supported | <csum> + 1 | len=22 | <ret> | version | name | devid | fss | mess | supported | <csum> version: 2bytes, protocol version @@ -64,7 +66,7 @@ identify: operation first. mess: - 2bytes, maximum eeprom segment size + 1byte, maximum eeprom segment size This represents the maximum number of eeprom bytes which may be written or read at once. Unlike <fss> value it is ok to write or read less than <mess> bytes. @@ -89,10 +91,10 @@ boot: ~~~~~ command: - 2 | <csum> (in this case <csum> will always be 2) + 2 | len=3 | <csum> answer: - 2 | <ret> | <csum> + 2 | len=4 | <ret> | <csum> This instucts the bootloader to boot to the user application directly (no reset) @@ -101,10 +103,10 @@ reset: ~~~~~~ command: - 3 | <csum> (in this case <csum> will always be 3) + 3 | len=3 | <csum> answer: - 3 | <ret> | <csum> + 3 | len=4 | <ret> | <csum> The device performs a reboot. If the boot condition (i.e.: port pin) is not met this instructs the device to boot to the user application. @@ -114,10 +116,10 @@ read flash: ~~~~~~~~~~~ command: - 4 | addr | <csum> + 4 | len=5 | addr | <csum> answer: - 4 | <ret> | data | <csum> + 4 | len=4+2*<fss> | <ret> | data | <csum> The bootloader reads <fss> words from flash address <addr> and returns it as <data>. @@ -127,10 +129,10 @@ write flash: ~~~~~~~~~~~~ command: - 5 | addr | data | <csum> + 5 | len=5+2*<fss> | addr | data | <csum> answer: - 5 | <ret> | <csum> + 5 | len=4 | <ret> | <csum> The bootloader writes <data> (which has to contain exactly <fss> words) to address <addr> inside the flash. The start address has to be aligned to <fss> boundaries. @@ -142,36 +144,36 @@ read eeprom: ~~~~~~~~~~~~ command: - 6 | addr | len | <csum> + 6 | len=5 | addr | len | <csum> answer: - 6 | <ret> | data | <csum> + 6 | len=4+<len> | <ret> | data | <csum> The bootloader reads <len> bytes from eeprom at address <addr> and returns it as - <data>. len is 2bytes long. + <data>. len is 1byte long. write eeprom: ~~~~~~~~~~~~~ command: - 7 | addr | len | data | <csum> + 7 | len=4+2<len(data) | addr | data | <csum> answer: - 7 | <ret> | <csum> + 7 | len=4 | <ret> | <csum> The bootloader writes <data> (which has to contain exactly <len> bytes) to address - <addr> inside the eeprom. len is 2bytes long and the value must not exceed <mess> bytes. + <addr> inside the eeprom. len is 1byte long and the value must not exceed <mess> bytes. read config: ~~~~~~~~~~~~ command: - 8 | nr | <csum> + 8 | len=3 | nr | <csum> answer: - 8 | <ret> | word | <csum> + 8 | len=6 | <ret> | word | <csum> The bootloader reads and returns the configuration word number <nr>. <nr> is one byte long. @@ -181,10 +183,10 @@ write config: ~~~~~~~~~~~~~ command: - 9 | nr | word | <csum> + 9 | len=5 | nr | word | <csum> answer: - 9 | <ret> | <csum> + 9 | len=4 | <ret> | <csum> The bootloader writes <word> onto configuration word number <nr>. <nr> is one byte long. |