From 80ff66e04d8c0f924f9645965c4c5acbd14a364d Mon Sep 17 00:00:00 2001 From: Morten Danmark Nielsen Date: Thu, 23 May 2024 13:22:33 +0200 Subject: [PATCH] Reformat hs3program --- .gitignore | 4 +- digilent_hs3/hs3program/avr32.py | 83 +++++---- digilent_hs3/hs3program/avr32_prog.py | 81 ++++++--- digilent_hs3/hs3program/avr32jtag.py | 73 ++++---- digilent_hs3/hs3program/ftdi_jtag_adapter.py | 175 +++++++++++-------- digilent_hs3/hs3program/jtag_adapter.py | 139 ++++++++------- digilent_hs3/setup.py | 18 +- 7 files changed, 322 insertions(+), 251 deletions(-) diff --git a/.gitignore b/.gitignore index 393ebfb..78a8d92 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ *.pdf *.egg-info build -.vscode \ No newline at end of file +.vscode +venv +*.elf diff --git a/digilent_hs3/hs3program/avr32.py b/digilent_hs3/hs3program/avr32.py index 50d17df..07456e4 100644 --- a/digilent_hs3/hs3program/avr32.py +++ b/digilent_hs3/hs3program/avr32.py @@ -72,17 +72,17 @@ def _WaitFlashReady(self): fsrReg = self._GetRegister(self.FSR) # If LOCKE bit in FSR set if (fsrReg & FSR_LOCKE_MASK) >> FSR_LOCKE_OFFSET: - raise Exception( - "Programming of at least one locked lock region has happend since the last read of FSR") + raise RuntimeError( + "Programming of at least one locked lock region has happend since the last read of FSR" + ) # If PROGE bit in FSR set if (fsrReg & FSR_PROGE_MASK) >> FSR_PROGE_OFFSET: - raise Exception( - "An invalid command and/or bad keywords were written in the Flash Command Register") + raise RuntimeError("An invalid command and/or bad keywords were written in the Flash Command Register") # Read FRDY bit in FSR if (fsrReg & FSR_FRDY_MASK) >> FSR_FRDY_OFFSET: return # FLASH ready for next operation - - raise Exception("Timeout while waiting for flash controller to be ready") + + raise RuntimeError("Timeout while waiting for flash controller to be ready") def _ClearPageBuffer(self): command = WRITE_PROTECT_KEY | CMD_CLEAR_PAGE_BUFFER @@ -94,6 +94,7 @@ def _ClearPageBuffer(self): def DeviceSize(self) -> int: if not self._device_size: self._GetInternalFlashSize() + assert self._device_size is not None return self._device_size @property @@ -104,6 +105,7 @@ def FlashBase(self) -> int: def PageSize(self) -> int: if not self._page_size: self._GetInternalFlashSize() + assert self._page_size is not None return self._page_size def _GetInternalFlashSize(self): @@ -146,23 +148,22 @@ def _GetInternalFlashSize(self): elif fsz == 14: size = 2048 * 1024 else: - raise Exception("Unknown flash size") + raise RuntimeError("Unknown flash size") self._device_size = size def UnlockRegion(self, offset, size): if (offset >= USER_PAGE_OFFSET) and (offset < USER_PAGE_OFFSET + self.PageSize): return # the user page doesn't need unlocking - if (offset >= self.DeviceSize) or (offset+size > self.DeviceSize): - raise Exception( - "Region to be unlock lies outside flash address space") - lastpagetounlock = (offset+size) // self.PageSize + if (offset >= self.DeviceSize) or (offset + size > self.DeviceSize): + raise RuntimeError("Region to be unlock lies outside flash address space") + lastpagetounlock = (offset + size) // self.PageSize # compute start offset of page to write to page = offset & ~(self.PageSize - 1) pagenr = offset // self.PageSize while pagenr <= lastpagetounlock: command = WRITE_PROTECT_KEY | CMD_UNLOCK_REGION # include the correct page number in the command - command |= ((pagenr << FCMD_PAGEN_OFFSET) & FCMD_PAGEN_MASK) + command |= (pagenr << FCMD_PAGEN_OFFSET) & FCMD_PAGEN_MASK # Unlocking page: pagenr self._WaitFlashReady() self._WriteCommand(command) # execute unlock page command @@ -190,13 +191,13 @@ def EraseRegionSequence(self, offset, size): if (offset >= USER_PAGE_OFFSET) and (offset < USER_PAGE_OFFSET + self.PageSize): self.EraseUserPage() - lastpagetoerase = (offset+size) // self.PageSize + lastpagetoerase = (offset + size) // self.PageSize # compute start offset of page to write to page = offset & ~(self.PageSize - 1) pagenr = offset // self.PageSize - while (pagenr <= lastpagetoerase): + while pagenr <= lastpagetoerase: Command = WRITE_PROTECT_KEY | CMD_ERASE_PAGE - Command |= ((pagenr << FCMD_PAGEN_OFFSET) & FCMD_PAGEN_MASK) + Command |= (pagenr << FCMD_PAGEN_OFFSET) & FCMD_PAGEN_MASK # include the correct page number in the command self._WaitFlashReady() self._WriteCommand(Command) # execute page erase command @@ -208,24 +209,30 @@ def EraseRegionSequence(self, offset, size): def SetGPFuseByte(self, index, value): if index > 3 or index < 0: - raise Exception("Invalid fuse byte") - - command = WRITE_PROTECT_KEY | CMD_PROGRAM_GP_FUSE_BYTE | (index << FCMD_PAGEN_OFFSET) | ((value & 0xFF) << (FCMD_PAGEN_OFFSET+3)) + raise RuntimeError("Invalid fuse byte") + + command = ( + WRITE_PROTECT_KEY + | CMD_PROGRAM_GP_FUSE_BYTE + | (index << FCMD_PAGEN_OFFSET) + | ((value & 0xFF) << (FCMD_PAGEN_OFFSET + 3)) + ) self._WaitFlashReady() self._WriteCommand(command) self._WaitFlashReady() - def WriteFuses(self, fuses: int): + def WriteFuses(self, fuses: int) -> None: """Assumes fuses are 32 bits""" for i in range(4): - self.SetGPFuseByte(i, (fuses >> (8*i)) & 0xFF) + self.SetGPFuseByte(i, (fuses >> (8 * i)) & 0xFF) - def _ProgramPage(self, address: int, cmd: int, offset: int, data: bytes): + def _ProgramPage(self, address: int, cmd: int, offset: int, data: bytes) -> None: bufferPacket = data - if (offset > 0) or (offset+len(data) < self.PageSize): - bufferPacket = self._ReadBlockWords(address, self.PageSize // 4) - bufferPacket[offset:offset+len(data)] = data + if (offset > 0) or (offset + len(data) < self.PageSize): + bufferPacketArray = bytearray(self._ReadBlockWords(address, self.PageSize // 4)) + bufferPacketArray[offset : offset + len(data)] = data + bufferPacket = bufferPacketArray self._ClearPageBuffer() self._WriteBlockWords(address, bufferPacket) @@ -235,16 +242,22 @@ def _ProgramPage(self, address: int, cmd: int, offset: int, data: bytes): self._WriteCommand(command) self._WaitFlashReady() - def ProgramUserPage(self, page_offset: int, DataBuffer: bytes): + def ProgramUserPage(self, page_offset: int, DataBuffer: bytes) -> None: self._ProgramPage(self.FlashBase + USER_PAGE_OFFSET, CMD_WRITE_USER_PAGE, page_offset, DataBuffer) - def ProgramSequence(self, address: int, data_buffer: bytes, progress_callback: typing.Callable[[int, int], None]): - if (address >= self.FlashBase + USER_PAGE_OFFSET) and (self.FlashBase + address < USER_PAGE_OFFSET + self.PageSize): + def ProgramSequence( + self, address: int, data_buffer: bytes, progress_callback: typing.Callable[[int, int], None] + ) -> None: + if (address >= self.FlashBase + USER_PAGE_OFFSET) and ( + self.FlashBase + address < USER_PAGE_OFFSET + self.PageSize + ): self.ProgramUserPage(address - (self.FlashBase + USER_PAGE_OFFSET), data_buffer) return - if (address >= self.FlashBase + self.DeviceSize) or (address+len(data_buffer) > self.FlashBase + self.DeviceSize): - raise Exception("Region to be programmed lies outside flash address space") + if (address >= self.FlashBase + self.DeviceSize) or ( + address + len(data_buffer) > self.FlashBase + self.DeviceSize + ): + raise RuntimeError("Region to be programmed lies outside flash address space") page_number = (address - self.FlashBase) // self.PageSize first_page = page_number @@ -259,10 +272,14 @@ def ProgramSequence(self, address: int, data_buffer: bytes, progress_callback: t # Write bytes command = CMD_WRITE_PAGE command |= page_number << FCMD_PAGEN_OFFSET - self._ProgramPage(page_number * self.PageSize + self.FlashBase, command, address % self.PageSize, data_buffer[index:index + bytes_in_page]) + self._ProgramPage( + page_number * self.PageSize + self.FlashBase, + command, + address % self.PageSize, + data_buffer[index : index + bytes_in_page], + ) - if progress_callback: - progress_callback(page_number - first_page, last_page - first_page) + progress_callback(page_number - first_page, last_page - first_page) address = 0 page_number += 1 @@ -276,4 +293,4 @@ def ReadMemory(self, address: int, size: int) -> bytes: data_offset = address - aligned_address data = self._ReadBlockWords(aligned_address, (aligned_end - aligned_address) // 4) - return data[data_offset:data_offset+size] + return data[data_offset : data_offset + size] diff --git a/digilent_hs3/hs3program/avr32_prog.py b/digilent_hs3/hs3program/avr32_prog.py index 68beb7a..1064185 100755 --- a/digilent_hs3/hs3program/avr32_prog.py +++ b/digilent_hs3/hs3program/avr32_prog.py @@ -1,37 +1,46 @@ -#!/bin/env python3 +#!/usr/bin/env python3 # Copyright (C) 2012-2022 Jeppe Johansen import argparse import logging import sys import time -from elftools.elf.elffile import ELFFile -from hs3program.avr32 import AVR32, FLASH_BASE +from elftools.elf.elffile import ELFFile +from hs3program.avr32 import AVR32 from hs3program.ftdi_jtag_adapter import FTDIJtagAdapter from hs3program.jtag_adapter import JtagAdapter ADAPTERS = { - "busblaster_v25": lambda frequency: FTDIJtagAdapter(0x0403, 0x6010, 0x0000, 0x0010, frequency=frequency, nSRST=(0x0200, 0x0800), nTRST=(0x0100, 0x0400)), - "digilent_hs3": lambda frequency: FTDIJtagAdapter(0x0403, 0x6014, 0x0080, 0x0080, frequency=frequency, nSRST=(0x2000, 0x1000)), - "openmoko_dbv3": lambda frequency: FTDIJtagAdapter(0x1457, 0x5118, 0x0000, 0x0010, frequency=frequency, nSRST=(0x0800, 0x0400), nTRST=(0x0200, 0x0100)), + "busblaster_v25": lambda frequency: FTDIJtagAdapter( + 0x0403, 0x6010, 0x0000, 0x0010, frequency=frequency, nSRST=(0x0200, 0x0800), nTRST=(0x0100, 0x0400) + ), + "digilent_hs3": lambda frequency: FTDIJtagAdapter( + 0x0403, 0x6014, 0x0080, 0x0080, frequency=frequency, nSRST=(0x2000, 0x1000) + ), + "openmoko_dbv3": lambda frequency: FTDIJtagAdapter( + 0x1457, 0x5118, 0x0000, 0x0010, frequency=frequency, nSRST=(0x0800, 0x0400), nTRST=(0x0200, 0x0100) + ), } + def get_adapter(config, frequency) -> JtagAdapter: if config in ADAPTERS: return ADAPTERS[config](frequency) raise Exception("Unknown adapter: " + config) -def program_segment(dev: AVR32, address: int, mem_size: int, data: bytes, do_erase: bool, verify: bool): +def program_segment(dev: AVR32, address: int, mem_size: int, data: bytes, do_erase: bool, verify: bool) -> None: assert not do_erase, "No segment erase support yet" assert mem_size == len(data), "Data should be as long as memory segment" def progress(current, total): if sys.stdout.isatty(): - sys.stdout.write("\r [%d%%] Wrote page %d out of %d" % (int(100*(current+1)/total), current + 1, total)) + sys.stdout.write( + "\r [%d%%] Wrote page %d out of %d" % (int(100 * (current + 1) / total), current + 1, total) + ) sys.stdout.flush() else: - print(" [%d%%] Wrote page %d out of %d" % (int(100*(current+1)/total), current + 1, total)) + print(" [%d%%] Wrote page %d out of %d" % (int(100 * (current + 1) / total), current + 1, total)) try: dev.ProgramSequence(address, data, progress) @@ -42,7 +51,7 @@ def progress(current, total): sys.stdout.flush() else: print(" Verifying...") - + readback = dev.ReadMemory(address, len(data)) error_offset = -1 @@ -51,7 +60,10 @@ def progress(current, total): error_offset = i break if error_offset >= 0: - raise Exception("Verification failed. Difference in read data at address: %d. Expected %02x, but read %02x." % (address+error_offset, data[error_offset], readback[error_offset])) + raise RuntimeError( + "Verification failed. Difference in read data at address: %d. Expected %02x, but read %02x." + % (address + error_offset, data[error_offset], readback[error_offset]) + ) finally: if sys.stdout.isatty(): sys.stdout.write("\n") @@ -64,9 +76,9 @@ def program(programmer, flash=None, no_verify=False, chip_erase=True, detect=Fal adapter.SetSignal("TCK", False) # Do the AVR32 reset sequence - adapter.SRST('0') + adapter.SRST("0") time.sleep(0.1) - adapter.SRST('z') + adapter.SRST("z") if detect: adapter.DetectDevices() @@ -82,7 +94,7 @@ def program(programmer, flash=None, no_verify=False, chip_erase=True, detect=Fal if dump: print("Dumping flash contents") with open(dump, "wb") as f: - f.write(dev._ReadBlockWords(dev.FlashBase, dev.DeviceSize // 4)) + f.write(dev._ReadBlockWords(dev.FlashBase, dev.DeviceSize // 4)) # pylint: disable=protected-access if chip_erase: print("Performing chip erase") @@ -98,8 +110,12 @@ def program(programmer, flash=None, no_verify=False, chip_erase=True, detect=Fal elf = ELFFile(file) for seg in elf.iter_segments("PT_LOAD"): - print(" Writing segment. Address: %8x Size: %x" % (seg.header["p_paddr"], seg.header["p_memsz"])) - program_segment(dev, seg.header["p_paddr"], seg.header["p_memsz"], seg.data(), not chip_erase, not no_verify) + print( + " Writing segment. Address: %8x Size: %x" % (seg.header["p_paddr"], seg.header["p_memsz"]) + ) + program_segment( + dev, seg.header["p_paddr"], seg.header["p_memsz"], seg.data(), not chip_erase, not no_verify + ) if fuses: print("Writing fuses") @@ -109,9 +125,9 @@ def program(programmer, flash=None, no_verify=False, chip_erase=True, detect=Fal print("Resetting...") adapter.SetSignal("TCK", True) - adapter.SRST('0') + adapter.SRST("0") time.sleep(0.1) - adapter.SRST('z') + adapter.SRST("z") adapter.SetSignal("TCK", False) finally: @@ -120,29 +136,44 @@ def program(programmer, flash=None, no_verify=False, chip_erase=True, detect=Fal def main(): parser = argparse.ArgumentParser() - parser.add_argument("--programmer", "-p", default="digilent_hs3", type=str, choices=ADAPTERS.keys(), help="Which JTAG adapter to use") + parser.add_argument( + "--programmer", + "-p", + default="digilent_hs3", + type=str, + choices=ADAPTERS.keys(), + help="Which JTAG adapter to use", + ) parser.add_argument("--chip_erase", "-E", action="store_true", help="Perform full chip erase.") parser.add_argument("--reset", "-R", action="store_true", help="Perform chip reset after programming.") - parser.add_argument("--dump", "-D", metavar="filename", default=None, type=str, help="Read the current FLASH contents (if not protected) out into a binary file.") + parser.add_argument( + "--dump", + "-D", + metavar="filename", + default=None, + type=str, + help="Read the current FLASH contents (if not protected) out into a binary file.", + ) parser.add_argument("--detect", "-d", action="store_true", help="Do detection of devices on JTAG bus") parser.add_argument("--flash", "-f", default=None, type=str, help="Path to ELF file to be programmed") parser.add_argument("--no-verify", "-V", action="store_true", help="Skip verifying flash") parser.add_argument("--fuses", "-GP", default=None, type=str, help="Program fuses") - parser.add_argument("--verbose", "-v",action="store_true", help="Verbose log output") + parser.add_argument("--verbose", "-v", action="store_true", help="Verbose log output") args = parser.parse_args() level = logging.DEBUG if args.verbose else logging.INFO del args.verbose logging.basicConfig( - filename='log_file_name.log', + filename="hs3program.log", level=level, - format= '[%(asctime)s] %(name)s %(levelname)s - %(message)s', - datefmt='%H:%M:%S' + format="[%(asctime)s] %(name)s %(levelname)s - %(message)s", + datefmt="%H:%M:%S", ) logging.root.setLevel(level) program(**vars(args)) + if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/digilent_hs3/hs3program/avr32jtag.py b/digilent_hs3/hs3program/avr32jtag.py index 73ff616..41c1313 100644 --- a/digilent_hs3/hs3program/avr32jtag.py +++ b/digilent_hs3/hs3program/avr32jtag.py @@ -2,7 +2,8 @@ import logging import struct -from hs3program.jtag_adapter import JtagAdapter, JtagState +from hs3program.jtag_adapter import JtagAdapter +from hs3program.jtag_adapter import JtagState # JTAG instructions IDCODE = 0x01 @@ -40,6 +41,7 @@ 0x200B03F: "AT32UC3C264C", } + class AVR32Jtag: def __init__(self, adapter: JtagAdapter): self._tap = adapter @@ -56,17 +58,16 @@ def __init__(self, adapter: JtagAdapter): self.model = self._idcode & 0x0FFFFFFF self.revision = (self._idcode >> 28) & 0xF - chip = IDCODES.get(self.model, 'Unknown') + chip = IDCODES.get(self.model, "Unknown") print(f"Detected ID code: {self._idcode:8X} = {chip}") if chip == "Unknown": - raise Exception("Could not detect chip type") - + raise RuntimeError("Could not detect chip type") + def ChipErase(self): while True: - ret = self._tap.IR(CHIP_ERASE, - IRLENGTH, JtagState.UpdateIR) + ret = self._tap.IR(CHIP_ERASE, IRLENGTH, JtagState.UpdateIR) self.log.debug(f" IP: {ret:2X}") if ret & 0x4: self.log.debug("Busy") @@ -74,23 +75,22 @@ def ChipErase(self): if ret & 0x8: self.log.warning("Last operation failed") if ret & 0x10: - raise Exception("Chip is protected") + raise RuntimeError("Chip is protected") break self._tap.SetState(JtagState.Idle) - def Reset(self, reset_bit: int): + def Reset(self, reset_bit: int) -> None: ret = self._tap.IR(AVR_RESET, IRLENGTH) self.log.debug(f" IP: {ret:2X}") if ret & 0x10: - raise Exception("Chip is protected") - + raise RuntimeError("Chip is protected") + ret = self._tap.DR(reset_bit, 1) self.log.debug(f" DP: {ret:2X}") def _ReadMemoryWord(self, address): while True: - ret = self._tap.IR(MEMORY_WORD_ACCESS, - IRLENGTH, JtagState.UpdateIR) + ret = self._tap.IR(MEMORY_WORD_ACCESS, IRLENGTH, JtagState.UpdateIR) self.log.debug(f" IP: {ret:2X}") if ret & 0x4: self.log.debug("Busy") @@ -98,7 +98,7 @@ def _ReadMemoryWord(self, address): if ret & 0x8: self.log.warning("Last operation failed") if ret & 0x10: - raise Exception("Chip is protected") + raise RuntimeError("Chip is protected") break # Address phase @@ -121,14 +121,13 @@ def _ReadMemoryWord(self, address): self.log.debug("Busy") continue if (ret >> 32) & 2: - raise Exception("Error while accessing memory") + raise RuntimeError("Error while accessing memory") self._tap.SetState(JtagState.Idle) return ret & 0xFFFFFFFF def _WriteMemoryWord(self, address, value): while True: - ret = self._tap.IR(MEMORY_WORD_ACCESS, - IRLENGTH, JtagState.UpdateIR) + ret = self._tap.IR(MEMORY_WORD_ACCESS, IRLENGTH, JtagState.UpdateIR) self.log.debug(f" IP: {ret:2X}") if ret & 0x4: self.log.debug("Busy") @@ -136,11 +135,11 @@ def _WriteMemoryWord(self, address, value): if ret & 0x8: self.log.warning("Last operation failed") if ret & 0x10: - raise Exception("Chip is protected") + raise RuntimeError("Chip is protected") break # Address phase - dr = (((SLV_HSB << 30) | ((address & 0xFFFFFFFF) >> 2)) << 1) + dr = ((SLV_HSB << 30) | ((address & 0xFFFFFFFF) >> 2)) << 1 while True: ret = self._tap.DR(dr, 35, JtagState.UpdateDR) self.log.debug(f" AP: {ret:9X}") @@ -160,7 +159,7 @@ def _WriteMemoryWord(self, address, value): self.log.debug("Busy") continue if ret & 2: - raise Exception("Error while accessing memory") + raise RuntimeError("Error while accessing memory") self._tap.SetState(JtagState.Idle) break @@ -170,7 +169,7 @@ def _ReadBlockWords(self, address: int, word_count: int) -> bytes: # for i in range(0, word_count * 4, 4): # res = self._ReadMemoryWord(address + i) # struct.pack_into(">L", result, i, res & 0xFFFFFFFF) - + # return result res = self._ReadMemoryWord(address) @@ -184,9 +183,9 @@ def _ReadBlockWords(self, address: int, word_count: int) -> bytes: self.log.debug("Busy") continue if ret & 0x8: - raise Exception("MEMORY_WORD_ACCESS operation failed") + raise RuntimeError("MEMORY_WORD_ACCESS operation failed") if ret & 0x10: - raise Exception("Chip is protected") + raise RuntimeError("Chip is protected") break word = 1 @@ -198,23 +197,23 @@ def _ReadBlockWords(self, address: int, word_count: int) -> bytes: for _ in range(left): self._tap.SetState(JtagState.SelectDR) self._tap.SetState(JtagState.ShiftDR) - ret = self._tap.ScheduleDRIn(5) + self._tap.ScheduleDRIn(5) res = self._tap.ReadScheduled(total) for idx in range(0, total, 5): - ret = res[idx+4] + ret = res[idx + 4] if ret & 1: self.log.debug("Busy") continue if ret & 2: - raise Exception("Error while accessing memory") + raise RuntimeError("Error while accessing memory") - result[word*4:word*4+4] = reversed(res[idx:idx+4]) + result[word * 4 : word * 4 + 4] = reversed(res[idx : idx + 4]) word += 1 - + self._tap.SetState(JtagState.Idle) self._tap.Flush() - + # for word in range(1, word_count): # # Data phase # # self._tap.SetState(JtagState.SelectDR) @@ -226,13 +225,13 @@ def _ReadBlockWords(self, address: int, word_count: int) -> bytes: # continue # if (ret >> 32) & 2: # raise Exception("Error while accessing memory") - + # struct.pack_into(">L", result, word*4, ret & 0xFFFFFFFF) # break return result - def _WriteBlockWords(self, address: int, data :bytes): + def _WriteBlockWords(self, address: int, data: bytes) -> None: # for i in range(0, len(data), 4): # value = struct.unpack_from(">L", data, i)[0] # self._WriteMemoryWord(address + i, value) @@ -240,7 +239,7 @@ def _WriteBlockWords(self, address: int, data :bytes): if len(data) <= 0: return if (len(data) % 4) != 0: - raise Exception("Data to be written is not a multiple of 4 bytes") + raise RuntimeError("Data to be written is not a multiple of 4 bytes") value = struct.unpack_from(">L", data, 0)[0] self._WriteMemoryWord(address, value) @@ -255,13 +254,13 @@ def _WriteBlockWords(self, address: int, data :bytes): self.log.debug("Busy") continue if ret & 0x8: - raise Exception("MEMORY_WORD_ACCESS operation failed") + raise RuntimeError("MEMORY_WORD_ACCESS operation failed") if ret & 0x10: - raise Exception("Chip is protected") + raise RuntimeError("Chip is protected") break self._tap.SetState(JtagState.Idle) - + for word in range(1, word_count): # Data phase self._tap.SetState(JtagState.SelectDR) @@ -274,12 +273,12 @@ def _WriteBlockWords(self, address: int, data :bytes): self._tap.SetState(JtagState.SelectDR) continue if ret & 2: - raise Exception("Error while accessing memory") + raise RuntimeError("Error while accessing memory") break value = struct.unpack_from(">L", data, word * 4)[0] self._tap.DROut(value, 32, JtagState.UpdateDR) - + # for word in range(1, word_count): # # Data phase # self._tap.SetState(JtagState.SelectDR) @@ -296,4 +295,4 @@ def _WriteBlockWords(self, address: int, data :bytes): # break self._tap.SetState(JtagState.Idle) - self._tap.Flush() \ No newline at end of file + self._tap.Flush() diff --git a/digilent_hs3/hs3program/ftdi_jtag_adapter.py b/digilent_hs3/hs3program/ftdi_jtag_adapter.py index 66c3773..24132c2 100644 --- a/digilent_hs3/hs3program/ftdi_jtag_adapter.py +++ b/digilent_hs3/hs3program/ftdi_jtag_adapter.py @@ -1,37 +1,41 @@ # Copyright (C) 2012-2022 Jeppe Johansen import logging import struct -import typing - +from typing import Optional +from typing import Tuple +from typing import Union + +from hs3program.jtag_adapter import JtagAdapter +from hs3program.jtag_adapter import JtagState +from hs3program.jtag_adapter import NavigateState +from hs3program.jtag_adapter import NextState from pyftdi.ftdi import Ftdi -from hs3program.jtag_adapter import JtagAdapter, JtagState, NavigateState, NextState - DIR = 0x000B INIT = 0x0008 -MPSSE_SET_DATA_LOW = 0x80 -MPSSE_READ_DATA_LOW = 0x81 -MPSSE_SET_DATA_HIGH = 0x82 +MPSSE_SET_DATA_LOW = 0x80 +MPSSE_READ_DATA_LOW = 0x81 +MPSSE_SET_DATA_HIGH = 0x82 MPSSE_READ_DATA_HIGH = 0x83 -MPSSE_LOOPBACK_ON = 0x84 -MPSSE_LOOPBACK_OFF = 0x85 -MPSSE_SET_CLOCK = 0x86 +MPSSE_LOOPBACK_ON = 0x84 +MPSSE_LOOPBACK_OFF = 0x85 +MPSSE_SET_CLOCK = 0x86 MPSSE_SEND_IMMEDIATE = 0x87 -MPSSE_DISABLE_DIV5 = 0x8A -MPSSE_ENABLE_DIV5 = 0x8B -MPSSE_ENABLE_3PHASE = 0x8C +MPSSE_DISABLE_DIV5 = 0x8A +MPSSE_ENABLE_DIV5 = 0x8B +MPSSE_ENABLE_3PHASE = 0x8C MPSSE_DISABLE_3PHASE = 0x8D -MPSSE_ENABLE_RCK = 0x96 -MPSSE_DISABLE_RCK = 0x97 +MPSSE_ENABLE_RCK = 0x96 +MPSSE_DISABLE_RCK = 0x97 MPSSE_CLK_ON_WRITE = 0x01 -MPSSE_BITMODE = 0x02 -MPSSE_CLK_ON_READ = 0x04 -MPSSE_LSB_FIRST = 0x08 -MPSSE_DO_TDO = 0x10 -MPSSE_DO_TDI = 0x20 -MPSSE_DO_TMS = 0x40 +MPSSE_BITMODE = 0x02 +MPSSE_CLK_ON_READ = 0x04 +MPSSE_LSB_FIRST = 0x08 +MPSSE_DO_TDO = 0x10 +MPSSE_DO_TDI = 0x20 +MPSSE_DO_TMS = 0x40 def get_transition_seq(src, dst): @@ -42,7 +46,7 @@ def get_transition_seq(src, dst): return (0, 0) curr = src - + while curr != dst: sel = NavigateState[curr][int(dst)] tms = tms | (sel << cnt) @@ -53,7 +57,16 @@ def get_transition_seq(src, dst): class FTDIJtagAdapter(JtagAdapter): - def __init__(self, vid, pid, init, dir, frequency=6e6, nSRST: typing.Tuple[int, int] = None, nTRST: typing.Tuple[int, int] = None): + def __init__( + self, + vid: int, + pid: int, + init: int, + direction: int, + frequency: float = 6e6, + nSRST: Optional[Tuple[int, int]] = None, + nTRST: Optional[Tuple[int, int]] = None, + ): JtagAdapter.__init__(self) self._dev = Ftdi() @@ -64,8 +77,8 @@ def __init__(self, vid, pid, init, dir, frequency=6e6, nSRST: typing.Tuple[int, for from_state in JtagState: for to_state in JtagState: self._transition_table[(from_state, to_state)] = get_transition_seq(from_state, to_state) - - self._dir = DIR | (dir & 0xFFF0) + + self._direction = DIR | (direction & 0xFFF0) self._initial = INIT | (init & 0xFFF0) self._has_srst = False @@ -75,22 +88,22 @@ def __init__(self, vid, pid, init, dir, frequency=6e6, nSRST: typing.Tuple[int, self._has_srst = True self._srst = nSRST - self._dir |= nSRST[0] | nSRST[1] + self._direction |= nSRST[0] | nSRST[1] self._initial |= nSRST[1] if nTRST is not None: self._has_trst = True self._trst = nTRST - self._dir |= nTRST[0] | nTRST[1] + self._direction |= nTRST[0] | nTRST[1] self._initial |= nTRST[1] self._current = self._initial - self._dev.open_mpsse(vid, pid, direction=self._dir, initial=self._initial, frequency=frequency) + self._dev.open_mpsse(vid, pid, direction=self._direction, initial=self._initial, frequency=frequency) self._stateDefined = False - self._currentState = -1 + self._currentState = JtagState.Unknown self._dev.read_data_set_chunksize(512) self._dev.write_data_set_chunksize(512) @@ -103,12 +116,12 @@ def __init__(self, vid, pid, init, dir, frequency=6e6, nSRST: typing.Tuple[int, def Close(self): self._dev.close() - def _WriteGPIO(self, dir, value): - self._AddBufferD([MPSSE_SET_DATA_LOW, value & 0xFF, dir & 0xFF]) + def _WriteGPIO(self, direction, value): + self._AddBufferD([MPSSE_SET_DATA_LOW, value & 0xFF, direction & 0xFF]) self._SendBuffer() self._dev.validate_mpsse() - self._AddBufferD([MPSSE_SET_DATA_HIGH, (value >> 8) & 0xFF, (dir >> 8) & 0xFF]) + self._AddBufferD([MPSSE_SET_DATA_HIGH, (value >> 8) & 0xFF, (direction >> 8) & 0xFF]) self._SendBuffer() self._dev.validate_mpsse() @@ -120,21 +133,21 @@ def _AddBuffer(self, byte): def _AddBufferD(self, data): count = len(data) # self._EnsureSpace(count) - self._buffer[self._buffer_size:self._buffer_size+count] = data + self._buffer[self._buffer_size : self._buffer_size + count] = data self._buffer_size += count - - def _AddBufferW(self, cmd: int): + + def _AddBufferW(self, cmd: int) -> None: # self._EnsureSpace(2) struct.pack_into(" None: if self._buffer_size + count >= len(self._buffer): self._SendBuffer() def _SendBuffer(self): if self._buffer_size > 0: - self._dev.write_data(self._buffer[0:self._buffer_size]) + self._dev.write_data(self._buffer[0 : self._buffer_size]) self._buffer_size = 0 def _CheckCommand(self): @@ -152,7 +165,7 @@ def _Read(self, size): if reads > 0: self.log.error("Multiple reads needed: %d", reads) - self.log.debug("Read %d bytes out of %d" % (len(res), size)) + self.log.debug("Read %d bytes out of %d", len(res), size) return res def _ClockTMSReadTDI(self, values: int, count: int, LastBit: bool) -> int: @@ -161,8 +174,10 @@ def _ClockTMSReadTDI(self, values: int, count: int, LastBit: bool) -> int: elif count <= 0: return 0 - self._AddBuffer(MPSSE_DO_TMS | MPSSE_DO_TDI | MPSSE_DO_TDO | MPSSE_CLK_ON_WRITE | MPSSE_LSB_FIRST | MPSSE_BITMODE) - self._AddBuffer(count-1) + self._AddBuffer( + MPSSE_DO_TMS | MPSSE_DO_TDI | MPSSE_DO_TDO | MPSSE_CLK_ON_WRITE | MPSSE_LSB_FIRST | MPSSE_BITMODE + ) + self._AddBuffer(count - 1) self._AddBuffer(values | (int(LastBit) << 7)) self._AddBuffer(MPSSE_SEND_IMMEDIATE) @@ -170,13 +185,19 @@ def _ClockTMSReadTDI(self, values: int, count: int, LastBit: bool) -> int: return self._Read(1)[0] - def _ClockTMS(self, value, count, lastBit = True): + def _ClockTMS(self, value, count, lastBit=True): if count > 7: count = 7 elif count <= 0: return - self._AddBufferD([MPSSE_DO_TMS | MPSSE_CLK_ON_WRITE | MPSSE_LSB_FIRST | MPSSE_BITMODE, count-1, value | (int(lastBit) << 7)]) + self._AddBufferD( + [ + MPSSE_DO_TMS | MPSSE_CLK_ON_WRITE | MPSSE_LSB_FIRST | MPSSE_BITMODE, + count - 1, + value | (int(lastBit) << 7), + ] + ) # self._SendBuffer() @@ -189,14 +210,14 @@ def _IntSetState(self, state: JtagState, TDO: bool = False) -> bool: self._stateDefined = True if self._currentState == state: - return + raise RuntimeError("Already in state - no transition needed - unable to read TDO") (val, x) = self._transition_table[(self._currentState, state)] self._currentState = state val = self._ClockTMSReadTDI(val, x, TDO) - return ((val >> (8-x)) & 1) == 1 + return ((val >> (8 - x)) & 1) == 1 def _IntSetState_NoRead(self, state: JtagState, TDO: bool = False) -> None: if not self._stateDefined: @@ -216,61 +237,61 @@ def _IntSetState_NoRead(self, state: JtagState, TDO: bool = False) -> None: def Flush(self): self._SendBuffer() - def SRST(self, state: str): + def SRST(self, state: str) -> None: if self._srst is None: - raise Exception("No SRST pin configured") - + raise RuntimeError("No SRST pin configured") + data = self._current - if state == '1': + if state == "1": data |= self._srst[0] data &= ~self._srst[1] - elif state == '0': + elif state == "0": data &= ~self._srst[0] data &= ~self._srst[1] - elif state in ['Z', 'z']: + elif state in ["Z", "z"]: data &= ~self._srst[0] data |= self._srst[1] self._current = data - - self._WriteGPIO(self._dir, data) + + self._WriteGPIO(self._direction, data) def SetState(self, state: JtagState) -> None: self._IntSetState_NoRead(state) - def Clock(self, count: int): + def Clock(self, count: int) -> None: self._ClockTMS(0, count) - def _WriteBytes(self, data: typing.Union[bytes, bytearray]) -> bytearray: + def _WriteBytes(self, data: Union[bytes, bytearray]) -> None: count = len(data) if count > self._MaxRW: count = self._MaxRW elif count <= 0: - return bytearray() + return self._AddBuffer(MPSSE_DO_TDO | MPSSE_CLK_ON_WRITE | MPSSE_LSB_FIRST) - self._AddBufferW(count-1) + self._AddBufferW(count - 1) self._AddBufferD(data) # self._SendBuffer() # self._CheckCommand() - def _WriteBits(self, data: int, count: int) -> int: + def _WriteBits(self, data: int, count: int) -> None: if count > 8: count = 8 elif count <= 0: - return 0 + return self._AddBuffer(MPSSE_DO_TDO | MPSSE_CLK_ON_WRITE | MPSSE_LSB_FIRST | MPSSE_BITMODE) - self._AddBuffer(count-1) + self._AddBuffer(count - 1) self._AddBuffer(data) # self._SendBuffer() # self._CheckCommand() - def _ReadWriteBytes(self, data: typing.Union[bytes, bytearray]) -> bytearray: + def _ReadWriteBytes(self, data: Union[bytes, bytearray]) -> bytearray: count = len(data) if count > self._MaxRW: @@ -279,7 +300,7 @@ def _ReadWriteBytes(self, data: typing.Union[bytes, bytearray]) -> bytearray: return bytearray() self._AddBuffer(MPSSE_DO_TDO | MPSSE_DO_TDI | MPSSE_CLK_ON_WRITE | MPSSE_LSB_FIRST) - self._AddBufferW(count-1) + self._AddBufferW(count - 1) self._AddBufferD(data) self._AddBuffer(MPSSE_SEND_IMMEDIATE) @@ -294,15 +315,15 @@ def _ReadWriteBits(self, data: int, count: int) -> int: return 0 self._AddBuffer(MPSSE_DO_TDO | MPSSE_DO_TDI | MPSSE_CLK_ON_WRITE | MPSSE_LSB_FIRST | MPSSE_BITMODE) - self._AddBuffer(count-1) + self._AddBuffer(count - 1) self._AddBuffer(data) self._AddBuffer(MPSSE_SEND_IMMEDIATE) self._SendBuffer() - return self._Read(1)[0] >> (8-count) + return self._Read(1)[0] >> (8 - count) - def SetSignal(self, signal: str, high: bool): + def SetSignal(self, signal: str, high: bool) -> None: signal_mask = { "TCK": 0x1, "TDI": 0x2, @@ -310,7 +331,7 @@ def SetSignal(self, signal: str, high: bool): } if signal not in signal_mask: - raise Exception("Signal not controllable") + raise RuntimeError("Signal not controllable") current = self._current if high: @@ -319,8 +340,8 @@ def SetSignal(self, signal: str, high: bool): current &= ~signal_mask[signal] self._current = current - self._WriteGPIO(self._dir, current) - + self._WriteGPIO(self._direction, current) + def IR(self, value: int, count: int, endState: JtagState = JtagState.Idle) -> int: self.SetState(JtagState.ShiftIR) @@ -334,7 +355,7 @@ def IR(self, value: int, count: int, endState: JtagState = JtagState.Idle) -> in if count > 8: nb = count // 8 indata[0:nb] = self._ReadWriteBytes(outdata[0:nb]) - count = count - nb*8 + count = count - nb * 8 idx += nb @@ -346,7 +367,7 @@ def IR(self, value: int, count: int, endState: JtagState = JtagState.Idle) -> in LastBit = self._IntSetState(endState, LastBit) indata[idx] |= int(LastBit) << count - + return struct.unpack(" int: @@ -362,7 +383,7 @@ def DR(self, value: int, count: int, endState: JtagState = JtagState.Idle) -> in if count > 8: nb = count // 8 indata[0:nb] = self._ReadWriteBytes(outdata[0:nb]) - count = count - nb*8 + count = count - nb * 8 idx += nb if count > 0: @@ -373,7 +394,7 @@ def DR(self, value: int, count: int, endState: JtagState = JtagState.Idle) -> in LastBit = self._IntSetState(endState, LastBit) indata[idx] |= int(LastBit) << count - + return struct.unpack(" None: @@ -388,7 +409,7 @@ def DROut(self, value: int, count: int, endState: JtagState = JtagState.Idle) -> if count > 8: nb = count // 8 self._WriteBytes(outdata[0:nb]) - count = count - nb*8 + count = count - nb * 8 idx += nb if count > 0: @@ -397,17 +418,17 @@ def DROut(self, value: int, count: int, endState: JtagState = JtagState.Idle) -> if endState != JtagState.ShiftDR: LastBit = ((outdata[idx] >> count) & 1) == 1 self._IntSetState_NoRead(endState, LastBit) - + # self._SendBuffer() # self._CheckCommand() - def ScheduleDRIn(self, bytes: int): + def ScheduleDRIn(self, num_bytes: int) -> None: self._AddBuffer(MPSSE_DO_TDI | MPSSE_LSB_FIRST) - self._AddBufferW(bytes-1) + self._AddBufferW(num_bytes - 1) - def ReadScheduled(self, bytes: int): + def ReadScheduled(self, num_bytes: int) -> bytes: self._AddBuffer(MPSSE_SEND_IMMEDIATE) self._SendBuffer() - return self._Read(bytes) \ No newline at end of file + return self._Read(num_bytes) diff --git a/digilent_hs3/hs3program/jtag_adapter.py b/digilent_hs3/hs3program/jtag_adapter.py index 9c30119..cf62629 100644 --- a/digilent_hs3/hs3program/jtag_adapter.py +++ b/digilent_hs3/hs3program/jtag_adapter.py @@ -1,68 +1,68 @@ # Copyright (C) 2012-2022 Jeppe Johansen import abc -from enum import IntEnum -import math import struct import typing +from enum import IntEnum class JtagState(IntEnum): - Unknown = -1, - - Reset = 0, - Idle = 1, - SelectDR = 2, - CaptureDR = 3, - ShiftDR = 4, - Exit1DR = 5, - PauseDR = 6, - Exit2DR = 7, - UpdateDR = 8, - - SelectIR = 9, - CaptureIR = 10, - ShiftIR = 11, - Exit1IR = 12, - PauseIR = 13, - Exit2IR = 14, - UpdateIR = 15, + Unknown = (-1,) + + Reset = (0,) + Idle = (1,) + SelectDR = (2,) + CaptureDR = (3,) + ShiftDR = (4,) + Exit1DR = (5,) + PauseDR = (6,) + Exit2DR = (7,) + UpdateDR = (8,) + + SelectIR = (9,) + CaptureIR = (10,) + ShiftIR = (11,) + Exit1IR = (12,) + PauseIR = (13,) + Exit2IR = (14,) + UpdateIR = (15,) + NextState = { JtagState.Reset: {False: JtagState.Idle, True: JtagState.Reset}, JtagState.Idle: {False: JtagState.Idle, True: JtagState.SelectDR}, - JtagState.SelectDR: {False: JtagState.CaptureDR, True: JtagState.SelectIR}, + JtagState.SelectDR: {False: JtagState.CaptureDR, True: JtagState.SelectIR}, JtagState.CaptureDR: {False: JtagState.ShiftDR, True: JtagState.Exit1DR}, JtagState.ShiftDR: {False: JtagState.ShiftDR, True: JtagState.Exit1DR}, JtagState.Exit1DR: {False: JtagState.PauseDR, True: JtagState.UpdateDR}, JtagState.PauseDR: {False: JtagState.PauseDR, True: JtagState.Exit2DR}, JtagState.Exit2DR: {False: JtagState.ShiftDR, True: JtagState.UpdateDR}, JtagState.UpdateDR: {False: JtagState.Idle, True: JtagState.SelectDR}, - JtagState.SelectIR: {False: JtagState.CaptureIR, True: JtagState.Reset}, + JtagState.SelectIR: {False: JtagState.CaptureIR, True: JtagState.Reset}, JtagState.CaptureIR: {False: JtagState.ShiftIR, True: JtagState.Exit1IR}, JtagState.ShiftIR: {False: JtagState.ShiftIR, True: JtagState.Exit1IR}, JtagState.Exit1IR: {False: JtagState.PauseIR, True: JtagState.UpdateIR}, JtagState.PauseIR: {False: JtagState.PauseIR, True: JtagState.Exit2IR}, JtagState.Exit2IR: {False: JtagState.ShiftIR, True: JtagState.UpdateIR}, - JtagState.UpdateIR: {False: JtagState.Idle, True: JtagState.SelectDR} + JtagState.UpdateIR: {False: JtagState.Idle, True: JtagState.SelectDR}, } NavigateState = { - JtagState.Reset: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - JtagState.Idle: [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - JtagState.SelectDR: [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1], - JtagState.CaptureDR: [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - JtagState.ShiftDR: [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - JtagState.Exit1DR: [1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1], - JtagState.PauseDR: [1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], - JtagState.Exit2DR: [1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1], - JtagState.UpdateDR: [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], - JtagState.SelectIR: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], - JtagState.CaptureIR: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1], - JtagState.ShiftIR: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1], - JtagState.Exit1IR: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1], - JtagState.PauseIR: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], - JtagState.Exit2IR: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1], - JtagState.UpdateIR: [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1] + JtagState.Reset: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + JtagState.Idle: [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + JtagState.SelectDR: [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1], + JtagState.CaptureDR: [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + JtagState.ShiftDR: [1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + JtagState.Exit1DR: [1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1], + JtagState.PauseDR: [1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1], + JtagState.Exit2DR: [1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1], + JtagState.UpdateDR: [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + JtagState.SelectIR: [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + JtagState.CaptureIR: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1], + JtagState.ShiftIR: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1], + JtagState.Exit1IR: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1], + JtagState.PauseIR: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1], + JtagState.Exit2IR: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1], + JtagState.UpdateIR: [1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], } @@ -72,8 +72,8 @@ class JtagState(IntEnum): VERSIONMASK = 0xF0000000 -def _Bits(len: int) -> int: - return (1 << len)-1 +def _Bits(length: int) -> int: + return (1 << length) - 1 class JtagDevice: @@ -93,7 +93,7 @@ def IRLength(self) -> int: class JtagAdapter(abc.ABC): def __init__(self): self._IRLength = 0 - self._devices = [] # type: typing.List[JtagDevice] + self._devices = [] self._headerDR = 0 self._trailerDR = 0 @@ -103,19 +103,22 @@ def __init__(self): def Close(self): pass - def DeviceIndex(self, idCode): - return map(lambda dev: dev.IDCode == idCode, self._devices).index(True) + def DeviceIndex(self, idCode: int) -> int: + for index, device in enumerate(self._devices): + if device.IDCode == idCode: + return index + raise ValueError("Device not found") def SoftReset(self): self.SetState(JtagState.Reset) self.SetState(JtagState.Idle) @abc.abstractmethod - def SetSignal(self, signal: str, high: bool): + def SetSignal(self, signal: str, high: bool) -> None: raise NotImplementedError() @abc.abstractmethod - def SRST(self, state: str): + def SRST(self, state: str) -> None: """ state can be '0', '1', or 'z'. """ @@ -130,14 +133,14 @@ def Flush(self) -> None: raise NotImplementedError() @abc.abstractmethod - def Clock(self, count: int): + def Clock(self, count: int) -> None: raise NotImplementedError() def DetectDevices(self): self.SoftReset() self._IRLength = 0 _devices = [] - if self.IR(1,1,JtagState.ShiftIR) == 0: + if self.IR(1, 1, JtagState.ShiftIR) == 0: self.SoftReset() return @@ -146,13 +149,13 @@ def DetectDevices(self): tmp = self.DR(0xFFFFFFFF, 32) self.SoftReset() - while (True): + while True: tmp = self.DR(1, 1, JtagState.ShiftDR) if tmp == 1: tmp = tmp | (self.DR(INVALIDMANUFACTURER >> 1, 31, JtagState.ShiftDR) << 1) if tmp == 0xFFFFFFFF: - break # Highly unlikely + break # Highly unlikely if (tmp & MANUFACTURERMASK) == INVALIDMANUFACTURER: break @@ -166,7 +169,7 @@ def DetectDevices(self): self.SetState(JtagState.Reset) # Get IR length - self.IR(1,1,JtagState.ShiftIR) + self.IR(1, 1, JtagState.ShiftIR) for i in range(len(_devices)): _devices[i]["IRLength"] = 0 @@ -182,22 +185,22 @@ def DetectDevices(self): self._devices = [JtagDevice(o["IDCode"], o["IRLength"]) for o in _devices] - def SelectDevice(self, index: int): + def SelectDevice(self, index: int) -> None: for i in range(self.IRLength): self.IR(1, 1, JtagState.ShiftIR) self.DR(~(1 << index), len(self._devices)) self._headerDR = index - self._trailerDR = len(self._devices)-index-1 + self._trailerDR = len(self._devices) - index - 1 self._headerIR = 0 self._trailerIR = 0 for i in range(len(self._devices)): if index > i: - self._headerIR += self._devices[i]["IRLength"] + self._headerIR += self._devices[i].IRLength elif index < i: - self._trailerIR += self._devices[i]["IRLength"] + self._trailerIR += self._devices[i].IRLength @abc.abstractmethod def IR(self, value: int, count: int, endState: JtagState = JtagState.Idle) -> int: @@ -211,15 +214,15 @@ def DROut(self, value: int, count: int, endState: JtagState = JtagState.Idle) -> self.DR(value, count, endState) @abc.abstractmethod - def ScheduleDRIn(self, bytes: int): + def ScheduleDRIn(self, num_bytes: int) -> None: raise NotImplementedError() @abc.abstractmethod - def ReadScheduled(self, bytes: int): + def ReadScheduled(self, num_bytes: int) -> bytes: raise NotImplementedError() def ScanIR(self, inValue: bytes, count: int, endState: JtagState) -> bytes: - output = bytes((count+7) // 8) + output = bytearray((count + 7) // 8) idx = 0 while count > 64: @@ -232,7 +235,7 @@ def ScanIR(self, inValue: bytes, count: int, endState: JtagState) -> bytes: while count > 0: inp = struct.unpack_from(" bytes: if endState != JtagState.ShiftIR: self.SetState(endState) - - return output + + return bytes(output) def ScanDR(self, inValue: bytes, count: int, endState: JtagState = JtagState.Idle) -> bytes: - output = bytes((count+7) // 8) + output = bytearray((count + 7) // 8) idx = 0 while count > 64: @@ -257,7 +260,7 @@ def ScanDR(self, inValue: bytes, count: int, endState: JtagState = JtagState.Idl while count > 0: inp = struct.unpack_from(" int: self.IR(_Bits(self._headerIR), self._headerIR, JtagState.ShiftIR) @@ -283,7 +286,7 @@ def ChainDR(self, AValue: int, ACount: int, endState: JtagState = JtagState.Idle @property def IRLength(self) -> int: return self._IRLength - + @property def Devices(self) -> typing.Sequence[JtagDevice]: - return list(self._devices) \ No newline at end of file + return list(self._devices) diff --git a/digilent_hs3/setup.py b/digilent_hs3/setup.py index 4f6fcff..7e52b85 100644 --- a/digilent_hs3/setup.py +++ b/digilent_hs3/setup.py @@ -1,15 +1,13 @@ -from setuptools import find_packages, setup +from setuptools import find_packages +from setuptools import setup setup( - name='hs3program', - version='2.0.0', + name="hs3program", + version="2.0.0", packages=find_packages(), - install_requires=[ - 'pyelftools>=0.29', - 'pyftdi>=0.54.0' - ], - entry_points=''' + install_requires=["pyelftools>=0.29", "pyftdi>=0.54.0"], + entry_points=""" [console_scripts] hs3program=hs3program.avr32_prog:main - ''', -) \ No newline at end of file + """, +)