w29ee011dip32.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. """
  2. # TOP2049 Open Source programming suite
  3. #
  4. # Winbond W29EE011 DIP32
  5. # Winbond W29EE011 PLCC32 (inside 1:1 PLCC32->DIP32 adapter)
  6. #
  7. # Copyright (c) 2010 Michael Buesch <m@bues.ch>
  8. #
  9. # This program is free software; you can redistribute it and/or modify
  10. # it under the terms of the GNU General Public License as published by
  11. # the Free Software Foundation; either version 2 of the License, or
  12. # (at your option) any later version.
  13. #
  14. # This program is distributed in the hope that it will be useful,
  15. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. # GNU General Public License for more details.
  18. #
  19. # You should have received a copy of the GNU General Public License along
  20. # with this program; if not, write to the Free Software Foundation, Inc.,
  21. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  22. """
  23. from libtoprammer.chip import *
  24. class Chip_w29ee011dip32(Chip):
  25. PROGCMD_WRITEBUF = 1 # Write buffer to chip
  26. STAT_BUSY = 0x01 # Programmer is running a command
  27. def __init__(self):
  28. Chip.__init__(self,
  29. chipPackage = "DIP32",
  30. chipPinVCC = 32,
  31. chipPinsVPP = None,
  32. chipPinGND = 16)
  33. def erase(self):
  34. self.applyVCC(True)
  35. self.applyVPP(True)
  36. self.applyGND(True)
  37. commands = (
  38. (0x5555, 0xAA),
  39. (0x2AAA, 0x55),
  40. (0x5555, 0x80),
  41. (0x5555, 0xAA),
  42. (0x2AAA, 0x55),
  43. (0x5555, 0x10),
  44. )
  45. self.progressMeterInit("Erasing chip", 0)
  46. self.__setCEOE(CE=0, OE=1)
  47. self.__resetBufferPointers()
  48. self.__swDataProtect(False)
  49. self.__runCommandSync(self.PROGCMD_WRITEBUF)
  50. self.top.hostDelay(0.05)
  51. self.__resetBufferPointers()
  52. for command in commands:
  53. self.__appendJEDEC(command[0], command[1])
  54. self.__runCommandSync(self.PROGCMD_WRITEBUF)
  55. self.top.hostDelay(0.05)
  56. self.__setCEOE(CE=1, OE=1)
  57. self.progressMeterFinish()
  58. def readEEPROM(self):
  59. self.applyVCC(True)
  60. self.applyVPP(True)
  61. self.applyGND(True)
  62. self.progressMeterInit("Reading EEPROM", 0x20000)
  63. self.__setCEOE(CE=0, OE=0)
  64. image = self.__readRange(0, 0x20000, progress=True)
  65. self.__setCEOE(CE=1, OE=1)
  66. self.progressMeterFinish()
  67. return image
  68. def __readRange(self, baseAddress, size, progress=False):
  69. image = b""
  70. byteCount = 0
  71. prevAddr = baseAddress
  72. self.__loadReadAddrLo(baseAddress)
  73. self.__loadReadAddrMed(baseAddress >> 8)
  74. self.__loadReadAddrHi(baseAddress >> 16)
  75. for offset in range(0, size):
  76. addr = baseAddress + offset
  77. if progress:
  78. self.progressMeter(addr)
  79. if (addr & 0xFF) != (prevAddr & 0xFF):
  80. self.__loadReadAddrLo(addr)
  81. if (addr & 0xFF00) != (prevAddr & 0xFF00):
  82. self.__loadReadAddrMed(addr >> 8)
  83. if (addr & 0xFF0000) != (prevAddr & 0xFF0000):
  84. self.__loadReadAddrHi(addr >> 16)
  85. prevAddr = addr
  86. self.top.cmdFPGARead(0x10)
  87. byteCount += 1
  88. if byteCount == self.top.getBufferRegSize():
  89. image += self.top.cmdReadBufferReg(byteCount)
  90. byteCount = 0
  91. image += self.top.cmdReadBufferReg(byteCount)
  92. return image
  93. def writeEEPROM(self, image):
  94. if len(image) > 0x20000:
  95. self.throwError("Invalid EPROM image size %d (expected <=%d)" %\
  96. (len(image), 0x20000))
  97. self.applyVCC(True)
  98. self.applyVPP(True)
  99. self.applyGND(True)
  100. self.progressMeterInit("Writing EEPROM", len(image))
  101. self.__setCEOE(CE=0, OE=1)
  102. for addr in range(0, len(image), 128):
  103. self.progressMeter(addr)
  104. pagelen = min(128, len(image) - addr)
  105. page = image[addr:addr+pagelen]
  106. self.__writePage(addr, page)
  107. self.__setCEOE(CE=1, OE=1)
  108. self.progressMeterFinish()
  109. def __swDataProtect(self, enable):
  110. if enable:
  111. jedecCommands = (
  112. (0x5555, 0xAA),
  113. (0x2AAA, 0x55),
  114. (0x5555, 0xA0),
  115. )
  116. else:
  117. jedecCommands = (
  118. (0x5555, 0xAA),
  119. (0x2AAA, 0x55),
  120. (0x5555, 0x80),
  121. (0x5555, 0xAA),
  122. (0x2AAA, 0x55),
  123. (0x5555, 0x20),
  124. )
  125. for command in jedecCommands:
  126. self.__appendJEDEC(command[0], command[1])
  127. def __writePage(self, pageAddress, pageData):
  128. for t in range(0, 15):
  129. self.__resetBufferPointers()
  130. self.__swDataProtect(True)
  131. assert(len(pageData) <= 128)
  132. for byte in pageData:
  133. self.__writeBufAppend(byte2int(byte))
  134. self.__loadWriteAddr(pageAddress)
  135. self.__runCommandSync(self.PROGCMD_WRITEBUF)
  136. self.top.hostDelay(0.01)
  137. # Verify
  138. self.__setCEOE(CE=0, OE=0)
  139. verifyImage = self.__readRange(pageAddress, len(pageData))
  140. self.__setCEOE(CE=0, OE=1)
  141. if verifyImage == pageData:
  142. break
  143. self.top.hostDelay(0.1)
  144. else:
  145. self.throwError("Verify error on page write at address 0x%05X" % pageAddress)
  146. def __writeBufAppend(self, byte):
  147. # This also auto-increments the write buffer pointer
  148. self.top.cmdFPGAWrite(0x10, byte & 0xFF)
  149. def __resetBufferPointers(self):
  150. self.top.cmdFPGAWrite(0x13, 0)
  151. def __loadCommand(self, command):
  152. self.top.cmdFPGAWrite(0x12, command & 0xFF)
  153. def __runCommandSync(self, command):
  154. self.__loadCommand(command)
  155. self.__busyWait()
  156. def __loadWriteAddr(self, addr):
  157. self.__loadWriteAddrLo(addr)
  158. self.__loadWriteAddrMed(addr >> 8)
  159. self.__loadWriteAddrHi(addr >> 16)
  160. def __loadWriteAddrLo(self, addrLo):
  161. self.top.cmdFPGAWrite(0x14, addrLo & 0xFF)
  162. def __loadWriteAddrMed(self, addrMed):
  163. self.top.cmdFPGAWrite(0x15, addrMed & 0xFF)
  164. def __loadWriteAddrHi(self, addrHi):
  165. self.top.cmdFPGAWrite(0x16, addrHi & 0xFF)
  166. def __loadReadAddrLo(self, addrLo):
  167. self.top.cmdFPGAWrite(0x17, addrLo & 0xFF)
  168. def __loadReadAddrMed(self, addrMed):
  169. self.top.cmdFPGAWrite(0x18, addrMed & 0xFF)
  170. def __loadReadAddrHi(self, addrHi):
  171. self.top.cmdFPGAWrite(0x19, addrHi & 0xFF)
  172. def __setCEOE(self, CE, OE):
  173. data = 0
  174. if CE:
  175. data |= 0x01
  176. if OE:
  177. data |= 0x02
  178. self.top.cmdFPGAWrite(0x1A, data)
  179. def __appendJEDEC(self, addr, data):
  180. self.__loadJEDECAddrLo(addr)
  181. self.__loadJEDECAddrMed(addr >> 8)
  182. self.__loadJEDECAddrHi(addr >> 16)
  183. self.__loadJEDECData(data)
  184. def __loadJEDECAddrLo(self, addrLo):
  185. self.top.cmdFPGAWrite(0x1B, addrLo & 0xFF)
  186. def __loadJEDECAddrMed(self, addrMed):
  187. self.top.cmdFPGAWrite(0x1C, addrMed & 0xFF)
  188. def __loadJEDECAddrHi(self, addrHi):
  189. self.top.cmdFPGAWrite(0x1D, addrHi & 0xFF)
  190. def __loadJEDECData(self, data):
  191. # This also auto-increments the JEDEC buffer pointer
  192. self.top.cmdFPGAWrite(0x1E, data & 0xFF)
  193. def __getStatusFlags(self):
  194. self.top.cmdFPGARead(0x12)
  195. stat = self.top.cmdReadBufferReg()
  196. return byte2int(stat[0])
  197. def __busy(self):
  198. return bool(self.__getStatusFlags() & self.STAT_BUSY)
  199. def __busyWait(self):
  200. for i in range(0, 100):
  201. if not self.__busy():
  202. return
  203. self.top.hostDelay(0.01)
  204. self.throwError("Timeout in busywait.")
  205. ChipDescription(
  206. Chip_w29ee011dip32,
  207. bitfile = "w29ee011dip32",
  208. runtimeID = (0x0009, 0x01),
  209. chipType = ChipDescription.TYPE_EEPROM,
  210. chipVendors = "Winbond",
  211. description = "W29EE011 EEPROM",
  212. packages = ( ("DIP32", ""), ("PLCC32", "Use 1:1 PLCC32->DIP32 adapter"), ),
  213. broken = True,
  214. )