123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490 |
- """
- # TOP2049 Open Source programming suite
- #
- # Implements the Atmel Mega MCU parallel HV programming algorithm
- #
- # Copyright (c) 2009-2010 Michael Buesch <m@bues.ch>
- #
- # This program is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 2 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License along
- # with this program; if not, write to the Free Software Foundation, Inc.,
- # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- """
- from libtoprammer.chip import *
- class Chip_ATMega_common(Chip):
- # The Atmel Mega programming commands
- CMD_CHIPERASE = 0x80 # Chip Erase
- CMD_WRITEFUSE = 0x40 # Write Fuse Bits
- CMD_WRITELOCK = 0x20 # Write Lock Bits
- CMD_WRITEFLASH = 0x10 # Write Flash
- CMD_WRITEEEPROM = 0x11 # Write EEPROM
- CMD_READSIG = 0x08 # Read Signature bytes and Calibration byte
- CMD_READFUSELOCK = 0x04 # Read Fuse and Lock bits
- CMD_READFLASH = 0x02 # Read Flash
- CMD_READEEPROM = 0x03 # Read EEPROM
- def __init__(self,
- chipPackage, chipPinVCC, chipPinsVPP, chipPinGND,
- signature,
- flashPageSize, flashPages,
- eepromPageSize, eepromPages,
- fuseBytes
- ):
- Chip.__init__(self,
- chipPackage = chipPackage,
- chipPinVCC = chipPinVCC,
- chipPinsVPP = chipPinsVPP,
- chipPinGND = chipPinGND)
- self.signature = signature
- self.flashPageSize = flashPageSize # Flash page size, in words
- self.flashPages = flashPages # Nr of flash pages
- self.eepromPageSize = eepromPageSize # EEPROM page size, in bytes
- self.eepromPages = eepromPages # Nr of EEPROM pages
- self.fuseBytes = fuseBytes # Nr of fuse bytes
- def readSignature(self):
- self.__enterPM()
- (signature, calibration) = self.__readSigAndCalib()
- return signature
- def erase(self):
- self.__enterPM()
- self.progressMeterInit("Erasing chip", 0)
- self.__loadCommand(self.CMD_CHIPERASE)
- self.__pulseWR()
- self.__waitForRDY()
- self.progressMeterFinish()
- def readProgmem(self):
- self.__enterPM()
- self.progressMeterInit("Reading Flash", self.flashPages)
- image = b""
- for page in range(0, self.flashPages):
- self.progressMeter(page)
- readWords = 0
- for word in range(0, self.flashPageSize):
- self.__loadCommand(self.CMD_READFLASH)
- self.__loadAddr((page * self.flashPageSize) + word)
- self.__readWordToStatusReg()
- readWords += 1
- if readWords >= 32:
- image += self.top.cmdReadBufferReg()
- readWords = 0
- if readWords:
- data = self.top.cmdReadBufferReg()
- image += data[0:readWords*2]
- self.progressMeterFinish()
- return image
- def writeProgmem(self, image):
- flashBytes = self.flashPageSize * 2 * self.flashPages
- if len(image) != flashBytes:
- self.throwError("Invalid program memory image size %d (expected %d)" %\
- (len(image), flashBytes))
- self.__enterPM()
- self.progressMeterInit("Writing Flash", self.flashPages)
- for page in range(0, self.flashPages):
- self.progressMeter(page)
- for word in range(0, self.flashPageSize):
- self.__loadCommand(self.CMD_WRITEFLASH)
- addr = (page * self.flashPageSize) + word
- self.__loadAddr(addr)
- addr *= 2
- data = image[addr : addr + 2]
- self.__loadData(byte2int(data[0]) | (byte2int(data[1]) << 8))
- self.__setBS1(1)
- self.__pulsePAGEL()
- self.__setBS1(0)
- self.__pulseWR()
- self.__waitForRDY()
- self.progressMeterFinish()
- def readEEPROM(self):
- self.__enterPM()
- assert(self.eepromPageSize <= self.top.getBufferRegSize())
- self.progressMeterInit("Reading EEPROM", self.eepromPages)
- image = b""
- for page in range(0, self.eepromPages):
- self.progressMeter(page)
- for byte in range(0, self.eepromPageSize):
- self.__loadCommand(self.CMD_READEEPROM)
- self.__loadAddr((page * self.eepromPageSize) + byte)
- self.__readLowByteToStatusReg()
- data = self.top.cmdReadBufferReg()
- image += data[0:self.eepromPageSize]
- self.progressMeterFinish()
- return image
- def writeEEPROM(self, image):
- eepromBytes = self.eepromPageSize * self.eepromPages
- if len(image) != eepromBytes:
- self.throwError("Invalid EEPROM image size %d (expected %d)" %\
- (len(image), eepromBytes))
- self.__enterPM()
- self.progressMeterInit("Writing EEPROM", self.eepromPages)
- for page in range(0, self.eepromPages):
- self.progressMeter(page)
- for byte in range(0, self.eepromPageSize):
- self.__loadCommand(self.CMD_WRITEEEPROM)
- addr = (page * self.eepromPageSize) + byte
- self.__loadAddr(addr)
- self.__loadDataLow(image[addr])
- self.__pulsePAGEL()
- self.__setBS1(0)
- self.__pulseWR()
- self.__waitForRDY()
- self.progressMeterFinish()
- def readFuse(self):
- self.__enterPM()
- self.progressMeterInit("Reading Fuse bits", 0)
- (fuse, lock) = self.__readFuseAndLockBits()
- self.progressMeterFinish()
- return fuse
- def writeFuse(self, image):
- if len(image) != self.fuseBytes:
- self.throwError("Invalid Fuses image size %d (expected %d)" %\
- (len(image), self.fuseBytes))
- self.__enterPM()
- self.progressMeterInit("Writing Fuse bits", 0)
- self.__loadCommand(self.CMD_WRITEFUSE)
- self.__setBS2(0)
- self.__loadDataLow(byte2int(image[0]))
- self.__setBS1(0)
- self.__pulseWR()
- self.__waitForRDY()
- self.__loadCommand(self.CMD_WRITEFUSE)
- self.__setBS2(0)
- self.__loadDataLow(byte2int(image[1]))
- self.__setBS1(1)
- self.__pulseWR()
- self.__waitForRDY()
- if len(image) >= 3:
- self.__loadCommand(self.CMD_WRITEFUSE)
- self.__setBS2(1)
- self.__loadDataLow(byte2int(image[2]))
- self.__setBS1(0)
- self.__pulseWR()
- self.__waitForRDY()
- self.__setBS1(0)
- self.__setBS2(0)
- self.progressMeterFinish()
- def readLockbits(self):
- self.__enterPM()
- self.progressMeterInit("Reading lock bits", 0)
- (fuses, lockbits) = self.__readFuseAndLockBits()
- self.progressMeterFinish()
- return lockbits
- def writeLockbits(self, image):
- if len(image) != 1:
- self.throwError("Invalid lock-bits image size %d (expected %d)" %\
- (len(image), 1))
- self.__enterPM()
- self.progressMeterInit("Writing lock bits", 0)
- self.__loadCommand(self.CMD_WRITELOCK)
- self.__loadDataLow(byte2int(image[0]))
- self.__pulseWR()
- self.__waitForRDY()
- self.progressMeterFinish()
- def __readSigAndCalib(self):
- """Reads the signature and calibration bytes and returns them.
- This function expects a DUT present and pins initialized."""
- signature = b""
- calibration = b""
- for addr in range(0, 3):
- self.__loadCommand(self.CMD_READSIG)
- self.__loadAddr(addr)
- self.__readWordToStatusReg()
- data = self.top.cmdReadBufferReg()
- if addr == 0:
- calibration += int2byte(data[1])
- signature += int2byte(data[0])
- return (signature, calibration)
- def __readFuseAndLockBits(self):
- """Reads the Fuse and Lock bits and returns them.
- This function expects a DUT present and pins initialized."""
- self.__loadCommand(self.CMD_READFUSELOCK)
- self.__setBS2(0)
- self.__readWordToStatusReg()
- self.__setBS2(1)
- self.__readWordToStatusReg()
- self.__setBS2(0)
- data = self.top.cmdReadBufferReg()
- if self.fuseBytes == 2:
- # fuseLow, fuseHigh
- fuses = int2byte(data[0]) + int2byte(data[3])
- elif self.fuseBytes == 3:
- # fuseLow, fuseHigh, fuseExt
- fuses = int2byte(data[0]) + int2byte(data[3]) + int2byte(data[2])
- else:
- assert(0)
- lock = int2byte(data[1])
- return (fuses, lock)
- def __enterPM(self):
- "Enter HV programming mode."
- self.applyVPP(False)
- self.applyVCC(False)
- self.applyGND(True)
- self.top.cmdSetVPPVoltage(0)
- self.top.cmdSetVPPVoltage(12)
- self.top.cmdSetVCCVoltage(5)
- self.__setVoltageControl(VPP_en=1, VPP=0, VCC_en=1, VCC=0)
- self.__setXA0(0)
- self.__setXA1(0)
- self.__setBS1(0)
- self.__setPAGEL(0)
- self.__setWR(0)
- self.top.hostDelay(0.1)
- self.applyVCC(True)
- self.__setVoltageControl(VPP_en=1, VPP=0, VCC_en=1, VCC=1)
- self.top.hostDelay(0.1)
- self.__setOE(0)
- self.__setWR(1)
- self.__setXTAL1(0)
- self.__setXA0(0)
- self.__setXA1(0)
- self.__setBS1(0)
- self.__setBS2(0)
- self.__setPAGEL(0)
- self.__pulseXTAL1(10)
- self.top.flushCommands()
- self.__setVoltageControl(VPP_en=0, VPP=0, VCC_en=1, VCC=1)
- self.applyVPP(True)
- self.__setOE(1)
- (signature, calibration) = self.__readSigAndCalib()
- if signature != self.signature:
- msg = "Unexpected device signature. " +\
- "Want %02X%02X%02X, but got %02X%02X%02X" % \
- (byte2int(self.signature[0]), byte2int(self.signature[1]),
- byte2int(self.signature[2]),
- byte2int(signature[0]), byte2int(signature[1]),
- byte2int(signature[2]))
- if self.top.getForceLevel() >= 1:
- self.printWarning(msg)
- else:
- self.throwError(msg)
- def __readWordToStatusReg(self):
- """Read a data word from the DUT into the status register."""
- self.__setBS1(0)
- self.__setOE(0)
- self.top.cmdFPGARead(0x10)
- self.__setBS1(1)
- self.top.cmdFPGARead(0x10)
- self.__setOE(1)
- def __readLowByteToStatusReg(self):
- """Read the low data byte from the DUT into the status register."""
- self.__setBS1(0)
- self.__setOE(0)
- self.top.cmdFPGARead(0x10)
- self.__setOE(1)
- def __readHighByteToStatusReg(self):
- """Read the high data byte from the DUT into the status register."""
- self.__setBS1(1)
- self.__setOE(0)
- self.top.cmdFPGARead(0x10)
- self.__setOE(1)
- def __loadData(self, data):
- """Load a data word."""
- self.__loadDataLow(data)
- self.__loadDataHigh(data >> 8)
- def __loadDataLow(self, dataLow):
- """Load the low data byte."""
- self.__setBS1(0)
- self.__setXA0(1)
- self.__setXA1(0)
- self.top.cmdFPGAWrite(0x10, dataLow & 0xFF)
- self.__pulseXTAL1()
- def __loadDataHigh(self, dataHigh):
- """Load the high data byte."""
- self.__setBS1(1)
- self.__setXA0(1)
- self.__setXA1(0)
- self.top.cmdFPGAWrite(0x10, dataHigh & 0xFF)
- self.__pulseXTAL1()
- def __loadAddr(self, addr):
- """Load an address word."""
- self.__loadAddrLow(addr)
- self.__loadAddrHigh(addr >> 8)
- def __loadAddrLow(self, addrLow):
- """Load the low address byte."""
- self.__setBS1(0)
- self.__setXA0(0)
- self.__setXA1(0)
- self.top.cmdFPGAWrite(0x10, addrLow & 0xFF)
- self.__pulseXTAL1()
- def __loadAddrHigh(self, addrHigh):
- """Load the high address byte."""
- self.__setBS1(1)
- self.__setXA0(0)
- self.__setXA1(0)
- self.top.cmdFPGAWrite(0x10, addrHigh & 0xFF)
- self.__pulseXTAL1()
- def __loadCommand(self, command):
- """Load a command into the device."""
- # self.top.queueCommand(b"\x34")
- self.__setBS1(0)
- # self.top.queueCommand(b"\x34")
- self.__setXA0(0)
- self.__setXA1(1)
- self.top.cmdFPGAWrite(0x10, command)
- self.__pulseXTAL1()
- def __waitForRDY(self):
- """Wait for the RDY pin to go high."""
- self.top.hostDelay(0.01)
- for i in range(0, 50):
- if self.__getRDY():
- return
- self.top.hostDelay(0.01)
- self.throwError("Timeout waiting for READY signal from chip.")
- def __getRDY(self):
- """Read the state of the RDY/BSY pin."""
- return bool(self.__getStatus() & 0x01)
- def __getStatus(self):
- """Read the programmer status register"""
- self.top.cmdFPGARead(0x12)
- stat = self.top.cmdReadBufferReg()
- return byte2int(stat[0])
- def __setOE(self, high):
- """Set the OE pin of the DUT"""
- value = 0x02
- if high:
- value |= 0x80
- self.top.cmdFPGAWrite(0x12, value)
- def __setWR(self, high):
- """Set the WR pin of the DUT"""
- value = 0x03
- if high:
- value |= 0x80
- self.top.cmdFPGAWrite(0x12, value)
- def __pulseWR(self, count=1):
- """Do a negative pulse on the WR pin of the DUT"""
- while count > 0:
- self.__setWR(0)
- self.__setWR(1)
- count -= 1
- def __setBS1(self, high):
- """Set the BS1 pin of the DUT"""
- value = 0x04
- if high:
- value |= 0x80
- self.top.cmdFPGAWrite(0x12, value)
- def __setXA0(self, high):
- """Set the XA0 pin of the DUT"""
- value = 0x05
- if high:
- value |= 0x80
- self.top.cmdFPGAWrite(0x12, value)
- def __setXA1(self, high):
- """Set the XA1 pin of the DUT"""
- value = 0x06
- if high:
- value |= 0x80
- self.top.cmdFPGAWrite(0x12, value)
- def __setXTAL1(self, high):
- """Set the XTAL1 pin of the DUT"""
- value = 0x07
- if high:
- value |= 0x80
- self.top.cmdFPGAWrite(0x12, value)
- def __pulseXTAL1(self, count=1):
- """Do a positive pulse on the XTAL1 pin of the DUT"""
- while count > 0:
- self.__setXTAL1(1)
- self.__setXTAL1(0)
- count -= 1
- def __setPAGEL(self, high):
- """Set the PAGEL pin of the DUT"""
- value = 0x09
- if high:
- value |= 0x80
- self.top.cmdFPGAWrite(0x12, value)
- def __pulsePAGEL(self, count=1):
- """Do a positive pulse on the PAGEL pin of the DUT"""
- while count > 0:
- self.__setPAGEL(1)
- self.__setPAGEL(0)
- count -= 1
- def __setBS2(self, high):
- """Set the BS2 pin of the DUT"""
- value = 0x0A
- if high:
- value |= 0x80
- self.top.cmdFPGAWrite(0x12, value)
- def __setVoltageControl(self, VPP_en, VPP, VCC_en, VCC):
- value = 0
- if VPP_en:
- value |= 0x01
- if VPP:
- value |= 0x02
- if VCC_en:
- value |= 0x04
- if VCC:
- value |= 0x08
- self.top.cmdFPGAWrite(0x11, value)
|