diff options
Diffstat (limited to 'downloader')
-rwxr-xr-x | downloader/downloader.py | 53 | ||||
-rw-r--r-- | downloader/proto.txt | 52 |
2 files changed, 56 insertions, 49 deletions
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. |