From c5ff13ad236dbbe3713770d554af31422099af74 Mon Sep 17 00:00:00 2001 From: soypat Date: Mon, 15 Jan 2024 21:11:49 -0300 Subject: [PATCH] implement Card interface --- sd/blockdevice.go | 29 ++++++++++++++++------------- sd/card.go | 2 -- sd/rustref.go | 25 +++++++++++++++++++------ 3 files changed, 35 insertions(+), 21 deletions(-) diff --git a/sd/blockdevice.go b/sd/blockdevice.go index 680a7fa..7311f16 100644 --- a/sd/blockdevice.go +++ b/sd/blockdevice.go @@ -9,20 +9,22 @@ var ( errNegativeOffset = errors.New("sd: negative offset") ) +// Compile time guarantee of interface implementation. +var _ Card = (*SPICard)(nil) + type Card interface { WriteBlocks(data []byte, startBlockIdx int64) error ReadBlocks(dst []byte, startBlockIdx int64) error - EraseBlockSize() int64 EraseBlocks(start, len int64) error } -func NewBlockDevice(card Card, blockSize int, numBlocks int64) *BlockDevice { - if card == nil || blockSize <= 0 { - panic("invalid arguments") +func NewBlockDevice(card Card, blockSize int, numBlocks, eraseBlockSize int64) (*BlockDevice, error) { + if card == nil || blockSize <= 0 || eraseBlockSize <= 0 || numBlocks <= 0 { + return nil, errors.New("invalid argument(s)") } tz := bits.TrailingZeros(uint(blockSize)) if blockSize>>tz != 1 { - panic("blockSize must be a power of 2") + return nil, errors.New("blockSize must be a power of 2") } bd := &BlockDevice{ card: card, @@ -31,20 +33,21 @@ func NewBlockDevice(card Card, blockSize int, numBlocks int64) *BlockDevice { blockmask: (1 << tz) - 1, numblocks: numBlocks, } - return bd + return bd, nil } // BlockDevice implements tinyfs.BlockDevice interface. type BlockDevice struct { - card Card - blockbuf []byte - blockshift int - blockmask int64 - numblocks int64 + card Card + blockbuf []byte + blockshift int + blockmask int64 + numblocks int64 + eraseBlockSize int64 } func (bd *BlockDevice) moduloBlockSize(n int64) int64 { - return n &^ bd.blockmask + return n & bd.blockmask } func (bd *BlockDevice) divideBlockSize(n int64) int64 { @@ -146,5 +149,5 @@ func (bd *BlockDevice) EraseBlocks(start, len int64) error { } func (bd *BlockDevice) EraseBlockSize() int64 { - return bd.card.EraseBlockSize() + return bd.eraseBlockSize } diff --git a/sd/card.go b/sd/card.go index 7a4feb5..0002889 100644 --- a/sd/card.go +++ b/sd/card.go @@ -34,8 +34,6 @@ type SPICard struct { bus drivers.SPI cs digitalPinout bufcmd [6]byte - buf [512]byte - bufTok [1]byte kind CardKind cid CID csd CSD diff --git a/sd/rustref.go b/sd/rustref.go index 76a959d..5cf7bb5 100644 --- a/sd/rustref.go +++ b/sd/rustref.go @@ -189,6 +189,10 @@ func (d *SPICard) ReadBlocks(dst []byte, startBlockIdx int64) error { panic("unreachable numblocks<=0") } +func (d *SPICard) EraseBlocks(startBlock, endBlock int64) error { + return errors.New("sd:erase not implemented") +} + // WriteBlocks writes to sdcard from a buffer multiple of 512 bytes from src starting at block `startBlockIdx`. func (d *SPICard) WriteBlocks(data []byte, startBlockIdx int64) error { numblocks, err := d.checkBounds(startBlockIdx, len(data)) @@ -274,20 +278,26 @@ func (d *SPICard) checkBounds(startBlockIdx int64, datalen int) (numblocks int, return numblocks, nil } -func (d *SPICard) read_cid() (csd CID, err error) { - err = d.cmd_read(cmdSendCID, 0, d.buf[:16]) // CMD10. +func (d *SPICard) read_cid() (cid CID, err error) { + err = d.cmd_read(cmdSendCID, 0, d.cid.data[:16]) // CMD10. if err != nil { - return csd, err + return cid, err } - return DecodeCID(d.buf[:16]) + if !d.cid.IsValid() { + return cid, errBadCSDCID + } + return d.cid, nil } func (d *SPICard) read_csd() (csd CSD, err error) { - err = d.cmd_read(cmdSendCSD, 0, d.buf[:16]) // CMD9. + err = d.cmd_read(cmdSendCSD, 0, d.csd.data[:16]) // CMD9. if err != nil { return csd, err } - return DecodeCSD(d.buf[:16]) + if !d.csd.IsValid() { + return csd, errBadCSDCID + } + return d.csd, nil } func (d *SPICard) cmd_read(cmd command, args uint32, buf []byte) error { @@ -322,6 +332,9 @@ func (d *SPICard) card_command(cmd command, args uint32) (uint8, error) { buf[5] = crc7noshift(buf[:5]) | 1 // CRC and end bit which is always 1. err = d.bus.Tx(buf, nil) + if err != nil { + return 0, err + } if cmd == cmdStopTransmission { d.receive() // skip stuff byte for stop read. }