mirror of
https://github.com/tinygo-org/drivers.git
synced 2026-08-05 23:43:41 +00:00
add status string method
This commit is contained in:
+1
-1
@@ -62,7 +62,7 @@ func main() {
|
||||
var buf [512]byte
|
||||
for i := 0; i < 11; i += 1 {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
err = sdcard.ReadBlock(int64(i), buf[:])
|
||||
err = sdcard.ReadBlock(0, buf[:])
|
||||
if err != nil {
|
||||
println("err reading block", i, ":", err.Error())
|
||||
continue
|
||||
|
||||
+15
@@ -43,6 +43,8 @@ type SPICard struct {
|
||||
timers [2]timer
|
||||
numblocks int64
|
||||
timeout time.Duration
|
||||
// relative card address.
|
||||
rca uint32
|
||||
}
|
||||
|
||||
func NewSPICard(spi drivers.SPI, cs digitalPinout) *SPICard {
|
||||
@@ -182,6 +184,12 @@ func (d *SPICard) Init() error {
|
||||
return errNoblocks
|
||||
}
|
||||
d.numblocks = int64(nb)
|
||||
|
||||
err = d.readRegister(cmdSendRelativeAddr, d.buf[:4])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
d.rca = binary.BigEndian.Uint32(d.buf[:4])
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -271,6 +279,13 @@ func (d *SPICard) WriteBlock(block int64, src []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *SPICard) ReadStatus() (response1, error) {
|
||||
if err := d.readRegister(cmdSendStatus, d.buf[:4]); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return response1(binary.BigEndian.Uint32(d.buf[:4])), nil
|
||||
}
|
||||
|
||||
// CID returns a copy of the Card Identification Register value last read.
|
||||
func (d *SPICard) CID() CID { return d.cid }
|
||||
|
||||
|
||||
@@ -476,6 +476,106 @@ const (
|
||||
tokWRITE_MULT = 0xfc
|
||||
)
|
||||
|
||||
type status uint32
|
||||
|
||||
// First status bits.
|
||||
//
|
||||
//go:generate stringer -type=status -trimprefix=status -output=status_string.go
|
||||
const (
|
||||
statusRsvd0 status = iota
|
||||
statusRsvd1
|
||||
statusRsvd2
|
||||
statusAuthSeqError
|
||||
statusRsvdSDIO
|
||||
statusAppCmd
|
||||
statusFXEvent
|
||||
statusRsvd7
|
||||
statusReadyForData
|
||||
)
|
||||
|
||||
// Upper bound status bits.
|
||||
const (
|
||||
statusEraseReset status = iota + 13
|
||||
statusECCDisabled
|
||||
statusWPEraseSkip
|
||||
statusCSDOverwrite
|
||||
_
|
||||
_
|
||||
statusGenericError
|
||||
statusControllerError // internal card controller error
|
||||
statusECCFailed
|
||||
statusIllegalCommand
|
||||
statusComCRCError // CRC check of previous command failed
|
||||
statusLockUnlockFailed
|
||||
statusCardIsLocked // Signals that the card is locked by the host.
|
||||
statusWPViolation // Write protected violation
|
||||
statusEraseParamError // invalid write block selection for erase
|
||||
statusEraseSeqError // error in erase sequence
|
||||
statusBlockLenError // tx block length not allowed
|
||||
statusAddrError // misaligned address
|
||||
statusAddrOutOfRange // address out of range
|
||||
)
|
||||
|
||||
// r1 is the normal response to a command.
|
||||
type r1 struct {
|
||||
data [48 / 8]byte // 48 bits of response.
|
||||
}
|
||||
|
||||
func (r *r1) RawCopy() [6]byte { return r.data }
|
||||
func (r *r1) startbit() bool {
|
||||
return r.data[0]&(1<<7) != 0
|
||||
}
|
||||
func (r *r1) txbit() bool {
|
||||
return r.data[0]&(1<<6) != 0
|
||||
}
|
||||
func (r *r1) cmdidx() uint8 {
|
||||
return r.data[0] & 0b11_1111
|
||||
}
|
||||
func (r *r1) cardstatus() status {
|
||||
return status(binary.BigEndian.Uint32(r.data[1:5]))
|
||||
}
|
||||
func (r *r1) CRC7() uint8 { return r.data[5] >> 1 }
|
||||
func (r *r1) endbit() bool { return r.data[5]&1 != 0 }
|
||||
|
||||
func (r *r1) IsValid() bool {
|
||||
return r.endbit() && CRC7(r.data[:5]) == r.CRC7()
|
||||
}
|
||||
|
||||
type r6 struct {
|
||||
data [48 / 8]byte
|
||||
}
|
||||
|
||||
func (r *r6) RawCopy() [6]byte { return r.data }
|
||||
func (r *r6) startbit() bool {
|
||||
return r.data[0]&(1<<7) != 0
|
||||
}
|
||||
func (r *r6) txbit() bool {
|
||||
return r.data[0]&(1<<6) != 0
|
||||
}
|
||||
func (r *r6) cmdidx() uint8 {
|
||||
return r.data[0] & 0b11_1111
|
||||
}
|
||||
func (r *r6) rca() uint16 {
|
||||
return binary.BigEndian.Uint16(r.data[1:3])
|
||||
}
|
||||
func (r *r6) cardstatus() status {
|
||||
moveBit := func(b status, from, to uint) status {
|
||||
return (b & (1 << from)) >> from << to
|
||||
}
|
||||
// See 4.9.5 R6 (Published RCA response) of the SD Simplified Specification.
|
||||
s := status(binary.BigEndian.Uint16(r.data[1:5]))
|
||||
s = moveBit(s, 13, 19)
|
||||
s = moveBit(s, 14, 22)
|
||||
s = moveBit(s, 15, 23)
|
||||
return s
|
||||
}
|
||||
func (r *r6) CRC7() uint8 { return r.data[5] >> 1 }
|
||||
func (r *r6) endbit() bool { return r.data[5]&1 != 0 }
|
||||
|
||||
func (r *r6) IsValid() bool {
|
||||
return r.endbit() && CRC7(r.data[:5]) == r.CRC7()
|
||||
}
|
||||
|
||||
type response1 uint8
|
||||
|
||||
func (r response1) IsIdle() bool { return r&_R1_IDLE_STATE != 0 }
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
package sd
|
||||
|
||||
func _() {
|
||||
// An "invalid array index" compiler error signifies that the constant values have changed.
|
||||
// Re-run the stringer command to generate them again.
|
||||
var x [1]struct{}
|
||||
_ = x[statusRsvd0-0]
|
||||
_ = x[statusRsvd1-1]
|
||||
_ = x[statusRsvd2-2]
|
||||
_ = x[statusAuthSeqError-3]
|
||||
_ = x[statusRsvdSDIO-4]
|
||||
_ = x[statusAppCmd-5]
|
||||
_ = x[statusFXEvent-6]
|
||||
_ = x[statusRsvd7-7]
|
||||
_ = x[statusReadyForData-8]
|
||||
_ = x[statusEraseReset-13]
|
||||
_ = x[statusECCDisabled-14]
|
||||
_ = x[statusWPEraseSkip-15]
|
||||
_ = x[statusCSDOverwrite-16]
|
||||
_ = x[statusGenericError-19]
|
||||
_ = x[statusControllerError-20]
|
||||
_ = x[statusECCFailed-21]
|
||||
_ = x[statusIllegalCommand-22]
|
||||
_ = x[statusComCRCError-23]
|
||||
_ = x[statusLockUnlockFailed-24]
|
||||
_ = x[statusCardIsLocked-25]
|
||||
_ = x[statusWPViolation-26]
|
||||
_ = x[statusEraseParamError-27]
|
||||
_ = x[statusEraseSeqError-28]
|
||||
_ = x[statusBlockLenError-29]
|
||||
_ = x[statusAddrError-30]
|
||||
_ = x[statusAddrOutOfRange-31]
|
||||
}
|
||||
|
||||
const (
|
||||
_status_name_0 = "Rsvd0Rsvd1Rsvd2AuthSeqErrorRsvdSDIOAppCmdFXEventRsvd7ReadyForData"
|
||||
_status_name_1 = "EraseResetECCDisabledWPEraseSkipCSDOverwrite"
|
||||
_status_name_2 = "GenericErrorControllerErrorECCFailedIllegalCommandComCRCErrorLockUnlockFailedCardIsLockedWPViolationEraseParamErrorEraseSeqErrorBlockLenErrorAddrErrorAddrOutOfRange"
|
||||
)
|
||||
|
||||
var (
|
||||
_status_index_0 = [...]uint8{0, 5, 10, 15, 27, 35, 41, 48, 53, 65}
|
||||
_status_index_1 = [...]uint8{0, 10, 21, 32, 44}
|
||||
_status_index_2 = [...]uint8{0, 12, 27, 36, 50, 61, 77, 89, 100, 115, 128, 141, 150, 164}
|
||||
)
|
||||
|
||||
func (i status) string() string {
|
||||
switch {
|
||||
case i <= 8:
|
||||
return _status_name_0[_status_index_0[i]:_status_index_0[i+1]]
|
||||
case 13 <= i && i <= 16:
|
||||
i -= 13
|
||||
return _status_name_1[_status_index_1[i]:_status_index_1[i+1]]
|
||||
case 19 <= i && i <= 31:
|
||||
i -= 19
|
||||
return _status_name_2[_status_index_2[i]:_status_index_2[i+1]]
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (s status) String() string {
|
||||
return string(s.appendf(nil, ','))
|
||||
}
|
||||
|
||||
func (s status) appendf(b []byte, delim byte) []byte {
|
||||
b = append(b, '[')
|
||||
if s == 0 {
|
||||
return append(b, ']')
|
||||
}
|
||||
for bit := 0; bit < 32; bit++ {
|
||||
if s&(1<<bit) != 0 {
|
||||
b = append(b, status(bit).string()...)
|
||||
b = append(b, delim)
|
||||
}
|
||||
}
|
||||
b = append(b[:len(b)-1], ']')
|
||||
return b
|
||||
}
|
||||
Reference in New Issue
Block a user