}
def cmd_annotation_classes():
- return [[cmd[0].lower(), cmd[1]] for cmd in cmds.values()]
+ return tuple([tuple([cmd[0].lower(), cmd[1]]) for cmd in cmds.values()])
def decode_status_reg(data):
# TODO: Additional per-bit(s) self.put() calls with correct start/end.
return ret
class Decoder(srd.Decoder):
- api_version = 1
+ api_version = 2
id = 'mx25lxx05d'
name = 'MX25Lxx05D'
longname = 'Macronix MX25Lxx05D'
desc = 'SPI (NOR) flash chip protocol.'
license = 'gplv2+'
- inputs = ['spi', 'logic']
+ inputs = ['logic']
outputs = ['mx25lxx05d']
- probes = []
- optional_probes = [
- {'id': 'hold', 'name': 'HOLD#', 'desc': 'Pause device w/o deselecting it'},
- {'id': 'wp_acc', 'name': 'WP#/ACC', 'desc': 'Write protect'},
- ]
- options = {}
- annotations = cmd_annotation_classes() + [
- ['bits', 'Bits'],
- ['bits2', 'Bits2'],
- ['warnings', 'Warnings'],
- ]
+ annotations = cmd_annotation_classes() + (
+ ('bits', 'Bits'),
+ ('bits2', 'Bits2'),
+ ('warnings', 'Warnings'),
+ )
annotation_rows = (
('bits', 'Bits', (24, 25)),
('commands', 'Commands', tuple(range(23 + 1))),
self.data = []
def start(self):
- # self.out_python = self.register(srd.OUTPUT_PYTHON)
self.out_ann = self.register(srd.OUTPUT_ANN)
def putx(self, data):
# Simplification, most annotations span exactly one SPI byte/packet.
self.put(self.ss, self.es, self.out_ann, data)
+ def putb(self, data):
+ self.put(self.block_ss, self.block_es, self.out_ann, data)
+
def handle_wren(self, mosi, miso):
self.putx([0, ['Command: %s' % cmds[self.state][1]]])
self.state = None
def handle_rdid(self, mosi, miso):
if self.cmdstate == 1:
# Byte 1: Master sends command ID.
- self.start_sample = self.ss
+ self.ss_block = self.ss
self.putx([2, ['Command: %s' % cmds[self.state][1]]])
elif self.cmdstate == 2:
# Byte 2: Slave sends the JEDEC manufacturer ID.
# TODO: Check self.device_id is valid & exists in device_names.
# TODO: Same device ID? Check!
d = 'Device: Macronix %s' % device_name[self.device_id]
- self.put(self.start_sample, self.es, self.out_ann, [0, [d]])
+ self.put(self.ss_block, self.es, self.out_ann, [0, [d]])
self.state = None
else:
self.cmdstate += 1
self.cmdstate += 1
def handle_fast_read(self, mosi, miso):
- pass # TODO
+ # Fast read: Master asserts CS#, sends FAST READ command, sends
+ # 3-byte address + 1 dummy byte, reads >= 1 data bytes, de-asserts CS#.
+ if self.cmdstate == 1:
+ # Byte 1: Master sends command ID.
+ self.putx([5, ['Command: %s' % cmds[self.state][1]]])
+ elif self.cmdstate in (2, 3, 4):
+ # Bytes 2/3/4: Master sends read address (24bits, MSB-first).
+ self.putx([24, ['AD%d: 0x%02x' % (self.cmdstate - 1, mosi)]])
+ if self.cmdstate == 2:
+ self.block_ss = self.ss
+ self.addr |= (mosi << ((4 - self.cmdstate) * 8))
+ elif self.cmdstate == 5:
+ self.putx([24, ['Dummy byte: 0x%02x' % mosi]])
+ self.block_es = self.es
+ self.putb([5, ['Read address: 0x%06x' % self.addr]])
+ self.addr = 0
+ elif self.cmdstate >= 6:
+ # Bytes 6-x: Master reads data bytes (until CS# de-asserted).
+ # TODO: For now we hardcode 32 bytes per FAST READ command.
+ if self.cmdstate == 6:
+ self.block_ss = self.ss
+ if self.cmdstate <= 32 + 5: # TODO: While CS# asserted.
+ self.data.append(miso)
+ if self.cmdstate == 32 + 5: # TODO: If CS# got de-asserted.
+ self.block_es = self.es
+ s = ' '.join([hex(b)[2:] for b in self.data])
+ self.putb([25, ['Read data: %s' % s]])
+ self.data = []
+ self.state = None
+ return
+
+ self.cmdstate += 1
def handle_2read(self, mosi, miso):
pass # TODO
if self.cmdstate == 1:
# Byte 1: Master sends command ID.
self.addr = 0
- self.start_sample = self.ss
+ self.ss_block = self.ss
self.putx([8, ['Command: %s' % cmds[self.state][1]]])
elif self.cmdstate in (2, 3, 4):
- # Bytes 2/3/4: Master sends sectror address (24bits, MSB-first).
+ # Bytes 2/3/4: Master sends sector address (24bits, MSB-first).
self.addr |= (mosi << ((4 - self.cmdstate) * 8))
# self.putx([0, ['Sector address, byte %d: 0x%02x' % \
# (4 - self.cmdstate, mosi)]])
if self.cmdstate == 4:
d = 'Erase sector %d (0x%06x)' % (self.addr, self.addr)
- self.put(self.start_sample, self.es, self.out_ann, [24, [d]])
+ self.put(self.ss_block, self.es, self.out_ann, [24, [d]])
# TODO: Max. size depends on chip, check that too if possible.
if self.addr % 4096 != 0:
# Sector addresses must be 4K-aligned (same for all 3 chips).
d = 'Warning: Invalid sector address!'
- self.put(self.start_sample, self.es, self.out_ann, [101, [d]])
+ self.put(self.ss_block, self.es, self.out_ann, [101, [d]])
self.state = None
else:
self.cmdstate += 1
def handle_rems(self, mosi, miso):
if self.cmdstate == 1:
# Byte 1: Master sends command ID.
- self.start_sample = self.ss
+ self.ss_block = self.ss
self.putx([16, ['Command: %s' % cmds[self.state][1]]])
elif self.cmdstate in (2, 3):
# Bytes 2/3: Master sends two dummy bytes.
self.putx([24, ['%s ID' % d]])
if self.cmdstate == 6:
- self.end_sample = self.es
id = self.ids[1] if self.manufacturer_id_first else self.ids[0]
self.putx([24, ['Device: Macronix %s' % device_name[id]]])
self.state = None
self.ss, self.es = ss, es
# If we encountered a known chip command, enter the resp. state.
- if self.state == None:
+ if self.state is None:
self.state = mosi
self.cmdstate = 1
else:
self.putx([24, ['Unknown command: 0x%02x' % mosi]])
self.state = None
-