m24cxxdip8.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. """
  2. # TOP2049 Open Source programming suite
  3. #
  4. # M24C16 I2C based serial EEPROM
  5. #
  6. # Copyright (c) 2011-2017 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_m24cXXdip8_common(Chip):
  24. I2C_BASE_ADDR = 0x50 << 1
  25. I2C_READ = 0x01
  26. I2C_WRITE = 0x00
  27. def __init__(self, eepromSize):
  28. Chip.__init__(self,
  29. chipPackage = "DIP8",
  30. chipPinVCC = 8,
  31. chipPinGND = 4)
  32. self.eepromSize = eepromSize # in bytes
  33. def __chipTurnOn(self):
  34. self.top.cmdSetVCCVoltage(5)
  35. self.top.cmdSetVPPVoltage(5)
  36. self.applyVCC(True)
  37. self.applyVPP(False)
  38. self.applyGND(True)
  39. self.top.cmdEnableZifPullups(True)
  40. self.currentAddrExt = None
  41. self.currentWriteMode = None
  42. def erase(self):
  43. self.writeEEPROM(b"\xFF" * self.eepromSize)
  44. def readEEPROM(self):
  45. self.__chipTurnOn()
  46. image = b""
  47. prevAddr = None
  48. self.progressMeterInit("Reading EEPROM", self.eepromSize)
  49. for addr in range(0, self.eepromSize):
  50. self.progressMeter(addr)
  51. if prevAddr is None or (prevAddr & 0xFF00) != (addr & 0xFF00):
  52. self.__setAddressExtension(addr, writeMode=False)
  53. # Begin sequential random read
  54. self.__runI2C(data=self.I2C_BASE_ADDR | self.currentAddrExt | self.I2C_WRITE,
  55. read=False, do_start=True, do_stop=False)
  56. self.__expectACK()
  57. self.__runI2C(data=addr & 0xFF,
  58. read=False, do_start=False, do_stop=False)
  59. self.__expectACK()
  60. self.__runI2C(data=self.I2C_BASE_ADDR | self.currentAddrExt | self.I2C_READ,
  61. read=False, do_start=True, do_stop=False)
  62. self.__expectACK()
  63. prevAddr = addr
  64. # Sequential random read
  65. if addr >= self.eepromSize - 1:
  66. # Last byte
  67. self.__runI2C(read=True, do_start=False, do_stop=True)
  68. self.__expectNACK()
  69. else:
  70. self.__runI2C(read=True, do_start=False, do_stop=False,
  71. drive_ack=True)
  72. self.__expectACK()
  73. self.__readData()
  74. image += self.top.cmdReadBufferReg(1)
  75. self.progressMeterFinish()
  76. return image
  77. def writeEEPROM(self, image):
  78. if len(image) > self.eepromSize:
  79. self.throwError("Invalid EEPROM image size %d (expected <=%d)" %\
  80. (len(image), self.eepromSize))
  81. self.__chipTurnOn()
  82. self.progressMeterInit("Writing EEPROM", len(image))
  83. prevAddr = None
  84. for addr in range(0, len(image)):
  85. self.progressMeter(addr)
  86. if prevAddr is None or (prevAddr & 0xFFF0) != (addr & 0xFFF0):
  87. self.__setAddressExtension(addr, writeMode=True)
  88. self.__runI2C(data=self.I2C_BASE_ADDR | self.currentAddrExt | self.I2C_WRITE,
  89. read=False, do_start=True, do_stop=False)
  90. self.__expectACK()
  91. self.__runI2C(data=addr & 0xFF,
  92. read=False, do_start=False, do_stop=False)
  93. self.__expectACK()
  94. prevAddr = addr
  95. if (addr & 0xF) == 0xF:
  96. self.__runI2C(data=byte2int(image[addr]),
  97. read=False, do_start=False, do_stop=True)
  98. self.__expectACK()
  99. self.top.cmdDelay(0.005) # Max write time
  100. else:
  101. self.__runI2C(data=byte2int(image[addr]),
  102. read=False, do_start=False, do_stop=False)
  103. self.__expectACK()
  104. self.progressMeterFinish()
  105. def __readData(self):
  106. self.top.cmdFPGARead(0)
  107. def __setData(self, dataByte):
  108. self.top.cmdFPGAWrite(1, dataByte & 0xFF)
  109. def __setAddressExtension(self, address, writeMode):
  110. sizeMask = self.eepromSize - 1
  111. assert(sizeMask & ~0x7FF == 0)
  112. addrExt = ((address & 0x700 & sizeMask) >> 8) << 1
  113. if self.currentWriteMode != writeMode:
  114. E0 = E1 = E2 = 0
  115. E0_en = not (sizeMask & 0x0100)
  116. E1_en = not (sizeMask & 0x0200)
  117. E2_en = not (sizeMask & 0x0400)
  118. WC = not writeMode
  119. self.__setControlPins(E0=E0, E0_en=E0_en,
  120. E1=E1, E1_en=E1_en,
  121. E2=E2, E2_en=E2_en,
  122. WC=WC)
  123. self.currentAddrExt = addrExt
  124. self.currentWriteMode = writeMode
  125. def __runI2C(self, data=None, read=False, do_start=False, do_stop=False, drive_ack=False):
  126. if data is not None:
  127. self.__setData(data)
  128. else:
  129. self.__setData(0)
  130. command = (0x01 if read else 0) |\
  131. (0x02 if do_start else 0) |\
  132. (0x04 if do_stop else 0) |\
  133. (0x08 if drive_ack else 0)
  134. self.top.cmdFPGAWrite(0, command)
  135. self.__busyWait()
  136. def __isBusy(self):
  137. (busy, ack) = self.__getStatusFlags()
  138. return busy
  139. def __busyWait(self):
  140. for i in range(0, 100):
  141. if not self.__isBusy():
  142. return
  143. self.top.hostDelay(0.001)
  144. self.throwError("Timeout in busywait.")
  145. def __getStatusFlags(self):
  146. self.top.cmdFPGARead(1)
  147. stat = self.top.cmdReadBufferReg8()
  148. busy = bool(stat & 0x01)
  149. ack = not bool(stat & 0x02)
  150. self.lastAck = ack
  151. return (busy, ack)
  152. def __expectACK(self):
  153. if not self.lastAck:
  154. self.throwError("Expected I2C ACK, but received NACK")
  155. def __expectNACK(self):
  156. if self.lastAck:
  157. self.throwError("Expected I2C NACK, but received ACK")
  158. def __setControlPins(self, E0, E0_en, E1, E1_en, E2, E2_en, WC):
  159. value = 0
  160. if E0:
  161. value |= (1 << 0)
  162. if E0_en:
  163. value |= (1 << 1)
  164. if E1:
  165. value |= (1 << 2)
  166. if E1_en:
  167. value |= (1 << 3)
  168. if E2:
  169. value |= (1 << 4)
  170. if E2_en:
  171. value |= (1 << 5)
  172. if WC:
  173. value |= (1 << 6)
  174. self.top.cmdFPGAWrite(2, value)
  175. class Chip_m24c01dip8(Chip_m24cXXdip8_common):
  176. def __init__(self):
  177. Chip_m24cXXdip8_common.__init__(self, eepromSize = 1024 * 1 // 8)
  178. class Chip_m24c02dip8(Chip_m24cXXdip8_common):
  179. def __init__(self):
  180. Chip_m24cXXdip8_common.__init__(self, eepromSize = 1024 * 2 // 8)
  181. class Chip_m24c04dip8(Chip_m24cXXdip8_common):
  182. def __init__(self):
  183. Chip_m24cXXdip8_common.__init__(self, eepromSize = 1024 * 4 // 8)
  184. class Chip_m24c08dip8(Chip_m24cXXdip8_common):
  185. def __init__(self):
  186. Chip_m24cXXdip8_common.__init__(self, eepromSize = 1024 * 8 // 8)
  187. class Chip_m24c16dip8(Chip_m24cXXdip8_common):
  188. def __init__(self):
  189. Chip_m24cXXdip8_common.__init__(self, eepromSize = 1024 * 16 // 8)
  190. class ChipDescription_m24cXX(ChipDescription):
  191. def __init__(self, chipImplClass, chipID, description):
  192. ChipDescription.__init__(self,
  193. chipImplClass = chipImplClass,
  194. bitfile = "m24c16dip8",
  195. chipID = chipID,
  196. runtimeID = (0x000B, 0x01),
  197. chipType = ChipDescription.TYPE_EEPROM,
  198. chipVendors = "ST",
  199. description = description,
  200. packages = (
  201. ("DIP8", ""),
  202. ("SO8", "With 1:1 adapter"),
  203. ("TSSOP8", "With 1:1 adapter"),
  204. ),
  205. )
  206. ChipDescription_m24cXX(
  207. Chip_m24c01dip8,
  208. chipID = "m24c01dip8",
  209. description = "M24C01 I2C EEPROM",
  210. )
  211. ChipDescription_m24cXX(
  212. Chip_m24c02dip8,
  213. chipID = "m24c02dip8",
  214. description = "M24C02 I2C EEPROM",
  215. )
  216. ChipDescription_m24cXX(
  217. Chip_m24c04dip8,
  218. chipID = "m24c04dip8",
  219. description = "M24C04 I2C EEPROM",
  220. )
  221. ChipDescription_m24cXX(
  222. Chip_m24c08dip8,
  223. chipID = "m24c08dip8",
  224. description = "M24C08 I2C EEPROM",
  225. )
  226. ChipDescription_m24cXX(
  227. Chip_m24c16dip8,
  228. chipID = "m24c16dip8",
  229. description = "M24C16 I2C EEPROM",
  230. )