読者です 読者をやめる 読者になる 読者になる

SDカードから読み込めたけど,書き込みがacceptedされているのに書き込めていない

移転しました。

(追記: 書き込めるようになりましたhttp://d.hatena.ne.jp/beiz23/20131231/1388488925)

SDカードの初期化が出来たので,読み込みをしてみた.FATらしき文字列がでてきてうまく読めているようだ.
しかし,書き込みの方は,書き込み後のフラグがacceptedになっているにもかかわらず,CMD13でstatusをみると,0x08で,CC error — Internal card controller errorとなっていて,書き込めていないようだ.原因不明だし,ロジアナをもっていないなので放置することにします...
ロジアナ欲しいなー..

from pylibftdi import BitBangDevice, Bus
import time

class sd(object):
    """
    The FT245R is wired to the SD as follows:
       DB0 to DI
       DB1 to D0
       DB2 to CLK
       DB3 to CS
       DB4 to POW 
    """
    DI = Bus(0)
    DO = Bus(1)
    CLK = Bus(2)
    CS = Bus(3)
    POW = Bus(4)

    def __init__(self, device):
        # The Bus descriptor assumes we have a 'device'
        # attribute which provides a port
        self.device = device

    def _trigger(self, n = 1):
        "generate a H->L"
        for _ in range(n):
            self.CLK = 1
            self.CLK = 0

    def _getDO(self): #read when clk down -> up mode 0
        self.CLK = 1 #up 
        do = self.DO #read
        self.CLK = 0
        return do

    def _putDI(self, di):
        self.DI = di #write 
        self.CLK = 1 #up
        self.CLK = 0

    def _write_raw(self, byte, l = 8):
    	for i in range(l):
            di = (byte >> (l-1-i)) & 0b1
            self._putDI(di)
#            print "%d" % di,

#        print 

    def _read_raw(self, l = 8):
        res = 0
    	for i in range(l):
            do = self._getDO()
            #print "%d" % do
            res += do << (l-1-i)

        return res

    def read_res(self, l = 1):
        print "read_res (timeout >= 8 byte)"
        for i in range(8):
            res = self._read_raw()
            print "response: %x" % res
            if res != 0xFF:
                for _ in range(l-1):
                    res = (res << 8) + self._read_raw()
                break

        return res


    def write_cmd(self, cmd, addr, crc): #cmd 6bit, addr 8x4bit, crc7bit
        #cmd
        self._write_raw(0b01000000 + cmd)
        #addr
        #for i in range(4):
	#    self._write_raw((addr >> (3-i)*8) & 0xff)
        self._write_raw(addr, 8*4)
        #CRC
        self._write_raw(0b1 + (crc << 1))
        #up
        #self.DI = 1 #stop bit is always 1
        #print "DI after cmd: ", self.DI

    def init_spi(self):
        print "power on and wait > 1ms"
        self.POW = 1
        time.sleep(0.01)

        print "dummy clock >= 74 with CS and DI high"
        self.CS = 1
        self.DI = 1
        self._trigger(75)#more than 74 times

        print "CMD0 with CS low"
        self.CS = 0
        while 1:
            self.write_cmd(0, 0, 0b1001010)
            if self.read_res() == 0b1:
                print "cmd0 ok (response == 1)"
                print "wait 8bit..: %x" % self._read_raw(8)
                break


        #cmd1
        #print "cmd1"
        #while 1:
        #    self.write_cmd(1, 0, 0)
       #     if self.read_byte() == 0b0:
        #        break
        #print "cmd1 ok (res == 0)"

        #cmd55
        print "ACMD41"
        while 1:
            self.write_cmd(55, 0, 0)
            if self.read_res() == 0b1:
                print "wait 8bit..: %x" % self._read_raw(8)
        #print "cmd55 ok (response == 1)"
                self.write_cmd(41, 0, 0)
                if self.read_res() == 0b0:
                    print "ACMD41 ok (response == 0)"
                    print "wait 8bit..: %x" % self._read_raw(8)
                    break


    """
    def _wait_DO_0(self, timeout = 8):
        for i in range(timeout*8):
            do = self._getDO()
            print "%d" % do,
            if (do == 0):
                break

            if (i == timeout*8-1):
                print "timeout"
                sys.exit()
                """

    def single_read(self, addr, l = 512):
        #cmd17
        print "single read CMD17, addr: %d" % addr, "len: %d" % l
        while 1:
            self.write_cmd(17, addr, 0)
            if self.read_res() == 0b0:
                print "cmd17 ok, response: 0"
                break

        #start 0xfe
        while (self.read_res() != 0xfe): #_wait_DO_0()
            pass

        print "start data"
        #f = open('sdout.bin', 'wb')

        #for i in range(16):#byte
        #    for j in range(32):#byte
        for i in range(l):
            c = self._read_raw()
            print "%x" % c,
            #f.write(chr(c))
            if i%32==31:
                print

        #f.close()

        print "crc: %x" % self._read_raw(8*2)
        print "wait 8bit..: %x" % self._read_raw(8)



    def single_write(self, addr, l = 512):
        print "single write CMD24, addr: %d" % addr, "len: %d" % l
        while 1:
            self.write_cmd(24, addr, 0)
            if self.read_res() == 0b0:
                print "cmd24 ok, response: 0"
                break

        print "wait >= 1 byte"
        self._trigger(8)

        self._write_raw(0xfe) #data token
        print "send data"
        #f = open('sdout.bin', 'wb')
        text = "Hello, world!"
        for i in range(l / len(text)):
            for c in text:
                self._write_raw(ord(c))
                print c, bin(ord(c))
            print i

        #fill 0xff
        #for i in range(512):#range(l % len(text)):

        self._write_raw(0, (l % len(text))*8)
        print (l/len(text))*len(text) + l % len(text)
        #crc
        #print "crc: %x" % self._read_raw(8*2)
        print "crc: 0x00"
        self._write_raw(0, 8*2)
        self.DI = 1
        #self._trigger(8*2) 

        #responce
        #self._wait_DO_0()
        res = self._read_raw()
        if (res & 0b00011111) == 0b00101:
            print bin(res), "data accepted."
        else:
            print bin(res), "error."

        print "wait for releasing busy state (DO = 1)"
        res = 0
        while res != 0x0:
            res = self._read_raw()
            print res

        #    if do == 1:
        #        print "do is 1"
        #        break

        print "wait 8bit..: %x" % self._read_raw()
        print "wait 8bit..: %x" % self._read_raw()
        #self.get_status()


    def set_blocklen(self, l):
        #cmd16
        print "set blocklen cmd16 len: %d" % l
        while 1:
            self.write_cmd(16, l, 0)
            if self.read_res() == 0b0:
                break

        print "cmd16 ok, response: 0"


    def multi_read(self, addr):
        #cmd18
        print "cmd18, addr: %d" % addr
        while 1:
            self.write_cmd(18, addr, 0)
            if self.read_res() == 0b0:
                break

        print "cmd18 ok, response: 0"
        f = open('sdout.bin', 'wb')

        for j in range(10):
            self._wait_DO_0()
            print "start data"
            for i in range(512):#byte
                c = self._read_raw(8)
                print "%x" % c,
                f.write(chr(c))
                if i%32==0:
                    print
            #crc
            print "crc:", self._read_raw(8*2)

        f.close()
        self.POW = 0


    def get_status(self):
        print "cmd13, SEND_STATUS"
        self.write_cmd(13, 0, 0)
        #r2
        print "r2: %x" % self.read_res(2) #p.96, 92
        print "wait 8bit..: %x" % self._read_raw(8)

    def get_ocr(self):
        print "cmd58, READ_OCR"
        self.write_cmd(58, 0, 0)
        #r3
        print "r3: %x" % self.read_res(5) #p.37, 92
        print "wait 8bit..: %x" % self._read_raw(8)

    def get_cid(self):
        print "cmd10, SEND_CID"
        #r1, 128/8 byte
        while 1:
            self.write_cmd(10, 0, 0)
            r1 = self.read_res() #p.38, 92
            print "r1: %x" % r1
            if r1 == 0:
                break

        while (self.read_res() != 0xfe):
            pass

        for i in range(16):
            c = self._read_raw()
            print "%x" % c,

        print
        print "crc: %x" % self._read_raw(8*2)
        print "wait 8bit..: %x" % self._read_raw(8)

    def get_csd(self):
        print "cmd9, SEND_CSD"
        self.write_cmd(9, 0, 0)
        #r1, 128/8 byte = 16 byte
        print "r2: %x" % self.read_res(2) #p.39

    def power_off(self):
        self.POW = 0

def display(device_id=None):

    with BitBangDevice(device_id) as bb:
        # the actual baudrate is 16x this in bitbang mode...
        #bb.baudrate = 921600, 307200, 153600, 76800, 38400, 19200, 9600, 4800
        #bb.baudrate = 2400
        print bb.baudrate
        bb.ftdi_fn.ftdi_set_latency_timer(1)
       	bb.direction = 0b00011101
        #bb.port = 0x00 #output (not pullup)
       	sdc = sd(bb)
        sdc.init_spi()
        print "complete init"
        #print bb.baudrate
        #text = "Hello, world!"
        #l = len(text)
        #sdc.set_blocklen(30)

        # latency for reading
        #latency = 0
        #bb.ftdi_fn.ftdi_get_latency_timer(latency) #1-255
        #print latency

        #bb.ftdi_fn.ftdi_get_latency_timer(latency) #1-255
        #print latency

        #sdc.single_write(512, 30)
        sdc.get_status()
        sdc.single_write(0)
        sdc.get_status()
        #sdc.single_read(512*0)
        sdc.single_read(512*1)
#        sdc.single_read(512*2)
#        sdc.single_read(512*3)
#        sdc.single_read(512*4)
#        sdc.single_read(512*6)
        #sdc.single_read(512*2)
        #sdc.single_read(512, 30)
        #sdc.multi_read(0)
        #sdc.power_off()
        #sdc.multi_read(0)
#r2 8

if __name__ == '__main__':
    import sys
    display()