ePaper display driven by a Raspberry Pi Pico
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

308 lines
9.8 KiB

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