]> sigrok.org Git - libsigrokdecode.git/blame - decoders/avr_isp/pd.py
decoders: Add/update tags for each PD.
[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
UH
22
23VENDOR_CODE_ATMEL = 0x1e
24
25class Decoder(srd.Decoder):
b197383c 26 api_version = 3
3bd76451
UH
27 id = 'avr_isp'
28 name = 'AVR ISP'
d523eae6 29 longname = 'AVR In-System Programming'
3bd76451
UH
30 desc = 'Protocol for in-system programming Atmel AVR MCUs.'
31 license = 'gplv2+'
4e4f8527 32 inputs = ['spi']
3bd76451 33 outputs = ['avr_isp']
d6d8a8a4 34 tags = ['Debug/trace']
da9bcbd9
BV
35 annotations = (
36 ('pe', 'Programming enable'),
37 ('rsb0', 'Read signature byte 0'),
38 ('rsb1', 'Read signature byte 1'),
39 ('rsb2', 'Read signature byte 2'),
40 ('ce', 'Chip erase'),
41 ('rfb', 'Read fuse bits'),
42 ('rhfb', 'Read high fuse bits'),
43 ('refb', 'Read extended fuse bits'),
44 ('warnings', 'Warnings'),
45 ('dev', 'Device'),
46 )
3b001341
UH
47 annotation_rows = (
48 ('bits', 'Bits', ()),
49 ('commands', 'Commands', tuple(range(7 + 1))),
50 ('warnings', 'Warnings', (8,)),
38ab4ed0 51 ('dev', 'Device', (9,)),
3b001341 52 )
3bd76451 53
92b7b49f 54 def __init__(self):
10aeb8ea
GS
55 self.reset()
56
57 def reset(self):
3bd76451
UH
58 self.state = 'IDLE'
59 self.mosi_bytes, self.miso_bytes = [], []
486b19ce 60 self.ss_cmd, self.es_cmd = 0, 0
3bd76451 61 self.xx, self.yy, self.zz, self.mm = 0, 0, 0, 0
486b19ce 62 self.ss_device = None
3bd76451 63
8915b346 64 def start(self):
be465111 65 self.out_ann = self.register(srd.OUTPUT_ANN)
3bd76451 66
3bd76451 67 def putx(self, data):
486b19ce 68 self.put(self.ss_cmd, self.es_cmd, self.out_ann, data)
3bd76451
UH
69
70 def handle_cmd_programming_enable(self, cmd, ret):
71 # Programming enable.
72 # Note: The chip doesn't send any ACK for 'Programming enable'.
73 self.putx([0, ['Programming enable']])
74
75 # Sanity check on reply.
76 if ret[1:4] != [0xac, 0x53, cmd[2]]:
ad30cb46 77 self.putx([8, ['Warning: Unexpected bytes in reply!']])
3bd76451
UH
78
79 def handle_cmd_read_signature_byte_0x00(self, cmd, ret):
80 # Signature byte 0x00: vendor code.
81 self.vendor_code = ret[3]
82 v = vendor_code[self.vendor_code]
ad30cb46 83 self.putx([1, ['Vendor code: 0x%02x (%s)' % (ret[3], v)]])
3bd76451
UH
84
85 # Store for later.
86 self.xx = cmd[1] # Same as ret[2].
87 self.yy = cmd[3]
88 self.zz = ret[0]
89
90 # Sanity check on reply.
91 if ret[1] != 0x30 or ret[2] != cmd[1]:
ad30cb46 92 self.putx([8, ['Warning: Unexpected bytes in reply!']])
3bd76451
UH
93
94 # Sanity check for the vendor code.
95 if self.vendor_code != VENDOR_CODE_ATMEL:
ad30cb46 96 self.putx([8, ['Warning: Vendor code was not 0x1e (Atmel)!']])
3bd76451
UH
97
98 def handle_cmd_read_signature_byte_0x01(self, cmd, ret):
99 # Signature byte 0x01: part family and memory size.
100 self.part_fam_flash_size = ret[3]
ad30cb46 101 self.putx([2, ['Part family / memory size: 0x%02x' % ret[3]]])
3bd76451
UH
102
103 # Store for later.
104 self.mm = cmd[3]
486b19ce 105 self.ss_device = self.ss_cmd
3bd76451
UH
106
107 # Sanity check on reply.
108 if ret[1] != 0x30 or ret[2] != cmd[1] or ret[0] != self.yy:
ad30cb46 109 self.putx([8, ['Warning: Unexpected bytes in reply!']])
3bd76451
UH
110
111 def handle_cmd_read_signature_byte_0x02(self, cmd, ret):
112 # Signature byte 0x02: part number.
113 self.part_number = ret[3]
ad30cb46 114 self.putx([3, ['Part number: 0x%02x' % ret[3]]])
3bd76451 115
3bd76451 116 p = part[(self.part_fam_flash_size, self.part_number)]
38ab4ed0 117 data = [9, ['Device: Atmel %s' % p]]
486b19ce 118 self.put(self.ss_device, self.es_cmd, self.out_ann, data)
3bd76451
UH
119
120 # Sanity check on reply.
121 if ret[1] != 0x30 or ret[2] != self.xx or ret[0] != self.mm:
ad30cb46 122 self.putx([8, ['Warning: Unexpected bytes in reply!']])
3bd76451
UH
123
124 self.xx, self.yy, self.zz, self.mm = 0, 0, 0, 0
125
126 def handle_cmd_chip_erase(self, cmd, ret):
1fd698dc
UH
127 # Chip erase (erases both flash an EEPROM).
128 # Upon successful chip erase, the lock bits will also be erased.
129 # The only way to end a Chip Erase cycle is to release RESET#.
ad30cb46 130 self.putx([4, ['Chip erase']])
3bd76451 131
1fd698dc
UH
132 # TODO: Check/handle RESET#.
133
134 # Sanity check on reply.
135 bit = (ret[2] & (1 << 7)) >> 7
136 if ret[1] != 0xac or bit != 1 or ret[3] != cmd[2]:
ad30cb46 137 self.putx([8, ['Warning: Unexpected bytes in reply!']])
1fd698dc 138
3bd76451
UH
139 def handle_cmd_read_fuse_bits(self, cmd, ret):
140 # Read fuse bits.
ad30cb46 141 self.putx([5, ['Read fuse bits: 0x%02x' % ret[3]]])
3bd76451
UH
142
143 # TODO: Decode fuse bits.
144 # TODO: Sanity check on reply.
145
146 def handle_cmd_read_fuse_high_bits(self, cmd, ret):
147 # Read fuse high bits.
ad30cb46 148 self.putx([6, ['Read fuse high bits: 0x%02x' % ret[3]]])
3bd76451
UH
149
150 # TODO: Decode fuse bits.
151 # TODO: Sanity check on reply.
152
153 def handle_cmd_read_extended_fuse_bits(self, cmd, ret):
154 # Read extended fuse bits.
ad30cb46 155 self.putx([7, ['Read extended fuse bits: 0x%02x' % ret[3]]])
3bd76451
UH
156
157 # TODO: Decode fuse bits.
158 # TODO: Sanity check on reply.
159
160 def handle_command(self, cmd, ret):
161 if cmd[:2] == [0xac, 0x53]:
162 self.handle_cmd_programming_enable(cmd, ret)
163 elif cmd[0] == 0xac and (cmd[1] & (1 << 7)) == (1 << 7):
164 self.handle_cmd_chip_erase(cmd, ret)
165 elif cmd[:3] == [0x50, 0x00, 0x00]:
166 self.handle_cmd_read_fuse_bits(cmd, ret)
167 elif cmd[:3] == [0x58, 0x08, 0x00]:
168 self.handle_cmd_read_fuse_high_bits(cmd, ret)
169 elif cmd[:3] == [0x50, 0x08, 0x00]:
170 self.handle_cmd_read_extended_fuse_bits(cmd, ret)
171 elif cmd[0] == 0x30 and cmd[2] == 0x00:
172 self.handle_cmd_read_signature_byte_0x00(cmd, ret)
173 elif cmd[0] == 0x30 and cmd[2] == 0x01:
174 self.handle_cmd_read_signature_byte_0x01(cmd, ret)
175 elif cmd[0] == 0x30 and cmd[2] == 0x02:
176 self.handle_cmd_read_signature_byte_0x02(cmd, ret)
177 else:
178 c = '%02x %02x %02x %02x' % tuple(cmd)
179 r = '%02x %02x %02x %02x' % tuple(ret)
180 self.putx([0, ['Unknown command: %s (reply: %s)!' % (c, r)]])
181
182 def decode(self, ss, es, data):
183 ptype, mosi, miso = data
184
ad30cb46
UH
185 # For now, only use DATA and BITS packets.
186 if ptype not in ('DATA', 'BITS'):
3bd76451
UH
187 return
188
ad30cb46
UH
189 # Store the individual bit values and ss/es numbers. The next packet
190 # is guaranteed to be a 'DATA' packet belonging to this 'BITS' one.
191 if ptype == 'BITS':
192 self.miso_bits, self.mosi_bits = miso, mosi
193 return
3bd76451
UH
194
195 self.ss, self.es = ss, es
196
011ed1a3 197 if len(self.mosi_bytes) == 0:
486b19ce 198 self.ss_cmd = ss
011ed1a3 199
3bd76451
UH
200 # Append new bytes.
201 self.mosi_bytes.append(mosi)
202 self.miso_bytes.append(miso)
203
3bd76451
UH
204 # All commands consist of 4 bytes.
205 if len(self.mosi_bytes) < 4:
206 return
207
486b19ce 208 self.es_cmd = es
3bd76451
UH
209
210 self.handle_command(self.mosi_bytes, self.miso_bytes)
211
212 self.mosi_bytes = []
213 self.miso_bytes = []