FLASHROM.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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):
  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. for block in range(first_block, last_block + 1):
  53. self.write_enable(True)
  54. self.erase_block(block)
  55. msg('%s: write %d bytes @0x%x ' % (self.name, length, offset))
  56. spin_reset()
  57. index = 0
  58. rc = self.write_block(buffer[0:pre_bytes], offset)
  59. if rc:
  60. spin()
  61. else:
  62. spin_reset()
  63. msg('F')
  64. index += pre_bytes
  65. offset += pre_bytes
  66. if rc:
  67. for b in range(0, blocks):
  68. rc = self.write_block(buffer[index:index + self.program_block_size], offset)
  69. if rc:
  70. spin()
  71. else:
  72. spin_reset()
  73. msg('F')
  74. break
  75. index += self.program_block_size
  76. offset += self.program_block_size
  77. if rc:
  78. rc = self.write_block(buffer[index:], offset)
  79. if rc:
  80. spin()
  81. else:
  82. spin_reset()
  83. msg('F')
  84. self.wait_ready()
  85. self.write_enable(False)
  86. msg('\n')
  87. return rc
  88. def verify(self, buffer, offset):
  89. length = len(buffer)
  90. msg('%s: verifying %d bytes @0x%x ' % (self.name, length, offset))
  91. verify_buffer = ''
  92. a = 0
  93. spin_reset()
  94. while a < length:
  95. if (length - a) < self.verify_block_size:
  96. read_length = length - a
  97. else:
  98. read_length = self.verify_block_size
  99. verify_buffer += self.read_block(a + offset, read_length)
  100. spin()
  101. if buffer[a:a + read_length] != verify_buffer[a:a + read_length]:
  102. spin_reset()
  103. msg('\n')
  104. msg('%s: verify failed @0x%x, length = %d\n' % (self.name, a, read_length))
  105. msg('Read[expected]:')
  106. Dump.hexcmp(verify_buffer[a:a + read_length], buffer[a:a + read_length])
  107. msg('\n')
  108. return False
  109. a += read_length
  110. msg('\n')
  111. return True
  112. # Child clas must override some of these
  113. # at least read/write/erase block functions must be given
  114. def write_enable(enable):
  115. pass
  116. def wait_ready(s):
  117. pass
  118. def erase_block(s, block):
  119. assert True, 'Virtual %s called' % __name__
  120. def set_block_protection():
  121. pass
  122. def write_block(self, buffer, offset):
  123. assert True, 'Virtual %s called' % __name__
  124. def read_block(self, address, read_length):
  125. assert True, 'Virtual %s called' % __name__
  126. class PM25LV512(FLASHROM):
  127. def __init__(self, spi, name = 'PM25LV512', program_block_size = 256, verify_block_size = 256):
  128. FLASHROM.__init__(self, name, program_block_size, verify_block_size)
  129. self.spi = spi
  130. def write_enable(self, enable):
  131. if enable:
  132. e = 0x06
  133. else:
  134. e = 0x04
  135. self.spi.command(e)
  136. def wait_ready(self):
  137. status = 0x01
  138. while 0x01 == (status & 0x01):
  139. status = ord(self.spi.transact(0x05, 1, 1)[0])
  140. def erase_block(self, block):
  141. a = block << 12
  142. block &= (1 << 12) - 1
  143. if block in self.erased:
  144. return
  145. msg('erase 4k sector @0x%08x\n' % a)
  146. self.write_enable(True)
  147. self.wait_ready()
  148. self.spi.command([0xd7, (a >> 16), (a >> 8), (a & 0xff)])
  149. self.wait_ready()
  150. self.erased.add(block)
  151. def set_block_protection(self):
  152. self.spi.command([0xf1, 0x00])
  153. self.spi.command([0x01, 0x02])
  154. def write_block(self, buffer, address):
  155. if 0 == len(buffer):
  156. return True
  157. self.wait_ready()
  158. self.write_enable(True)
  159. self.spi.command([0x02, (address >> 16), (address >> 8), address, buffer])
  160. return True
  161. def read_block(self, address, read_length):
  162. return self.spi.transact([0x03, (address >> 16), (address >> 8), address], 1, read_length)
  163. class EN25F05(FLASHROM):
  164. def __init__(self, spi, name = 'EN25F05', program_block_size = 256, verify_block_size = 256):
  165. FLASHROM.__init__(self, name, program_block_size, verify_block_size)
  166. self.spi = spi
  167. def write_enable(self, enable):
  168. if enable:
  169. e = 0x06
  170. else:
  171. e = 0x04
  172. self.spi.command(e)
  173. def wait_ready(self):
  174. status = 0x01
  175. while 0x01 == (status & 0x01):
  176. status = ord(self.spi.transact(0x05, 1, 1)[0])
  177. def erase_block(self, block):
  178. a = block << 12
  179. block &= (1 << 12) - 1
  180. if block in self.erased:
  181. return
  182. msg('erase 4k sector @0x%08x\n' % a)
  183. self.write_enable(True)
  184. self.wait_ready()
  185. self.spi.command([0x20, (a >> 16), (a >> 8), (a & 0xff)])
  186. self.wait_ready()
  187. self.erased.add(block)
  188. def set_block_protection(self):
  189. pass
  190. #self.spi.command([0xf1, 0x00])
  191. #self.spi.command([0x01, 0x02])
  192. def write_block(self, buffer, address):
  193. if 0 == len(buffer):
  194. return True
  195. self.wait_ready()
  196. self.write_enable(True)
  197. self.spi.command([0x02, (address >> 16), (address >> 8), address, buffer])
  198. return True
  199. def read_block(self, address, read_length):
  200. return self.spi.transact([0x03, (address >> 16), (address >> 8), address], 1, read_length)