]> sigrok.org Git - libsigrokdecode.git/blame_incremental - decoders/avr_isp/pd.py
avr_isp: move "unknown command" to warning, drop empty 'bits' row
[libsigrokdecode.git] / decoders / avr_isp / pd.py
... / ...
CommitLineData
1##
2## This file is part of the libsigrokdecode project.
3##
4## Copyright (C) 2012-2014 Uwe Hermann <uwe@hermann-uwe.de>
5##
6## This program is free software; you can redistribute it and/or modify
7## it under the terms of the GNU General Public License as published by
8## the Free Software Foundation; either version 2 of the License, or
9## (at your option) any later version.
10##
11## This program is distributed in the hope that it will be useful,
12## but WITHOUT ANY WARRANTY; without even the implied warranty of
13## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14## GNU General Public License for more details.
15##
16## You should have received a copy of the GNU General Public License
17## along with this program; if not, see <http://www.gnu.org/licenses/>.
18##
19
20import sigrokdecode as srd
21from .parts import *
22
23class Ann:
24 PE, RSB0, RSB1, RSB2, CE, RFB, RHFB, REFB, \
25 WARN, DEV, = range(10)
26
27VENDOR_CODE_ATMEL = 0x1e
28
29class Decoder(srd.Decoder):
30 api_version = 3
31 id = 'avr_isp'
32 name = 'AVR ISP'
33 longname = 'AVR In-System Programming'
34 desc = 'Atmel AVR In-System Programming (ISP) protocol.'
35 license = 'gplv2+'
36 inputs = ['spi']
37 outputs = []
38 tags = ['Debug/trace']
39 annotations = (
40 ('pe', 'Programming enable'),
41 ('rsb0', 'Read signature byte 0'),
42 ('rsb1', 'Read signature byte 1'),
43 ('rsb2', 'Read signature byte 2'),
44 ('ce', 'Chip erase'),
45 ('rfb', 'Read fuse bits'),
46 ('rhfb', 'Read high fuse bits'),
47 ('refb', 'Read extended fuse bits'),
48 ('warning', 'Warning'),
49 ('dev', 'Device'),
50 )
51 annotation_rows = (
52 ('commands', 'Commands', (Ann.PE, Ann.RSB0, Ann.RSB1, Ann.RSB2,
53 Ann.CE, Ann.RFB, Ann.RHFB, Ann.REFB,)),
54 ('warnings', 'Warnings', (Ann.WARN,)),
55 ('devs', 'Devices', (Ann.DEV,)),
56 )
57
58 def __init__(self):
59 self.reset()
60
61 def reset(self):
62 self.state = 'IDLE'
63 self.mosi_bytes, self.miso_bytes = [], []
64 self.ss_cmd, self.es_cmd = 0, 0
65 self.xx, self.yy, self.zz, self.mm = 0, 0, 0, 0
66 self.ss_device = None
67
68 def start(self):
69 self.out_ann = self.register(srd.OUTPUT_ANN)
70
71 def putx(self, data):
72 self.put(self.ss_cmd, self.es_cmd, self.out_ann, data)
73
74 def handle_cmd_programming_enable(self, cmd, ret):
75 # Programming enable.
76 # Note: The chip doesn't send any ACK for 'Programming enable'.
77 self.putx([Ann.PE, ['Programming enable']])
78
79 # Sanity check on reply.
80 if ret[1:4] != [0xac, 0x53, cmd[2]]:
81 self.putx([Ann.WARN, ['Warning: Unexpected bytes in reply!']])
82
83 def handle_cmd_read_signature_byte_0x00(self, cmd, ret):
84 # Signature byte 0x00: vendor code.
85 self.vendor_code = ret[3]
86 v = vendor_code[self.vendor_code]
87 self.putx([Ann.RSB0, ['Vendor code: 0x%02x (%s)' % (ret[3], v)]])
88
89 # Store for later.
90 self.xx = cmd[1] # Same as ret[2].
91 self.yy = cmd[3]
92 self.zz = ret[0]
93
94 # Sanity check on reply.
95 if ret[1] != 0x30 or ret[2] != cmd[1]:
96 self.putx([Ann.WARN, ['Warning: Unexpected bytes in reply!']])
97
98 # Sanity check for the vendor code.
99 if self.vendor_code != VENDOR_CODE_ATMEL:
100 self.putx([Ann.WARN, ['Warning: Vendor code was not 0x1e (Atmel)!']])
101
102 def handle_cmd_read_signature_byte_0x01(self, cmd, ret):
103 # Signature byte 0x01: part family and memory size.
104 self.part_fam_flash_size = ret[3]
105 self.putx([Ann.RSB1, ['Part family / memory size: 0x%02x' % ret[3]]])
106
107 # Store for later.
108 self.mm = cmd[3]
109 self.ss_device = self.ss_cmd
110
111 # Sanity check on reply.
112 if ret[1] != 0x30 or ret[2] != cmd[1] or ret[0] != self.yy:
113 self.putx([Ann.WARN, ['Warning: Unexpected bytes in reply!']])
114
115 def handle_cmd_read_signature_byte_0x02(self, cmd, ret):
116 # Signature byte 0x02: part number.
117 self.part_number = ret[3]
118 self.putx([Ann.RSB2, ['Part number: 0x%02x' % ret[3]]])
119
120 p = part[(self.part_fam_flash_size, self.part_number)]
121 data = [Ann.DEV, ['Device: Atmel %s' % p]]
122 self.put(self.ss_device, self.es_cmd, self.out_ann, data)
123
124 # Sanity check on reply.
125 if ret[1] != 0x30 or ret[2] != self.xx or ret[0] != self.mm:
126 self.putx([Ann.WARN, ['Warning: Unexpected bytes in reply!']])
127
128 self.xx, self.yy, self.zz, self.mm = 0, 0, 0, 0
129
130 def handle_cmd_chip_erase(self, cmd, ret):
131 # Chip erase (erases both flash an EEPROM).
132 # Upon successful chip erase, the lock bits will also be erased.
133 # The only way to end a Chip Erase cycle is to release RESET#.
134 self.putx([Ann.CE, ['Chip erase']])
135
136 # TODO: Check/handle RESET#.
137
138 # Sanity check on reply.
139 bit = (ret[2] & (1 << 7)) >> 7
140 if ret[1] != 0xac or bit != 1 or ret[3] != cmd[2]:
141 self.putx([Ann.WARN, ['Warning: Unexpected bytes in reply!']])
142
143 def handle_cmd_read_fuse_bits(self, cmd, ret):
144 # Read fuse bits.
145 self.putx([Ann.RFB, ['Read fuse bits: 0x%02x' % ret[3]]])
146
147 # TODO: Decode fuse bits.
148 # TODO: Sanity check on reply.
149
150 def handle_cmd_read_fuse_high_bits(self, cmd, ret):
151 # Read fuse high bits.
152 self.putx([Ann.RHFB, ['Read fuse high bits: 0x%02x' % ret[3]]])
153
154 # TODO: Decode fuse bits.
155 # TODO: Sanity check on reply.
156
157 def handle_cmd_read_extended_fuse_bits(self, cmd, ret):
158 # Read extended fuse bits.
159 self.putx([Ann.REFB, ['Read extended fuse bits: 0x%02x' % ret[3]]])
160
161 # TODO: Decode fuse bits.
162 # TODO: Sanity check on reply.
163
164 def handle_command(self, cmd, ret):
165 if cmd[:2] == [0xac, 0x53]:
166 self.handle_cmd_programming_enable(cmd, ret)
167 elif cmd[0] == 0xac and (cmd[1] & (1 << 7)) == (1 << 7):
168 self.handle_cmd_chip_erase(cmd, ret)
169 elif cmd[:3] == [0x50, 0x00, 0x00]:
170 self.handle_cmd_read_fuse_bits(cmd, ret)
171 elif cmd[:3] == [0x58, 0x08, 0x00]:
172 self.handle_cmd_read_fuse_high_bits(cmd, ret)
173 elif cmd[:3] == [0x50, 0x08, 0x00]:
174 self.handle_cmd_read_extended_fuse_bits(cmd, ret)
175 elif cmd[0] == 0x30 and cmd[2] == 0x00:
176 self.handle_cmd_read_signature_byte_0x00(cmd, ret)
177 elif cmd[0] == 0x30 and cmd[2] == 0x01:
178 self.handle_cmd_read_signature_byte_0x01(cmd, ret)
179 elif cmd[0] == 0x30 and cmd[2] == 0x02:
180 self.handle_cmd_read_signature_byte_0x02(cmd, ret)
181 else:
182 c = '%02x %02x %02x %02x' % tuple(cmd)
183 r = '%02x %02x %02x %02x' % tuple(ret)
184 self.putx([Ann.WARN, ['Unknown command: %s (reply: %s)!' % (c, r)]])
185
186 def decode(self, ss, es, data):
187 ptype, mosi, miso = data
188
189 # For now, only use DATA and BITS packets.
190 if ptype not in ('DATA', 'BITS'):
191 return
192
193 # Store the individual bit values and ss/es numbers. The next packet
194 # is guaranteed to be a 'DATA' packet belonging to this 'BITS' one.
195 if ptype == 'BITS':
196 self.miso_bits, self.mosi_bits = miso, mosi
197 return
198
199 self.ss, self.es = ss, es
200
201 if len(self.mosi_bytes) == 0:
202 self.ss_cmd = ss
203
204 # Append new bytes.
205 self.mosi_bytes.append(mosi)
206 self.miso_bytes.append(miso)
207
208 # All commands consist of 4 bytes.
209 if len(self.mosi_bytes) < 4:
210 return
211
212 self.es_cmd = es
213
214 self.handle_command(self.mosi_bytes, self.miso_bytes)
215
216 self.mosi_bytes = []
217 self.miso_bytes = []