44Requires an SPI bus and a CS pin. Provides readblocks and writeblocks
55methods so the device can be mounted as a filesystem.
66
7- Example usage:
7+ Example usage on pyboard :
88
99 import pyb, sdcard, os
1010 sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5)
1111 pyb.mount(sd, '/sd2')
1212 os.listdir('/')
1313
14+ Example usage on ESP8266:
15+
16+ import machine, sdcard, os
17+ sd = sdcard.SDCard(machine.SPI(0), machine.Pin(15))
18+ os.umount()
19+ os.VfsFat(sd, "")
20+ os.listdir()
21+
1422"""
1523
16- import pyb
24+ import time
1725
18- class SDCard :
19- CMD_TIMEOUT = const (100 )
20-
21- R1_IDLE_STATE = const (1 << 0 )
22- #R1_ERASE_RESET = const(1 << 1)
23- R1_ILLEGAL_COMMAND = const (1 << 2 )
24- #R1_COM_CRC_ERROR = const(1 << 3)
25- #R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
26- #R1_ADDRESS_ERROR = const(1 << 5)
27- #R1_PARAMETER_ERROR = const(1 << 6)
28- TOKEN_CMD25 = const (0xfc )
29- TOKEN_STOP_TRAN = const (0xfd )
30- TOKEN_DATA = const (0xfe )
3126
27+ _CMD_TIMEOUT = const (100 )
28+
29+ _R1_IDLE_STATE = const (1 << 0 )
30+ #R1_ERASE_RESET = const(1 << 1)
31+ _R1_ILLEGAL_COMMAND = const (1 << 2 )
32+ #R1_COM_CRC_ERROR = const(1 << 3)
33+ #R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
34+ #R1_ADDRESS_ERROR = const(1 << 5)
35+ #R1_PARAMETER_ERROR = const(1 << 6)
36+ _TOKEN_CMD25 = const (0xfc )
37+ _TOKEN_STOP_TRAN = const (0xfd )
38+ _TOKEN_DATA = const (0xfe )
39+
40+
41+ class SDCard :
3242 def __init__ (self , spi , cs ):
3343 self .spi = spi
3444 self .cs = cs
@@ -42,30 +52,39 @@ def __init__(self, spi, cs):
4252 # initialise the card
4353 self .init_card ()
4454
55+ def init_spi (self , baudrate ):
56+ try :
57+ master = self .spi .MASTER
58+ except AttributeError :
59+ # on ESP8266
60+ self .spi .init (baudrate = baudrate , phase = 0 , polarity = 0 )
61+ else :
62+ # on pyboard
63+ self .spi .init (master , baudrate = baudrate , phase = 0 , polarity = 0 )
64+
4565 def init_card (self ):
4666 # init CS pin
47- self .cs .high ()
48- self .cs .init (self .cs .OUT_PP )
67+ self .cs .init (self .cs .OUT , value = 1 )
4968
5069 # init SPI bus; use low data rate for initialisation
51- self .spi . init ( self . spi . MASTER , baudrate = 100000 , phase = 0 , polarity = 0 )
70+ self .init_spi ( 100000 )
5271
5372 # clock card at least 100 cycles with cs high
5473 for i in range (16 ):
55- self .spi .send ( 0xff )
74+ self .spi .write ( b' \xff ' )
5675
57- # CMD0: init card; should return R1_IDLE_STATE (allow 5 attempts)
76+ # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
5877 for _ in range (5 ):
59- if self .cmd (0 , 0 , 0x95 ) == R1_IDLE_STATE :
78+ if self .cmd (0 , 0 , 0x95 ) == _R1_IDLE_STATE :
6079 break
6180 else :
6281 raise OSError ("no SD card" )
6382
6483 # CMD8: determine card version
6584 r = self .cmd (8 , 0x01aa , 0x87 , 4 )
66- if r == R1_IDLE_STATE :
85+ if r == _R1_IDLE_STATE :
6786 self .init_card_v2 ()
68- elif r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND ):
87+ elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND ):
6988 self .init_card_v1 ()
7089 else :
7190 raise OSError ("couldn't determine SD card version" )
@@ -86,10 +105,10 @@ def init_card(self):
86105 raise OSError ("can't set 512 block size" )
87106
88107 # set to high data rate now that it's initialised
89- self .spi . init ( self . spi . MASTER , baudrate = 1320000 , phase = 0 , polarity = 0 )
108+ self .init_spi ( 1320000 )
90109
91110 def init_card_v1 (self ):
92- for i in range (CMD_TIMEOUT ):
111+ for i in range (_CMD_TIMEOUT ):
93112 self .cmd (55 , 0 , 0 )
94113 if self .cmd (41 , 0 , 0 ) == 0 :
95114 self .cdv = 512
@@ -98,8 +117,8 @@ def init_card_v1(self):
98117 raise OSError ("timeout waiting for v1 card" )
99118
100119 def init_card_v2 (self ):
101- for i in range (CMD_TIMEOUT ):
102- pyb . delay (50 )
120+ for i in range (_CMD_TIMEOUT ):
121+ time . sleep_ms (50 )
103122 self .cmd (58 , 0 , 0 , 4 )
104123 self .cmd (55 , 0 , 0 )
105124 if self .cmd (41 , 0x40000000 , 0 ) == 0 :
@@ -120,87 +139,87 @@ def cmd(self, cmd, arg, crc, final=0, release=True):
120139 buf [3 ] = arg >> 8
121140 buf [4 ] = arg
122141 buf [5 ] = crc
123- self .spi .send (buf )
142+ self .spi .write (buf )
124143
125144 # wait for the repsonse (response[7] == 0)
126- for i in range (CMD_TIMEOUT ):
127- response = self .spi .send_recv ( 0xff )[0 ]
145+ for i in range (_CMD_TIMEOUT ):
146+ response = self .spi .read ( 1 , 0xff )[0 ]
128147 if not (response & 0x80 ):
129148 # this could be a big-endian integer that we are getting here
130149 for j in range (final ):
131- self .spi .send ( 0xff )
150+ self .spi .write ( b' \xff ' )
132151 if release :
133152 self .cs .high ()
134- self .spi .send ( 0xff )
153+ self .spi .write ( b' \xff ' )
135154 return response
136155
137156 # timeout
138157 self .cs .high ()
139- self .spi .send ( 0xff )
158+ self .spi .write ( b' \xff ' )
140159 return - 1
141160
142161 def cmd_nodata (self , cmd ):
143- self .spi .send (cmd )
144- self .spi .send_recv ( 0xff ) # ignore stuff byte
145- for _ in range (CMD_TIMEOUT ):
146- if self .spi .send_recv ( 0xff )[0 ] == 0xff :
162+ self .spi .write (cmd )
163+ self .spi .read ( 1 , 0xff ) # ignore stuff byte
164+ for _ in range (_CMD_TIMEOUT ):
165+ if self .spi .read ( 1 , 0xff )[0 ] == 0xff :
147166 self .cs .high ()
148- self .spi .send ( 0xff )
167+ self .spi .write ( b' \xff ' )
149168 return 0 # OK
150169 self .cs .high ()
151- self .spi .send ( 0xff )
170+ self .spi .write ( b' \xff ' )
152171 return 1 # timeout
153172
154173 def readinto (self , buf ):
155174 self .cs .low ()
156175
157176 # read until start byte (0xff)
158- while self .spi .send_recv ( 0xff )[0 ] != 0xfe :
177+ while self .spi .read ( 1 , 0xff )[0 ] != 0xfe :
159178 pass
160179
161180 # read data
162181 mv = self .dummybuf_memoryview [:len (buf )]
163- self .spi .send_recv (mv , recv = buf )
182+ self .spi .write_readinto (mv , buf )
164183
165184 # read checksum
166- self .spi .send ( 0xff )
167- self .spi .send ( 0xff )
185+ self .spi .write ( b' \xff ' )
186+ self .spi .write ( b' \xff ' )
168187
169188 self .cs .high ()
170- self .spi .send ( 0xff )
189+ self .spi .write ( b' \xff ' )
171190
172191 def write (self , token , buf ):
173192 self .cs .low ()
174193
175194 # send: start of block, data, checksum
176- self .spi .send ( token )
177- self .spi .send (buf )
178- self .spi .send ( 0xff )
179- self .spi .send ( 0xff )
195+ self .spi .read ( 1 , token )
196+ self .spi .write (buf )
197+ self .spi .write ( b' \xff ' )
198+ self .spi .write ( b' \xff ' )
180199
181200 # check the response
182- if (self .spi .send_recv ( 0xff )[0 ] & 0x1f ) != 0x05 :
201+ if (self .spi .read ( 1 , 0xff )[0 ] & 0x1f ) != 0x05 :
183202 self .cs .high ()
184- self .spi .send ( 0xff )
203+ self .spi .write ( b' \xff ' )
185204 return
186205
187206 # wait for write to finish
188- while self .spi .send_recv ( 0xff )[0 ] == 0 :
207+ while self .spi .read ( 1 , 0xff )[0 ] == 0 :
189208 pass
190209
191210 self .cs .high ()
192- self .spi .send ( 0xff )
211+ self .spi .write ( b' \xff ' )
193212
194213 def write_token (self , token ):
195214 self .cs .low ()
196- self .spi .send ( token )
197- self .spi .send ( 0xff )
215+ self .spi .read ( 1 , token )
216+ self .spi .write ( b' \xff ' )
198217 # wait for write to finish
199- while self .spi .send_recv ( 0xff )[0 ] == 0 :
218+ while self .spi .read ( 1 , 0xff )[0 ] == 0x00 :
200219 pass
201220
202221 self .cs .high ()
203- self .spi .send ( 0xff )
222+ self .spi .write ( b' \xff ' )
204223
205224 def count (self ):
206225 return self .sectors
@@ -224,7 +243,7 @@ def readblocks(self, block_num, buf):
224243 self .readinto (mv [offset : offset + 512 ])
225244 offset += 512
226245 nblocks -= 1
227- return self .cmd_nodata (12 )
246+ return self .cmd_nodata (b' \x0c ' ) # cmd 12
228247 return 0
229248
230249 def writeblocks (self , block_num , buf ):
@@ -236,7 +255,7 @@ def writeblocks(self, block_num, buf):
236255 return 1
237256
238257 # send the data
239- self .write (TOKEN_DATA , buf )
258+ self .write (_TOKEN_DATA , buf )
240259 else :
241260 # CMD25: set write address for first block
242261 if self .cmd (25 , block_num * self .cdv , 0 ) != 0 :
@@ -245,8 +264,8 @@ def writeblocks(self, block_num, buf):
245264 offset = 0
246265 mv = memoryview (buf )
247266 while nblocks :
248- self .write (TOKEN_CMD25 , mv [offset : offset + 512 ])
267+ self .write (_TOKEN_CMD25 , mv [offset : offset + 512 ])
249268 offset += 512
250269 nblocks -= 1
251- self .write_token (TOKEN_STOP_TRAN )
270+ self .write_token (_TOKEN_STOP_TRAN )
252271 return 0
0 commit comments