__init__.py 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. """
  2. MicroPython driver for SD cards using SPI bus.
  3. Requires an SPI bus and a CS pin. Provides readblocks and writeblocks
  4. methods so the device can be mounted as a filesystem.
  5. Example usage on pyboard:
  6. import pyb, sdcard, os
  7. sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5)
  8. pyb.mount(sd, '/sd2')
  9. os.listdir('/')
  10. Example usage on ESP8266:
  11. import machine, sdcard, os
  12. sd = sdcard.SDCard(machine.SPI(1), machine.Pin(15))
  13. os.mount(sd, '/sd')
  14. os.listdir('/')
  15. """
  16. from micropython import const
  17. import time
  18. _CMD_TIMEOUT = const(100)
  19. _R1_IDLE_STATE = const(1 << 0)
  20. # R1_ERASE_RESET = const(1 << 1)
  21. _R1_ILLEGAL_COMMAND = const(1 << 2)
  22. # R1_COM_CRC_ERROR = const(1 << 3)
  23. # R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
  24. # R1_ADDRESS_ERROR = const(1 << 5)
  25. # R1_PARAMETER_ERROR = const(1 << 6)
  26. _TOKEN_CMD25 = const(0xFC)
  27. _TOKEN_STOP_TRAN = const(0xFD)
  28. _TOKEN_DATA = const(0xFE)
  29. class SDCard:
  30. def __init__(self, spi, cs, baudrate=1320000):
  31. self.spi = spi
  32. self.cs = cs
  33. self.cmdbuf = bytearray(6)
  34. self.dummybuf = bytearray(512)
  35. self.tokenbuf = bytearray(1)
  36. for i in range(512):
  37. self.dummybuf[i] = 0xFF
  38. self.dummybuf_memoryview = memoryview(self.dummybuf)
  39. # initialise the card
  40. self.init_card(baudrate)
  41. def init_spi(self, baudrate):
  42. try:
  43. master = self.spi.MASTER
  44. except AttributeError:
  45. # on ESP8266
  46. self.spi.init(baudrate=baudrate, phase=0, polarity=0)
  47. else:
  48. # on pyboard
  49. self.spi.init(master, baudrate=baudrate, phase=0, polarity=0)
  50. def init_card(self, baudrate):
  51. # init CS pin
  52. self.cs.init(self.cs.OUT, value=1)
  53. # init SPI bus; use low data rate for initialisation
  54. self.init_spi(100000)
  55. # clock card at least 100 cycles with cs high
  56. for i in range(16):
  57. self.spi.write(b"\xff")
  58. # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
  59. for _ in range(5):
  60. if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE:
  61. break
  62. else:
  63. raise OSError("no SD card")
  64. # CMD8: determine card version
  65. r = self.cmd(8, 0x01AA, 0x87, 4)
  66. if r == _R1_IDLE_STATE:
  67. self.init_card_v2()
  68. elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
  69. self.init_card_v1()
  70. else:
  71. raise OSError("couldn't determine SD card version")
  72. # get the number of sectors
  73. # CMD9: response R2 (R1 byte + 16-byte block read)
  74. if self.cmd(9, 0, 0, 0, False) != 0:
  75. raise OSError("no response from SD card")
  76. csd = bytearray(16)
  77. self.readinto(csd)
  78. if csd[0] & 0xC0 == 0x40: # CSD version 2.0
  79. self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024
  80. elif csd[0] & 0xC0 == 0x00: # CSD version 1.0 (old, <=2GB)
  81. c_size = (csd[6] & 0b11) << 10 | csd[7] << 2 | csd[8] >> 6
  82. c_size_mult = (csd[9] & 0b11) << 1 | csd[10] >> 7
  83. read_bl_len = csd[5] & 0b1111
  84. capacity = (c_size + 1) * (2 ** (c_size_mult + 2)) * (2**read_bl_len)
  85. self.sectors = capacity // 512
  86. else:
  87. raise OSError("SD card CSD format not supported")
  88. # print('sectors', self.sectors)
  89. # CMD16: set block length to 512 bytes
  90. if self.cmd(16, 512, 0) != 0:
  91. raise OSError("can't set 512 block size")
  92. # set to high data rate now that it's initialised
  93. self.init_spi(baudrate)
  94. def init_card_v1(self):
  95. for i in range(_CMD_TIMEOUT):
  96. time.sleep_ms(50)
  97. self.cmd(55, 0, 0)
  98. if self.cmd(41, 0, 0) == 0:
  99. # SDSC card, uses byte addressing in read/write/erase commands
  100. self.cdv = 512
  101. # print("[SDCard] v1 card")
  102. return
  103. raise OSError("timeout waiting for v1 card")
  104. def init_card_v2(self):
  105. for i in range(_CMD_TIMEOUT):
  106. time.sleep_ms(50)
  107. self.cmd(58, 0, 0, 4)
  108. self.cmd(55, 0, 0)
  109. if self.cmd(41, 0x40000000, 0) == 0:
  110. self.cmd(58, 0, 0, -4) # 4-byte response, negative means keep the first byte
  111. ocr = self.tokenbuf[0] # get first byte of response, which is OCR
  112. if not ocr & 0x40:
  113. # SDSC card, uses byte addressing in read/write/erase commands
  114. self.cdv = 512
  115. else:
  116. # SDHC/SDXC card, uses block addressing in read/write/erase commands
  117. self.cdv = 1
  118. # print("[SDCard] v2 card")
  119. return
  120. raise OSError("timeout waiting for v2 card")
  121. def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False):
  122. self.cs(0)
  123. # create and send the command
  124. buf = self.cmdbuf
  125. buf[0] = 0x40 | cmd
  126. buf[1] = arg >> 24
  127. buf[2] = arg >> 16
  128. buf[3] = arg >> 8
  129. buf[4] = arg
  130. buf[5] = crc
  131. self.spi.write(buf)
  132. if skip1:
  133. self.spi.readinto(self.tokenbuf, 0xFF)
  134. # wait for the response (response[7] == 0)
  135. for i in range(_CMD_TIMEOUT):
  136. self.spi.readinto(self.tokenbuf, 0xFF)
  137. response = self.tokenbuf[0]
  138. if not (response & 0x80):
  139. # this could be a big-endian integer that we are getting here
  140. # if final<0 then store the first byte to tokenbuf and discard the rest
  141. if final < 0:
  142. self.spi.readinto(self.tokenbuf, 0xFF)
  143. final = -1 - final
  144. for j in range(final):
  145. self.spi.write(b"\xff")
  146. if release:
  147. self.cs(1)
  148. self.spi.write(b"\xff")
  149. return response
  150. # timeout
  151. self.cs(1)
  152. self.spi.write(b"\xff")
  153. return -1
  154. def readinto(self, buf):
  155. self.cs(0)
  156. # read until start byte (0xff)
  157. for i in range(_CMD_TIMEOUT):
  158. self.spi.readinto(self.tokenbuf, 0xFF)
  159. if self.tokenbuf[0] == _TOKEN_DATA:
  160. break
  161. time.sleep_ms(1)
  162. else:
  163. self.cs(1)
  164. raise OSError("timeout waiting for response")
  165. # read data
  166. mv = self.dummybuf_memoryview
  167. if len(buf) != len(mv):
  168. mv = mv[: len(buf)]
  169. self.spi.write_readinto(mv, buf)
  170. # read checksum
  171. self.spi.write(b"\xff")
  172. self.spi.write(b"\xff")
  173. self.cs(1)
  174. self.spi.write(b"\xff")
  175. def write(self, token, buf):
  176. self.cs(0)
  177. # send: start of block, data, checksum
  178. self.spi.read(1, token)
  179. self.spi.write(buf)
  180. self.spi.write(b"\xff")
  181. self.spi.write(b"\xff")
  182. # check the response
  183. if (self.spi.read(1, 0xFF)[0] & 0x1F) != 0x05:
  184. self.cs(1)
  185. self.spi.write(b"\xff")
  186. return
  187. # wait for write to finish
  188. while self.spi.read(1, 0xFF)[0] == 0:
  189. pass
  190. self.cs(1)
  191. self.spi.write(b"\xff")
  192. def write_token(self, token):
  193. self.cs(0)
  194. self.spi.read(1, token)
  195. self.spi.write(b"\xff")
  196. # wait for write to finish
  197. while self.spi.read(1, 0xFF)[0] == 0x00:
  198. pass
  199. self.cs(1)
  200. self.spi.write(b"\xff")
  201. def readblocks(self, block_num, buf):
  202. # workaround for shared bus, required for (at least) some Kingston
  203. # devices, ensure MOSI is high before starting transaction
  204. self.spi.write(b"\xff")
  205. nblocks = len(buf) // 512
  206. assert nblocks and not len(buf) % 512, "Buffer length is invalid"
  207. if nblocks == 1:
  208. # CMD17: set read address for single block
  209. if self.cmd(17, block_num * self.cdv, 0, release=False) != 0:
  210. # release the card
  211. self.cs(1)
  212. raise OSError(5) # EIO
  213. # receive the data and release card
  214. self.readinto(buf)
  215. else:
  216. # CMD18: set read address for multiple blocks
  217. if self.cmd(18, block_num * self.cdv, 0, release=False) != 0:
  218. # release the card
  219. self.cs(1)
  220. raise OSError(5) # EIO
  221. offset = 0
  222. mv = memoryview(buf)
  223. while nblocks:
  224. # receive the data and release card
  225. self.readinto(mv[offset : offset + 512])
  226. offset += 512
  227. nblocks -= 1
  228. if self.cmd(12, 0, 0xFF, skip1=True):
  229. raise OSError(5) # EIO
  230. def writeblocks(self, block_num, buf):
  231. # workaround for shared bus, required for (at least) some Kingston
  232. # devices, ensure MOSI is high before starting transaction
  233. self.spi.write(b"\xff")
  234. nblocks, err = divmod(len(buf), 512)
  235. assert nblocks and not err, "Buffer length is invalid"
  236. if nblocks == 1:
  237. # CMD24: set write address for single block
  238. if self.cmd(24, block_num * self.cdv, 0) != 0:
  239. raise OSError(5) # EIO
  240. # send the data
  241. self.write(_TOKEN_DATA, buf)
  242. else:
  243. # CMD25: set write address for first block
  244. if self.cmd(25, block_num * self.cdv, 0) != 0:
  245. raise OSError(5) # EIO
  246. # send the data
  247. offset = 0
  248. mv = memoryview(buf)
  249. while nblocks:
  250. self.write(_TOKEN_CMD25, mv[offset : offset + 512])
  251. offset += 512
  252. nblocks -= 1
  253. self.write_token(_TOKEN_STOP_TRAN)
  254. def ioctl(self, op, arg):
  255. if op == 4: # get number of blocks
  256. return self.sectors
  257. if op == 5: # get block size in bytes
  258. return 512