summaryrefslogtreecommitdiff
path: root/downloader
diff options
context:
space:
mode:
authorChristian Pointner <equinox@spreadspace.org>2013-07-07 01:48:13 +0000
committerChristian Pointner <equinox@spreadspace.org>2013-07-07 01:48:13 +0000
commitfc547cad2fffcaa354b170694796beddf37dd4a1 (patch)
tree3d94e7692ce139cf11e29f401a4a73356b136971 /downloader
parentskipping 'invalid' code doesn't work on some hardware (diff)
added length field for messages
git-svn-id: https://svn.spreadspace.org/pic/trunk@46 a09c6847-51d9-44de-8ef2-e725cf50f3c7
Diffstat (limited to 'downloader')
-rwxr-xr-xdownloader/downloader.py53
-rw-r--r--downloader/proto.txt52
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.