tests: added pack and unpack test
[renesas-ra-flasher] / flasher / flasher.py
1 # Copyright (C) Robin Krens - 2024
2
3 # This program is free software; you can redistribute it and/or
4 # modify it under the terms of the GNU General Public License
5 # as published by the Free Software Foundation; either version 2
6 # of the License, or (at your option) any later version.
7
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 # GNU General Public License for more details.
12
13 # You should have received a copy of the GNU General Public License
14 # along with this program; if not, write to the Free Software
15 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16 #
17
18 import struct
19
20 # Commands send to boot firmware
21 INQ_CMD = 0x00
22 ERA_CMD = 0x12
23 WRI_CMD = 0x13
24 REA_CMD = 0x15
25 IDA_CMD = 0x30
26 BAU_CMD = 0x34
27 SIG_CMD = 0x3A
28 ARE_CMD = 0x3B
29
30 # These are combined with send command, for example
31 # STATUS_OK | ERA_CMD == 0x12
32 # STATUS_ERR | ERA_CMD = 0x92
33 STATUS_OK = 0x00
34 STATUS_ERR = 0x80
35
36 # Error codes
37 ERR_UNSU = 0xC
38 ERR_PCKT = 0xC1
39 ERR_CHKS = 0xC2
40 ERR_FLOW = 0xC3
41 ERR_ADDR = 0xD0
42 ERR_BAUD = 0xD4
43 ERR_PROT = 0xDA
44 ERR_ID = 0xDB
45 ERR_SERI = 0xDC
46 ERR_ERA = 0xE1
47 ERR_WRI = 0xE2
48 ERR_SEQ = 0xE7
49
50 # used for init sequence
51 LOW_PULSE = 0x00
52 GENERIC_CODE = 0x55
53 BOOT_CODE = 0xC3
54
55 TESTID = [
56     "0xF0", "0xF1", "0xF2", "0xF3",
57     "0xE4", "0xE5", "0xE6", "0xE7",
58     "0xD8", "0xD9", "0xDA", "0xDB",
59     "0xCC", "0xCD", "0xCE", "0xCF"
60 ]
61
62 def calc_sum(cmd, data):
63     data_len = len(data)
64     lnh = data_len + 1 & 0xFF00
65     lnl = data_len + 1 & 0x00FF
66     res = lnh + lnl + cmd
67     for i in range(data_len):
68             if isinstance(data[i], str):
69                 res += int(data[i], 16)
70             else:
71                 res += ord(data[i])
72     res = ~(res - 1) & 0xFF # two's complement
73     return (lnh, lnl, res)
74
75
76 # format of data packet is [SOD|LNH|LNL|COM|byte_data|SUM|ETX]
77 def format_command(cmd, data):
78     SOD = 0x01
79     COM = cmd
80
81     if isinstance(data, str):
82         byte_data = bytes(data.encode('utf-8'))
83     else:
84         byte_data = bytes([int(x, 16) for x in data])
85     
86     LNH, LNL, SUM = calc_sum(int(cmd), data)
87     ETX = 0x03
88     fmt_header = '<BBBB'
89     fmt_footer = 'BB'
90     fmt = fmt_header + str(len(data)) + 's' + fmt_footer
91     pack = struct.pack(fmt, SOD, LNH, LNL, COM, byte_data, SUM, ETX)
92     print(fmt, pack, len(pack))
93     return fmt
94
95 # format of data packet is [SOD|LNH|LNL|RES|DAT|SUM|ETX]
96 def format_data(res, data):
97     SOD = 0x81
98     if (len(data) >= 1024):
99         raise Exception(f'Data packet too large, data length is {DATA_LEN} (>1024)')
100     LNH, LNL, SUM = calc_sum(int(res), data)
101     DAT = bytes([int(x, 16) for x in data])
102     RES = res
103     ETX = 0x03
104     fmt_header = '<BBBB'
105     fmt_footer = 'BB'
106     fmt = fmt_header + str(len(data)) + 's' + fmt_footer
107     pack = struct.pack(fmt, SOD, LNH, LNL, RES, DAT, SUM, ETX)
108     print(fmt, pack, len(pack))
109
110 # packet received from mcu 
111 def unpack_header(data):
112     header = data[0:4]
113     fmt_header = '<BBBB'
114     SOD, LNH, LNL, RES = struct.unpack(fmt_header, header)
115     if (SOD != 0x81):
116         raise Exception(f'Wrong start of packet data received')
117     pkt_len = (LNH << 0x8 | LNL) - 1
118     if (RES & 0x80):
119         raise Exception(f'MCU encountered error {RES & 0x7F}')
120     fmt_message = '<' + str(pkt_len) + 's'
121     raw = struct.unpack_from(fmt_message, data, 4)[0]
122     message = ['0x{:02X}'.format(byte) for byte in raw]
123     fmt_footer = '<BB'
124     SUM, ETX = struct.unpack_from(fmt_footer, data, 4 + pkt_len)
125     lnh, lnl, local_sum = calc_sum(RES, message)
126     if (SUM != local_sum):
127         raise Exception(f'Sum calculation mismatch, read {local_sum} instead of {SUM}')
128     if (ETX != 0x03):
129         raise Exception(f'Packet ETX error')
130     return message
131
132     
133
134 cmd = format_command(INQ_CMD, "")
135 cmd = format_command(BAU_CMD, ['0x00','0x1E'])
136 cmd = format_command(IDA_CMD, TESTID)
137
138 format_data(0x13, ['0x00','0x01','0x02'])
139 format_data(0x34, ['0x00'])
140 format_data(0x00, ['0x00'])
141 format_data(0x12, ['0x00'])
142
143 #print(unpack_header(b'\x81\x00\x02\x08\xC0\x12\x03'))
144 #print(unpack_header(b'\x81\x00\x03\x08\xC0\xD0\x12\x03'))
145 print(unpack_header(b'\x81\x00\x02\x00\x00\xFE\x03'))