atmega_common.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. """
  2. # TOP2049 Open Source programming suite
  3. #
  4. # Implements the Atmel Mega MCU parallel HV programming algorithm
  5. #
  6. # Copyright (c) 2009-2010 Michael Buesch <m@bues.ch>
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation; either version 2 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License along
  19. # with this program; if not, write to the Free Software Foundation, Inc.,
  20. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. """
  22. from libtoprammer.chip import *
  23. class Chip_ATMega_common(Chip):
  24. # The Atmel Mega programming commands
  25. CMD_CHIPERASE = 0x80 # Chip Erase
  26. CMD_WRITEFUSE = 0x40 # Write Fuse Bits
  27. CMD_WRITELOCK = 0x20 # Write Lock Bits
  28. CMD_WRITEFLASH = 0x10 # Write Flash
  29. CMD_WRITEEEPROM = 0x11 # Write EEPROM
  30. CMD_READSIG = 0x08 # Read Signature bytes and Calibration byte
  31. CMD_READFUSELOCK = 0x04 # Read Fuse and Lock bits
  32. CMD_READFLASH = 0x02 # Read Flash
  33. CMD_READEEPROM = 0x03 # Read EEPROM
  34. def __init__(self,
  35. chipPackage, chipPinVCC, chipPinsVPP, chipPinGND,
  36. signature,
  37. flashPageSize, flashPages,
  38. eepromPageSize, eepromPages,
  39. fuseBytes
  40. ):
  41. Chip.__init__(self,
  42. chipPackage = chipPackage,
  43. chipPinVCC = chipPinVCC,
  44. chipPinsVPP = chipPinsVPP,
  45. chipPinGND = chipPinGND)
  46. self.signature = signature
  47. self.flashPageSize = flashPageSize # Flash page size, in words
  48. self.flashPages = flashPages # Nr of flash pages
  49. self.eepromPageSize = eepromPageSize # EEPROM page size, in bytes
  50. self.eepromPages = eepromPages # Nr of EEPROM pages
  51. self.fuseBytes = fuseBytes # Nr of fuse bytes
  52. def readSignature(self):
  53. self.__enterPM()
  54. (signature, calibration) = self.__readSigAndCalib()
  55. return signature
  56. def erase(self):
  57. self.__enterPM()
  58. self.progressMeterInit("Erasing chip", 0)
  59. self.__loadCommand(self.CMD_CHIPERASE)
  60. self.__pulseWR()
  61. self.__waitForRDY()
  62. self.progressMeterFinish()
  63. def readProgmem(self):
  64. self.__enterPM()
  65. self.progressMeterInit("Reading Flash", self.flashPages)
  66. image = b""
  67. for page in range(0, self.flashPages):
  68. self.progressMeter(page)
  69. readWords = 0
  70. for word in range(0, self.flashPageSize):
  71. self.__loadCommand(self.CMD_READFLASH)
  72. self.__loadAddr((page * self.flashPageSize) + word)
  73. self.__readWordToStatusReg()
  74. readWords += 1
  75. if readWords >= 32:
  76. image += self.top.cmdReadBufferReg()
  77. readWords = 0
  78. if readWords:
  79. data = self.top.cmdReadBufferReg()
  80. image += data[0:readWords*2]
  81. self.progressMeterFinish()
  82. return image
  83. def writeProgmem(self, image):
  84. flashBytes = self.flashPageSize * 2 * self.flashPages
  85. if len(image) != flashBytes:
  86. self.throwError("Invalid program memory image size %d (expected %d)" %\
  87. (len(image), flashBytes))
  88. self.__enterPM()
  89. self.progressMeterInit("Writing Flash", self.flashPages)
  90. for page in range(0, self.flashPages):
  91. self.progressMeter(page)
  92. for word in range(0, self.flashPageSize):
  93. self.__loadCommand(self.CMD_WRITEFLASH)
  94. addr = (page * self.flashPageSize) + word
  95. self.__loadAddr(addr)
  96. addr *= 2
  97. data = image[addr : addr + 2]
  98. self.__loadData(byte2int(data[0]) | (byte2int(data[1]) << 8))
  99. self.__setBS1(1)
  100. self.__pulsePAGEL()
  101. self.__setBS1(0)
  102. self.__pulseWR()
  103. self.__waitForRDY()
  104. self.progressMeterFinish()
  105. def readEEPROM(self):
  106. self.__enterPM()
  107. assert(self.eepromPageSize <= self.top.getBufferRegSize())
  108. self.progressMeterInit("Reading EEPROM", self.eepromPages)
  109. image = b""
  110. for page in range(0, self.eepromPages):
  111. self.progressMeter(page)
  112. for byte in range(0, self.eepromPageSize):
  113. self.__loadCommand(self.CMD_READEEPROM)
  114. self.__loadAddr((page * self.eepromPageSize) + byte)
  115. self.__readLowByteToStatusReg()
  116. data = self.top.cmdReadBufferReg()
  117. image += data[0:self.eepromPageSize]
  118. self.progressMeterFinish()
  119. return image
  120. def writeEEPROM(self, image):
  121. eepromBytes = self.eepromPageSize * self.eepromPages
  122. if len(image) != eepromBytes:
  123. self.throwError("Invalid EEPROM image size %d (expected %d)" %\
  124. (len(image), eepromBytes))
  125. self.__enterPM()
  126. self.progressMeterInit("Writing EEPROM", self.eepromPages)
  127. for page in range(0, self.eepromPages):
  128. self.progressMeter(page)
  129. for byte in range(0, self.eepromPageSize):
  130. self.__loadCommand(self.CMD_WRITEEEPROM)
  131. addr = (page * self.eepromPageSize) + byte
  132. self.__loadAddr(addr)
  133. self.__loadDataLow(image[addr])
  134. self.__pulsePAGEL()
  135. self.__setBS1(0)
  136. self.__pulseWR()
  137. self.__waitForRDY()
  138. self.progressMeterFinish()
  139. def readFuse(self):
  140. self.__enterPM()
  141. self.progressMeterInit("Reading Fuse bits", 0)
  142. (fuse, lock) = self.__readFuseAndLockBits()
  143. self.progressMeterFinish()
  144. return fuse
  145. def writeFuse(self, image):
  146. if len(image) != self.fuseBytes:
  147. self.throwError("Invalid Fuses image size %d (expected %d)" %\
  148. (len(image), self.fuseBytes))
  149. self.__enterPM()
  150. self.progressMeterInit("Writing Fuse bits", 0)
  151. self.__loadCommand(self.CMD_WRITEFUSE)
  152. self.__setBS2(0)
  153. self.__loadDataLow(byte2int(image[0]))
  154. self.__setBS1(0)
  155. self.__pulseWR()
  156. self.__waitForRDY()
  157. self.__loadCommand(self.CMD_WRITEFUSE)
  158. self.__setBS2(0)
  159. self.__loadDataLow(byte2int(image[1]))
  160. self.__setBS1(1)
  161. self.__pulseWR()
  162. self.__waitForRDY()
  163. if len(image) >= 3:
  164. self.__loadCommand(self.CMD_WRITEFUSE)
  165. self.__setBS2(1)
  166. self.__loadDataLow(byte2int(image[2]))
  167. self.__setBS1(0)
  168. self.__pulseWR()
  169. self.__waitForRDY()
  170. self.__setBS1(0)
  171. self.__setBS2(0)
  172. self.progressMeterFinish()
  173. def readLockbits(self):
  174. self.__enterPM()
  175. self.progressMeterInit("Reading lock bits", 0)
  176. (fuses, lockbits) = self.__readFuseAndLockBits()
  177. self.progressMeterFinish()
  178. return lockbits
  179. def writeLockbits(self, image):
  180. if len(image) != 1:
  181. self.throwError("Invalid lock-bits image size %d (expected %d)" %\
  182. (len(image), 1))
  183. self.__enterPM()
  184. self.progressMeterInit("Writing lock bits", 0)
  185. self.__loadCommand(self.CMD_WRITELOCK)
  186. self.__loadDataLow(byte2int(image[0]))
  187. self.__pulseWR()
  188. self.__waitForRDY()
  189. self.progressMeterFinish()
  190. def __readSigAndCalib(self):
  191. """Reads the signature and calibration bytes and returns them.
  192. This function expects a DUT present and pins initialized."""
  193. signature = b""
  194. calibration = b""
  195. for addr in range(0, 3):
  196. self.__loadCommand(self.CMD_READSIG)
  197. self.__loadAddr(addr)
  198. self.__readWordToStatusReg()
  199. data = self.top.cmdReadBufferReg()
  200. if addr == 0:
  201. calibration += int2byte(data[1])
  202. signature += int2byte(data[0])
  203. return (signature, calibration)
  204. def __readFuseAndLockBits(self):
  205. """Reads the Fuse and Lock bits and returns them.
  206. This function expects a DUT present and pins initialized."""
  207. self.__loadCommand(self.CMD_READFUSELOCK)
  208. self.__setBS2(0)
  209. self.__readWordToStatusReg()
  210. self.__setBS2(1)
  211. self.__readWordToStatusReg()
  212. self.__setBS2(0)
  213. data = self.top.cmdReadBufferReg()
  214. if self.fuseBytes == 2:
  215. # fuseLow, fuseHigh
  216. fuses = int2byte(data[0]) + int2byte(data[3])
  217. elif self.fuseBytes == 3:
  218. # fuseLow, fuseHigh, fuseExt
  219. fuses = int2byte(data[0]) + int2byte(data[3]) + int2byte(data[2])
  220. else:
  221. assert(0)
  222. lock = int2byte(data[1])
  223. return (fuses, lock)
  224. def __enterPM(self):
  225. "Enter HV programming mode."
  226. self.applyVPP(False)
  227. self.applyVCC(False)
  228. self.applyGND(True)
  229. self.top.cmdSetVPPVoltage(0)
  230. self.top.cmdSetVPPVoltage(12)
  231. self.top.cmdSetVCCVoltage(5)
  232. self.__setVoltageControl(VPP_en=1, VPP=0, VCC_en=1, VCC=0)
  233. self.__setXA0(0)
  234. self.__setXA1(0)
  235. self.__setBS1(0)
  236. self.__setPAGEL(0)
  237. self.__setWR(0)
  238. self.top.hostDelay(0.1)
  239. self.applyVCC(True)
  240. self.__setVoltageControl(VPP_en=1, VPP=0, VCC_en=1, VCC=1)
  241. self.top.hostDelay(0.1)
  242. self.__setOE(0)
  243. self.__setWR(1)
  244. self.__setXTAL1(0)
  245. self.__setXA0(0)
  246. self.__setXA1(0)
  247. self.__setBS1(0)
  248. self.__setBS2(0)
  249. self.__setPAGEL(0)
  250. self.__pulseXTAL1(10)
  251. self.top.flushCommands()
  252. self.__setVoltageControl(VPP_en=0, VPP=0, VCC_en=1, VCC=1)
  253. self.applyVPP(True)
  254. self.__setOE(1)
  255. (signature, calibration) = self.__readSigAndCalib()
  256. if signature != self.signature:
  257. msg = "Unexpected device signature. " +\
  258. "Want %02X%02X%02X, but got %02X%02X%02X" % \
  259. (byte2int(self.signature[0]), byte2int(self.signature[1]),
  260. byte2int(self.signature[2]),
  261. byte2int(signature[0]), byte2int(signature[1]),
  262. byte2int(signature[2]))
  263. if self.top.getForceLevel() >= 1:
  264. self.printWarning(msg)
  265. else:
  266. self.throwError(msg)
  267. def __readWordToStatusReg(self):
  268. """Read a data word from the DUT into the status register."""
  269. self.__setBS1(0)
  270. self.__setOE(0)
  271. self.top.cmdFPGARead(0x10)
  272. self.__setBS1(1)
  273. self.top.cmdFPGARead(0x10)
  274. self.__setOE(1)
  275. def __readLowByteToStatusReg(self):
  276. """Read the low data byte from the DUT into the status register."""
  277. self.__setBS1(0)
  278. self.__setOE(0)
  279. self.top.cmdFPGARead(0x10)
  280. self.__setOE(1)
  281. def __readHighByteToStatusReg(self):
  282. """Read the high data byte from the DUT into the status register."""
  283. self.__setBS1(1)
  284. self.__setOE(0)
  285. self.top.cmdFPGARead(0x10)
  286. self.__setOE(1)
  287. def __loadData(self, data):
  288. """Load a data word."""
  289. self.__loadDataLow(data)
  290. self.__loadDataHigh(data >> 8)
  291. def __loadDataLow(self, dataLow):
  292. """Load the low data byte."""
  293. self.__setBS1(0)
  294. self.__setXA0(1)
  295. self.__setXA1(0)
  296. self.top.cmdFPGAWrite(0x10, dataLow & 0xFF)
  297. self.__pulseXTAL1()
  298. def __loadDataHigh(self, dataHigh):
  299. """Load the high data byte."""
  300. self.__setBS1(1)
  301. self.__setXA0(1)
  302. self.__setXA1(0)
  303. self.top.cmdFPGAWrite(0x10, dataHigh & 0xFF)
  304. self.__pulseXTAL1()
  305. def __loadAddr(self, addr):
  306. """Load an address word."""
  307. self.__loadAddrLow(addr)
  308. self.__loadAddrHigh(addr >> 8)
  309. def __loadAddrLow(self, addrLow):
  310. """Load the low address byte."""
  311. self.__setBS1(0)
  312. self.__setXA0(0)
  313. self.__setXA1(0)
  314. self.top.cmdFPGAWrite(0x10, addrLow & 0xFF)
  315. self.__pulseXTAL1()
  316. def __loadAddrHigh(self, addrHigh):
  317. """Load the high address byte."""
  318. self.__setBS1(1)
  319. self.__setXA0(0)
  320. self.__setXA1(0)
  321. self.top.cmdFPGAWrite(0x10, addrHigh & 0xFF)
  322. self.__pulseXTAL1()
  323. def __loadCommand(self, command):
  324. """Load a command into the device."""
  325. # self.top.queueCommand(b"\x34")
  326. self.__setBS1(0)
  327. # self.top.queueCommand(b"\x34")
  328. self.__setXA0(0)
  329. self.__setXA1(1)
  330. self.top.cmdFPGAWrite(0x10, command)
  331. self.__pulseXTAL1()
  332. def __waitForRDY(self):
  333. """Wait for the RDY pin to go high."""
  334. self.top.hostDelay(0.01)
  335. for i in range(0, 50):
  336. if self.__getRDY():
  337. return
  338. self.top.hostDelay(0.01)
  339. self.throwError("Timeout waiting for READY signal from chip.")
  340. def __getRDY(self):
  341. """Read the state of the RDY/BSY pin."""
  342. return bool(self.__getStatus() & 0x01)
  343. def __getStatus(self):
  344. """Read the programmer status register"""
  345. self.top.cmdFPGARead(0x12)
  346. stat = self.top.cmdReadBufferReg()
  347. return byte2int(stat[0])
  348. def __setOE(self, high):
  349. """Set the OE pin of the DUT"""
  350. value = 0x02
  351. if high:
  352. value |= 0x80
  353. self.top.cmdFPGAWrite(0x12, value)
  354. def __setWR(self, high):
  355. """Set the WR pin of the DUT"""
  356. value = 0x03
  357. if high:
  358. value |= 0x80
  359. self.top.cmdFPGAWrite(0x12, value)
  360. def __pulseWR(self, count=1):
  361. """Do a negative pulse on the WR pin of the DUT"""
  362. while count > 0:
  363. self.__setWR(0)
  364. self.__setWR(1)
  365. count -= 1
  366. def __setBS1(self, high):
  367. """Set the BS1 pin of the DUT"""
  368. value = 0x04
  369. if high:
  370. value |= 0x80
  371. self.top.cmdFPGAWrite(0x12, value)
  372. def __setXA0(self, high):
  373. """Set the XA0 pin of the DUT"""
  374. value = 0x05
  375. if high:
  376. value |= 0x80
  377. self.top.cmdFPGAWrite(0x12, value)
  378. def __setXA1(self, high):
  379. """Set the XA1 pin of the DUT"""
  380. value = 0x06
  381. if high:
  382. value |= 0x80
  383. self.top.cmdFPGAWrite(0x12, value)
  384. def __setXTAL1(self, high):
  385. """Set the XTAL1 pin of the DUT"""
  386. value = 0x07
  387. if high:
  388. value |= 0x80
  389. self.top.cmdFPGAWrite(0x12, value)
  390. def __pulseXTAL1(self, count=1):
  391. """Do a positive pulse on the XTAL1 pin of the DUT"""
  392. while count > 0:
  393. self.__setXTAL1(1)
  394. self.__setXTAL1(0)
  395. count -= 1
  396. def __setPAGEL(self, high):
  397. """Set the PAGEL pin of the DUT"""
  398. value = 0x09
  399. if high:
  400. value |= 0x80
  401. self.top.cmdFPGAWrite(0x12, value)
  402. def __pulsePAGEL(self, count=1):
  403. """Do a positive pulse on the PAGEL pin of the DUT"""
  404. while count > 0:
  405. self.__setPAGEL(1)
  406. self.__setPAGEL(0)
  407. count -= 1
  408. def __setBS2(self, high):
  409. """Set the BS2 pin of the DUT"""
  410. value = 0x0A
  411. if high:
  412. value |= 0x80
  413. self.top.cmdFPGAWrite(0x12, value)
  414. def __setVoltageControl(self, VPP_en, VPP, VCC_en, VCC):
  415. value = 0
  416. if VPP_en:
  417. value |= 0x01
  418. if VPP:
  419. value |= 0x02
  420. if VCC_en:
  421. value |= 0x04
  422. if VCC:
  423. value |= 0x08
  424. self.top.cmdFPGAWrite(0x11, value)