稼働中

マイクロビット(c_09)SDカード 読書き、消去 用モジュール

SDカードモジュール(SPI) SDC_RWE_c.py

2GB以下(MMC)とSDHC(2GB超~32GB)SDカードの読書き、消去で使う自作の’SDC_RWE_c.py’を作成しました。使い方だけを記載します。(※記事e_023を元にクラスにしました。)
‘SDC_RWE_c.py’は末尾にあります。

ファイル転送
micro:bitへ’SDC_RWE_c.py’を送った後でimportして使います。micro:bitに直接ファイルをアップロード出来ない場合(Thonny 3.1.12など)は、microfsなどを使ってアップロードします。
※microfsについては、当サイト内のこちらを参照ください。
※ファイルシステムへ送って使わないとメモリーエラーになると思います。(micro:bit V1)

メソッド
‘SDC_RWE_c’をimportすると「SDC_init, SDC_cmd17, SDC_cmd24, SDC_cmd32, SDC_cmd33, SDC_cmd38 SDC_end」のメソッドが使えるようになります。
SDC_RWE(pins=pin8)で初期化します。CS(chip select)と接続するmicro:bitのpinを指定して初期化します。defaltはpin8です。
(01)SDC_init()
ダミークロックを’0xff’を80個送りspi通信にします。CSをLowにしてデバイスを選択します。
(02)SDC_cmd17(adm)
cmd17(READ_SINGLE_BLOCK)コマンドを送ります。
admは読み出すアドレスです。アドレスは512バイト単位です。[0x00,0x00,0x00,0x00]で指定します。
(03)SDC_cmd24(block_buf,adm)
cmd24(WRITE_BLOCK)コマンドを送ります。
block_bufは書込むbytearrayデータです。512バイト単位で送ります。(256バイトx2にしています)
admは書込むアドレスです。アドレスは512バイト単位です。[0x00,0x00,0x00,0x00]で指定します。
(04)SDC_cmd32(s_adr)
cmd32(ERASE_WR_BLK_START_ADDR)コマンドを送ります。
s_adrは消去開始するアドレスです。512バイト単位です。[0x00,0x00,0x00,0x00]で指定します。
(05)SDC_cmd33(e_adr)
cmd33(ERASE_WR_BLK_END_ADDR)コマンドを送ります。
e_adrは消去終了するアドレスです。512バイト単位です。[0x00,0x00,0x00,0x00]で指定します。
(06)SDC_cmd38()
cmd38(ERASE)コマンドを送ります。SDC_cmd32、SDC_cmd33で指定したアドレスのデータを消去を実行します。
(07)SDC_end()
CSをHighにしてデバイスを非選択にします。

使用例

SDカードの読込み、書込み、消去の使用例です。


SDC_RWE_ex.py
from microbit import *
from SDC_RWE_c import SDC_RWE
## example ------------------
# SPI init bps=100kHz
spi.init(baudrate=100000, bits=8, mode=0, sclk=pin13, mosi=pin15, miso=pin14)
sleep(10)

# Write Data 256byte 512byteだとMemoryエラーになるので256x2回で書き込み
block_buf=bytearray(256)
for i in range(256):
    block_buf[i]=0xff

a=SDC_RWE()

## SDHC WRITE_BLOCK
a.SDC_init() 
w_adr=[0x00,0x00,0x00,0x00]
a.SDC_cmd24(block_buf,w_adr)
a.SDC_end()

# read address 512xnum num wo set
#SDC_cmd17(adm) [xx,xx,xx,xx] hex(512)'0x200'hex(1024)'0x400'
a.SDC_init()  ## 必要
m_adr=[0x00,0x00,0x00,0x00]
a.SDC_cmd17(m_adr)
a.SDC_end()

# SDHC ERASE_BLOCK
#a.SDC_init() 
#s_adr=[0x00,0x00,0x00,0x00]   # erase start address
#a.SDC_cmd32(s_adr)            # erase start address set
#
#e_adr=[0x00,0x00,0x04,0x00] # erase end address
#a.SDC_cmd33(e_adr)            # erase end address set
#
#a.SDC_cmd38()                 # erase
#a.SDC_end()


実行結果
メモリーエラーが生じるので各個別にコメントアウトを外して確認しています。

書込み0xffを512bytes実行後(0x00番地から512バイト)

読出し(0x00番地から512バイト)0xffが書き込まれている

>>> %Run SDC_RWE_ex.py
START CLK>80
cmd24 WRITE_BLOCK START
cmd24 OK
write-ok res=5 b'\xe5' 0b11100101
START CLK>80
cmd17 READ_SINGLE_BLOCK START
cmd17 pass >>
token 0xfe find
read_block_address= bytearray(b'\x00\x00\x00\x00')
512bytes= b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\
省略
xff\xff\xff\xff\xff\xff\xff\xff\xff'
CRC2= b'\x7f\xa1'
>>>

消去(0x00~0x400(1024)番地)


>>> %Run SDC_RWE_ex.py
START CLK>80
ERASE OK DONE
>>>

読出し(0x00番地から512バイト)消去されている


>>> %Run SDC_RWE_ex.py
START CLK>80
cmd17 READ_SINGLE_BLOCK START
cmd17 pass >>
token 0xfe find
read_block_address= bytearray(b'\x00\x00\x00\x00')
512bytes= b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\
省略
x00\x00\x00\x00\x00\x00\x00\x00'
CRC2= b'\x00\x00'

モジュール

SDカードの読込み、書込み、消去


SDC_RWE_c.py
from microbit import *
import sys
# 2022.06.30 ------------------- CMD17-24-38 READ WRITE ERASE SDC_RWE_c.py
# >>> %Run SDC_RWE_c.py  MemoryError: なので ufs put SDC_RWE_c.py
class SDC_RWE:
    def __init__(self,pins=pin8):    
        # micro:bit pin8 for CS active(0)
        self.CS_pin=pins
    # card send data
    def spi_cmd(self,cmd,da1,da2,da3,da4,crc):
        buf=bytearray(6)
        buf[0]=0x40+cmd
        buf[1]=da1
        buf[2]=da2
        buf[3]=da3
        buf[4]=da4
        buf[5]=crc
        spi.write(buf)
        return buf
    # dummy 8clk
    def spi_ff(self):
        spi.write(b'\xff') 
    # chip select active(0)
    def CS(self,dat):
        self.CS_pin.write_digital(dat)

    def SDC_init(self):
        # SDCの初期化
        # Initialization sequence
        print('START CLK>80')
        self.CS(1)               #CS=Hでダミークロックを80個送信(74個<)
        for i in range(10):
            self.spi_ff()
        self.CS(0)

    def SDC_end(self):
        #END
        self.spi_ff()
        self.CS(1)
        self.spi_ff()
        
    ##-------------------------------------------CMD17 (READ)
    #cmd17=0x51 READ_SINGLE_BLOCK
    def SDC_cmd17(self,adm):
        print('cmd17 READ_SINGLE_BLOCK START')
        self.spi_ff()
        radr=self.spi_cmd(17,adm[0],adm[1],adm[2],adm[3],0x01)
        b_add=radr[1:5]    # address 
        # 0x00>>0xfeが返るまで受信
        while True:
            self.spi_ff()    # CMD>>0xFF out>>read response
            res=spi.read(1) # response
            if res== b'\x00':
                print('cmd17 pass >>')
                break
        while True:
            self.spi_ff()    # CMD>>0xFF out>>read response
            res=spi.read(1) # response
            #print(res)
            if res== b'\xfe':
                print('token 0xfe find')
                break
        block_buf=spi.read(512)
        #crc 2byte read
        crc_buf=spi.read(2)
        
        print('read_block_address=',b_add)
        print('512bytes=',block_buf)
        print('CRC2=',crc_buf)  #特に使わない

    ##-------------------------------------------CMD24 (WRITE)
    # cmd24=0x58 WRITE_BLOCK
    def SDC_cmd24(self,block_buf,adm):
        print('cmd24 WRITE_BLOCK START')
        self.spi_ff()
        #spi_cmd(24,0x00,0x00,0x04,0x00,0x01)
        self.spi_cmd(24,adm[0],adm[1],adm[2],adm[3],0x01)
        self.spi_ff()

        while True:    
            #spi_ff()    # CMD>>0xFF out>>read response
            res=spi.read(1)
            if res== b'\x00':
                print('cmd24 OK')
                break
        self.spi_ff()            
        spi.write(b'\xfe')  #Start Block Token
        spi.write(block_buf) #512バイトデータを送ります
        spi.write(block_buf) # MEMORY ERR で256*2 にしている
        spi.write(b'\x00') #//Send CRC1
        spi.write(b'\x01') #//Send CRC2
        #
        cnt=0
        while True:
            cnt=cnt+1
            res=spi.read(1)
            re=res[0] & 0x1f
            if re==0x05:
                print('write-ok res=5',res,bin(res[0]))
                break
            if cnt>10:
                print('WRITE-NG',cnt)
    ##-------------------------------------------CMD32-33-38 (ERASE)
    #cmd32=0x60 ERASE_WR_BLK_START_ADDR R1
    def SDC_cmd32(self,s_adr):
        self.spi_ff()
        self.spi_cmd(32,s_adr[0],s_adr[1],s_adr[2],s_adr[3],0x01)
        self.spi_ff()
        res=spi.read(1) #response
        if res != b'\x00':
           print('CMD32 START ADD SET ERROR',res)
           sys.exit()
    # --------------------------------------------- CMD33 BLK_END_ADD
    #cmd33=0x61    ERASE_WR_BLK_END_ADDR   R1
    def SDC_cmd33(self,e_adr):    
        self.spi_ff()
        self.spi_cmd(33,e_adr[0],e_adr[1],e_adr[2],e_adr[3],0x01)
        self.spi_ff()
        res=spi.read(1) #response
        if res != b'\x00':
           print('CMD33 END ADD SET ERROR',res)
           sys.exit()
        
    # --------------------------------------------- CMD38 ERASE
    #cmd38=0x66  ERASE Erases   R1b
    def SDC_cmd38(self):
        self.spi_ff()
        self.spi_cmd(38,0x00,0x00,0x00,0x00,0x01) 
        self.spi_ff() 
        res=spi.read(1) #response
        if res != b'\x00':
           print('CMD38 ERASE ERROR',res)
           sys.exit()
        print('ERASE OK DONE')