FLASHROM.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # COPYRIGHT: Openmoko Inc. 2009
  4. # LICENSE: GPL Version 3 or later
  5. # DESCRIPTION: Simple FLASH programmer
  6. # AUTHOR: Christopher Hall <hsw@openmoko.com>
  7. import sys
  8. import time
  9. import Dump
  10. def msg(s):
  11. sys.stdout.write(s)
  12. sys.stdout.flush()
  13. def tty_msg(s):
  14. if sys.stdout.isatty():
  15. sys.stdout.write(s)
  16. sys.stdout.flush()
  17. spin_count = 0
  18. def spin_reset():
  19. global spin_count
  20. spin_count = 0
  21. def spin():
  22. global spin_count
  23. if 1 == spin_count:
  24. tty_msg('\x08-')
  25. spin_count = 2
  26. elif 2 == spin_count:
  27. tty_msg('\x08\\')
  28. spin_count = 3
  29. elif 3 == spin_count:
  30. tty_msg('\x08|')
  31. spin_count = 0
  32. else:
  33. tty_msg('/')
  34. spin_count = 1
  35. class FLASHROM:
  36. def __init__(self, name = 'FLASH', program_block_size = 128, verify_block_size = 128):
  37. self.name = name
  38. self.program_block_size = program_block_size
  39. self. verify_block_size = verify_block_size
  40. self.erased = set()
  41. def program(self, buffer, offset, erase = True):
  42. length = len(buffer)
  43. pre_bytes = (self.program_block_size - offset) % self.program_block_size
  44. block_bytes = length - pre_bytes
  45. post_bytes = block_bytes % self.program_block_size
  46. blocks = block_bytes / self.program_block_size
  47. #msg('pre = %d bytes\nblocks = %d * %d bytes\npost = %d bytes\n' % (pre_bytes, blocks, self.program_block_size, post_bytes))
  48. self.set_block_protection()
  49. # erase all 4k blocks we will need
  50. first_block = offset >> 12
  51. last_block = (offset + length) >> 12
  52. if erase:
  53. for block in range(first_block, last_block + 1):
  54. self.write_enable(True)
  55. self.erase_block(block)
  56. msg('%s: write %d bytes @0x%x ' % (self.name, length, offset))
  57. spin_reset()
  58. index = 0
  59. rc = self.write_block(buffer[0:pre_bytes], offset)
  60. if rc:
  61. spin()
  62. else:
  63. spin_reset()
  64. msg('F')
  65. index += pre_bytes
  66. offset += pre_bytes
  67. if rc:
  68. for b in range(0, blocks):
  69. rc = self.write_block(buffer[index:index + self.program_block_size], offset)
  70. if rc:
  71. spin()
  72. else:
  73. spin_reset()
  74. msg('F')
  75. break
  76. index += self.program_block_size
  77. offset += self.program_block_size
  78. if rc:
  79. rc = self.write_block(buffer[index:], offset)
  80. if rc:
  81. spin()
  82. else:
  83. spin_reset()
  84. msg('F')
  85. self.wait_ready()
  86. self.write_enable(False)
  87. msg('\n')
  88. return rc
  89. def verify(self, buffer, offset):
  90. length = len(buffer)
  91. msg('%s: verifying %d bytes @0x%x ' % (self.name, length, offset))
  92. verify_buffer = ''
  93. a = 0
  94. spin_reset()
  95. while a < length:
  96. if (length - a) < self.verify_block_size:
  97. read_length = length - a
  98. else:
  99. read_length = self.verify_block_size
  100. verify_buffer += self.read_block(a + offset, read_length)
  101. spin()
  102. if buffer[a:a + read_length] != verify_buffer[a:a + read_length]:
  103. spin_reset()
  104. msg('\n')
  105. msg('%s: verify failed @0x%x, length = %d\n' % (self.name, a, read_length))
  106. msg('Read[expected]:')
  107. Dump.hexcmp(verify_buffer[a:a + read_length], buffer[a:a + read_length])
  108. msg('\n')
  109. return False
  110. a += read_length
  111. msg('\n')
  112. return True
  113. # Child class must override some of these
  114. # at least read/write/erase block functions must be given
  115. def write_enable(self, enable):
  116. pass
  117. def wait_ready(self):
  118. pass
  119. def erase_block(self, block):
  120. assert True, 'Virtual %s called' % __name__
  121. def set_block_protection(self):
  122. pass
  123. def write_block(self, buffer, address):
  124. assert True, 'Virtual %s called' % __name__
  125. def read_block(self, address, read_length):
  126. assert True, 'Virtual %s called' % __name__
  127. class PM25LV512(FLASHROM):
  128. def __init__(self, spi, name = 'PM25LV512', program_block_size = 256, verify_block_size = 256):
  129. FLASHROM.__init__(self, name, program_block_size, verify_block_size)
  130. self.spi = spi
  131. def write_enable(self, enable):
  132. if enable:
  133. e = 0x06
  134. else:
  135. e = 0x04
  136. self.spi.command(e)
  137. def wait_ready(self):
  138. status = 0x01
  139. while 0x01 == (status & 0x01):
  140. status = ord(self.spi.transact(0x05, 1, 1)[0])
  141. def erase_block(self, block):
  142. a = block << 12
  143. block &= (1 << 12) - 1
  144. if block in self.erased:
  145. return
  146. msg('erase 4k sector @0x%08x\n' % a)
  147. self.write_enable(True)
  148. self.wait_ready()
  149. self.spi.command([0xd7, (a >> 16), (a >> 8), (a & 0xff)])
  150. self.wait_ready()
  151. self.erased.add(block)
  152. def set_block_protection(self):
  153. self.spi.command([0xf1, 0x00])
  154. self.spi.command([0x01, 0x02])
  155. def write_block(self, buffer, address):
  156. if 0 == len(buffer):
  157. return True
  158. self.wait_ready()
  159. self.write_enable(True)
  160. self.spi.command([0x02, (address >> 16), (address >> 8), address, buffer])
  161. return True
  162. def read_block(self, address, read_length):
  163. return self.spi.transact([0x03, (address >> 16), (address >> 8), address], 1, read_length)
  164. class EN25F05(FLASHROM):
  165. def __init__(self, spi, name = 'EN25F05', program_block_size = 256, verify_block_size = 256):
  166. FLASHROM.__init__(self, name, program_block_size, verify_block_size)
  167. self.spi = spi
  168. def write_enable(self, enable):
  169. if enable:
  170. e = 0x06
  171. else:
  172. e = 0x04
  173. self.spi.command(e)
  174. def wait_ready(self):
  175. status = 0x01
  176. while 0x01 == (status & 0x01):
  177. status = ord(self.spi.transact(0x05, 1, 1)[0])
  178. def erase_block(self, block):
  179. a = block << 12
  180. block &= (1 << 12) - 1
  181. if block in self.erased:
  182. return
  183. msg('erase 4k sector @0x%08x\n' % a)
  184. self.write_enable(True)
  185. self.wait_ready()
  186. self.spi.command([0x20, (a >> 16), (a >> 8), (a & 0xff)])
  187. self.wait_ready()
  188. self.erased.add(block)
  189. def set_block_protection(self):
  190. self.spi.command([0x01, 0x8c])
  191. def write_block(self, buffer, address):
  192. if 0 == len(buffer):
  193. return True
  194. self.wait_ready()
  195. self.write_enable(True)
  196. self.spi.command([0x02, (address >> 16), (address >> 8), address, buffer])
  197. return True
  198. def read_block(self, address, read_length):
  199. return self.spi.transact([0x03, (address >> 16), (address >> 8), address], 0, read_length)