summaryrefslogtreecommitdiffstatshomepage
path: root/drivers/sdcard/sdcard.py
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/sdcard/sdcard.py')
-rw-r--r--drivers/sdcard/sdcard.py139
1 files changed, 79 insertions, 60 deletions
diff --git a/drivers/sdcard/sdcard.py b/drivers/sdcard/sdcard.py
index fba383ae39..fc7a8af7c5 100644
--- a/drivers/sdcard/sdcard.py
+++ b/drivers/sdcard/sdcard.py
@@ -4,31 +4,41 @@ Micro Python driver for SD cards using SPI bus.
Requires an SPI bus and a CS pin. Provides readblocks and writeblocks
methods so the device can be mounted as a filesystem.
-Example usage:
+Example usage on pyboard:
import pyb, sdcard, os
sd = sdcard.SDCard(pyb.SPI(1), pyb.Pin.board.X5)
pyb.mount(sd, '/sd2')
os.listdir('/')
+Example usage on ESP8266:
+
+ import machine, sdcard, os
+ sd = sdcard.SDCard(machine.SPI(0), machine.Pin(15))
+ os.umount()
+ os.VfsFat(sd, "")
+ os.listdir()
+
"""
-import pyb
+import time
-class SDCard:
- CMD_TIMEOUT = const(100)
-
- R1_IDLE_STATE = const(1 << 0)
- #R1_ERASE_RESET = const(1 << 1)
- R1_ILLEGAL_COMMAND = const(1 << 2)
- #R1_COM_CRC_ERROR = const(1 << 3)
- #R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
- #R1_ADDRESS_ERROR = const(1 << 5)
- #R1_PARAMETER_ERROR = const(1 << 6)
- TOKEN_CMD25 = const(0xfc)
- TOKEN_STOP_TRAN = const(0xfd)
- TOKEN_DATA = const(0xfe)
+_CMD_TIMEOUT = const(100)
+
+_R1_IDLE_STATE = const(1 << 0)
+#R1_ERASE_RESET = const(1 << 1)
+_R1_ILLEGAL_COMMAND = const(1 << 2)
+#R1_COM_CRC_ERROR = const(1 << 3)
+#R1_ERASE_SEQUENCE_ERROR = const(1 << 4)
+#R1_ADDRESS_ERROR = const(1 << 5)
+#R1_PARAMETER_ERROR = const(1 << 6)
+_TOKEN_CMD25 = const(0xfc)
+_TOKEN_STOP_TRAN = const(0xfd)
+_TOKEN_DATA = const(0xfe)
+
+
+class SDCard:
def __init__(self, spi, cs):
self.spi = spi
self.cs = cs
@@ -42,30 +52,39 @@ class SDCard:
# initialise the card
self.init_card()
+ def init_spi(self, baudrate):
+ try:
+ master = self.spi.MASTER
+ except AttributeError:
+ # on ESP8266
+ self.spi.init(baudrate=baudrate, phase=0, polarity=0)
+ else:
+ # on pyboard
+ self.spi.init(master, baudrate=baudrate, phase=0, polarity=0)
+
def init_card(self):
# init CS pin
- self.cs.high()
- self.cs.init(self.cs.OUT_PP)
+ self.cs.init(self.cs.OUT, value=1)
# init SPI bus; use low data rate for initialisation
- self.spi.init(self.spi.MASTER, baudrate=100000, phase=0, polarity=0)
+ self.init_spi(100000)
# clock card at least 100 cycles with cs high
for i in range(16):
- self.spi.send(0xff)
+ self.spi.write(b'\xff')
- # CMD0: init card; should return R1_IDLE_STATE (allow 5 attempts)
+ # CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
for _ in range(5):
- if self.cmd(0, 0, 0x95) == R1_IDLE_STATE:
+ if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE:
break
else:
raise OSError("no SD card")
# CMD8: determine card version
r = self.cmd(8, 0x01aa, 0x87, 4)
- if r == R1_IDLE_STATE:
+ if r == _R1_IDLE_STATE:
self.init_card_v2()
- elif r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND):
+ elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
self.init_card_v1()
else:
raise OSError("couldn't determine SD card version")
@@ -86,10 +105,10 @@ class SDCard:
raise OSError("can't set 512 block size")
# set to high data rate now that it's initialised
- self.spi.init(self.spi.MASTER, baudrate=1320000, phase=0, polarity=0)
+ self.init_spi(1320000)
def init_card_v1(self):
- for i in range(CMD_TIMEOUT):
+ for i in range(_CMD_TIMEOUT):
self.cmd(55, 0, 0)
if self.cmd(41, 0, 0) == 0:
self.cdv = 512
@@ -98,8 +117,8 @@ class SDCard:
raise OSError("timeout waiting for v1 card")
def init_card_v2(self):
- for i in range(CMD_TIMEOUT):
- pyb.delay(50)
+ for i in range(_CMD_TIMEOUT):
+ time.sleep_ms(50)
self.cmd(58, 0, 0, 4)
self.cmd(55, 0, 0)
if self.cmd(41, 0x40000000, 0) == 0:
@@ -120,87 +139,87 @@ class SDCard:
buf[3] = arg >> 8
buf[4] = arg
buf[5] = crc
- self.spi.send(buf)
+ self.spi.write(buf)
# wait for the repsonse (response[7] == 0)
- for i in range(CMD_TIMEOUT):
- response = self.spi.send_recv(0xff)[0]
+ for i in range(_CMD_TIMEOUT):
+ response = self.spi.read(1, 0xff)[0]
if not (response & 0x80):
# this could be a big-endian integer that we are getting here
for j in range(final):
- self.spi.send(0xff)
+ self.spi.write(b'\xff')
if release:
self.cs.high()
- self.spi.send(0xff)
+ self.spi.write(b'\xff')
return response
# timeout
self.cs.high()
- self.spi.send(0xff)
+ self.spi.write(b'\xff')
return -1
def cmd_nodata(self, cmd):
- self.spi.send(cmd)
- self.spi.send_recv(0xff) # ignore stuff byte
- for _ in range(CMD_TIMEOUT):
- if self.spi.send_recv(0xff)[0] == 0xff:
+ self.spi.write(cmd)
+ self.spi.read(1, 0xff) # ignore stuff byte
+ for _ in range(_CMD_TIMEOUT):
+ if self.spi.read(1, 0xff)[0] == 0xff:
self.cs.high()
- self.spi.send(0xff)
+ self.spi.write(b'\xff')
return 0 # OK
self.cs.high()
- self.spi.send(0xff)
+ self.spi.write(b'\xff')
return 1 # timeout
def readinto(self, buf):
self.cs.low()
# read until start byte (0xff)
- while self.spi.send_recv(0xff)[0] != 0xfe:
+ while self.spi.read(1, 0xff)[0] != 0xfe:
pass
# read data
mv = self.dummybuf_memoryview[:len(buf)]
- self.spi.send_recv(mv, recv=buf)
+ self.spi.write_readinto(mv, buf)
# read checksum
- self.spi.send(0xff)
- self.spi.send(0xff)
+ self.spi.write(b'\xff')
+ self.spi.write(b'\xff')
self.cs.high()
- self.spi.send(0xff)
+ self.spi.write(b'\xff')
def write(self, token, buf):
self.cs.low()
# send: start of block, data, checksum
- self.spi.send(token)
- self.spi.send(buf)
- self.spi.send(0xff)
- self.spi.send(0xff)
+ self.spi.read(1, token)
+ self.spi.write(buf)
+ self.spi.write(b'\xff')
+ self.spi.write(b'\xff')
# check the response
- if (self.spi.send_recv(0xff)[0] & 0x1f) != 0x05:
+ if (self.spi.read(1, 0xff)[0] & 0x1f) != 0x05:
self.cs.high()
- self.spi.send(0xff)
+ self.spi.write(b'\xff')
return
# wait for write to finish
- while self.spi.send_recv(0xff)[0] == 0:
+ while self.spi.read(1, 0xff)[0] == 0:
pass
self.cs.high()
- self.spi.send(0xff)
+ self.spi.write(b'\xff')
def write_token(self, token):
self.cs.low()
- self.spi.send(token)
- self.spi.send(0xff)
+ self.spi.read(1, token)
+ self.spi.write(b'\xff')
# wait for write to finish
- while self.spi.send_recv(0xff)[0] == 0:
+ while self.spi.read(1, 0xff)[0] == 0x00:
pass
self.cs.high()
- self.spi.send(0xff)
+ self.spi.write(b'\xff')
def count(self):
return self.sectors
@@ -224,7 +243,7 @@ class SDCard:
self.readinto(mv[offset : offset + 512])
offset += 512
nblocks -= 1
- return self.cmd_nodata(12)
+ return self.cmd_nodata(b'\x0c') # cmd 12
return 0
def writeblocks(self, block_num, buf):
@@ -236,7 +255,7 @@ class SDCard:
return 1
# send the data
- self.write(TOKEN_DATA, buf)
+ self.write(_TOKEN_DATA, buf)
else:
# CMD25: set write address for first block
if self.cmd(25, block_num * self.cdv, 0) != 0:
@@ -245,8 +264,8 @@ class SDCard:
offset = 0
mv = memoryview(buf)
while nblocks:
- self.write(TOKEN_CMD25, mv[offset : offset + 512])
+ self.write(_TOKEN_CMD25, mv[offset : offset + 512])
offset += 512
nblocks -= 1
- self.write_token(TOKEN_STOP_TRAN)
+ self.write_token(_TOKEN_STOP_TRAN)
return 0