]> sigrok.org Git - libsigrokdecode.git/blame - decoders/avr_isp/pd.py
avr_isp: move "unknown command" to warning, drop empty 'bits' row
[libsigrokdecode.git] / decoders / avr_isp / pd.py
CommitLineData
3bd76451 1##
50bd5d25 2## This file is part of the libsigrokdecode project.
3bd76451 3##
ad30cb46 4## Copyright (C) 2012-2014 Uwe Hermann <uwe@hermann-uwe.de>
3bd76451
UH
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
4539e9ca 17## along with this program; if not, see <http://www.gnu.org/licenses/>.
3bd76451
UH
18##
19
3bd76451 20import sigrokdecode as srd
77adad94 21from .parts import *
3bd76451 22
f5250c60
HK
23class Ann:
24 PE, RSB0, RSB1, RSB2, CE, RFB, RHFB, REFB, \
25 WARN, DEV, = range(10)
26
3bd76451
UH
27VENDOR_CODE_ATMEL = 0x1e
28
29class Decoder(srd.Decoder):
b197383c 30 api_version = 3
3bd76451
UH
31 id = 'avr_isp'
32 name = 'AVR ISP'
d523eae6 33 longname = 'AVR In-System Programming'
2787cf2a 34 desc = 'Atmel AVR In-System Programming (ISP) protocol.'
3bd76451 35 license = 'gplv2+'
4e4f8527 36 inputs = ['spi']
6cbba91f 37 outputs = []
d6d8a8a4 38 tags = ['Debug/trace']
da9bcbd9
BV
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'),
e144452b 48 ('warning', 'Warning'),
da9bcbd9
BV
49 ('dev', 'Device'),
50 )
3b001341 51 annotation_rows = (
f5250c60
HK
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,)),
3b001341 56 )
3bd76451 57
92b7b49f 58 def __init__(self):
10aeb8ea
GS
59 self.reset()
60
61 def reset(self):
3bd76451
UH
62 self.state = 'IDLE'
63 self.mosi_bytes, self.miso_bytes = [], []
486b19ce 64 self.ss_cmd, self.es_cmd = 0, 0
3bd76451 65 self.xx, self.yy, self.zz, self.mm = 0, 0, 0, 0
486b19ce 66 self.ss_device = None
3bd76451 67
8915b346 68 def start(self):
be465111 69 self.out_ann = self.register(srd.OUTPUT_ANN)
3bd76451 70
3bd76451 71 def putx(self, data):
486b19ce 72 self.put(self.ss_cmd, self.es_cmd, self.out_ann, data)
3bd76451
UH
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'.
f5250c60 77 self.putx([Ann.PE, ['Programming enable']])
3bd76451
UH
78
79 # Sanity check on reply.
80 if ret[1:4] != [0xac, 0x53, cmd[2]]:
f5250c60 81 self.putx([Ann.WARN, ['Warning: Unexpected bytes in reply!']])
3bd76451
UH
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]
f5250c60 87 self.putx([Ann.RSB0, ['Vendor code: 0x%02x (%s)' % (ret[3], v)]])
3bd76451
UH
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]:
f5250c60 96 self.putx([Ann.WARN, ['Warning: Unexpected bytes in reply!']])
3bd76451
UH
97
98 # Sanity check for the vendor code.
99 if self.vendor_code != VENDOR_CODE_ATMEL:
f5250c60 100 self.putx([Ann.WARN, ['Warning: Vendor code was not 0x1e (Atmel)!']])
3bd76451
UH
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]
f5250c60 105 self.putx([Ann.RSB1, ['Part family / memory size: 0x%02x' % ret[3]]])
3bd76451
UH
106
107 # Store for later.
108 self.mm = cmd[3]
486b19ce 109 self.ss_device = self.ss_cmd
3bd76451
UH
110
111 # Sanity check on reply.
112 if ret[1] != 0x30 or ret[2] != cmd[1] or ret[0] != self.yy:
f5250c60 113 self.putx([Ann.WARN, ['Warning: Unexpected bytes in reply!']])
3bd76451
UH
114
115 def handle_cmd_read_signature_byte_0x02(self, cmd, ret):
116 # Signature byte 0x02: part number.
117 self.part_number = ret[3]
f5250c60 118 self.putx([Ann.RSB2, ['Part number: 0x%02x' % ret[3]]])
3bd76451 119
3bd76451 120 p = part[(self.part_fam_flash_size, self.part_number)]
f5250c60 121 data = [Ann.DEV, ['Device: Atmel %s' % p]]
486b19ce 122 self.put(self.ss_device, self.es_cmd, self.out_ann, data)
3bd76451
UH
123
124 # Sanity check on reply.
125 if ret[1] != 0x30 or ret[2] != self.xx or ret[0] != self.mm:
f5250c60 126 self.putx([Ann.WARN, ['Warning: Unexpected bytes in reply!']])
3bd76451
UH
127
128 self.xx, self.yy, self.zz, self.mm = 0, 0, 0, 0
129
130 def handle_cmd_chip_erase(self, cmd, ret):
1fd698dc
UH
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#.
f5250c60 134 self.putx([Ann.CE, ['Chip erase']])
3bd76451 135
1fd698dc
UH
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]:
f5250c60 141 self.putx([Ann.WARN, ['Warning: Unexpected bytes in reply!']])
1fd698dc 142
3bd76451
UH
143 def handle_cmd_read_fuse_bits(self, cmd, ret):
144 # Read fuse bits.
f5250c60 145 self.putx([Ann.RFB, ['Read fuse bits: 0x%02x' % ret[3]]])
3bd76451
UH
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.
f5250c60 152 self.putx([Ann.RHFB, ['Read fuse high bits: 0x%02x' % ret[3]]])
3bd76451
UH
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.
f5250c60 159 self.putx([Ann.REFB, ['Read extended fuse bits: 0x%02x' % ret[3]]])
3bd76451
UH
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)
3f2a4616 184 self.putx([Ann.WARN, ['Unknown command: %s (reply: %s)!' % (c, r)]])
3bd76451
UH
185
186 def decode(self, ss, es, data):
187 ptype, mosi, miso = data
188
ad30cb46
UH
189 # For now, only use DATA and BITS packets.
190 if ptype not in ('DATA', 'BITS'):
3bd76451
UH
191 return
192
ad30cb46
UH
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
3bd76451
UH
198
199 self.ss, self.es = ss, es
200
011ed1a3 201 if len(self.mosi_bytes) == 0:
486b19ce 202 self.ss_cmd = ss
011ed1a3 203
3bd76451
UH
204 # Append new bytes.
205 self.mosi_bytes.append(mosi)
206 self.miso_bytes.append(miso)
207
3bd76451
UH
208 # All commands consist of 4 bytes.
209 if len(self.mosi_bytes) < 4:
210 return
211
486b19ce 212 self.es_cmd = es
3bd76451
UH
213
214 self.handle_command(self.mosi_bytes, self.miso_bytes)
215
216 self.mosi_bytes = []
217 self.miso_bytes = []