Work on SDCard

This commit is contained in:
Rob Giseburt
2020-01-10 19:25:10 -06:00
parent dd8ac1830c
commit add4bb778c
2 changed files with 136 additions and 102 deletions
+92 -84
View File
@@ -32,22 +32,22 @@ int rcvr_datablock ( /* 1:OK, 0:Failed */
UINT btr /* Byte count (must be even number) */
)
{
volatile INT token;
volatile INT token;
uint32_t start = Motate::SysTickTimer.getValue();
do { /* Wait for data packet in timeout of 100ms */
token = sd_card.read(SPIMessage::DeassertAfter);
} while ((token != 0xFE) && Motate::SysTickTimer.getValue()-start < 100);
if(token != 0xFE) {
do { /* Wait for data packet in timeout of 100ms */
token = sd_card.read(SPIMessage::DeassertAfter);
} while ((token != 0xFE) && Motate::SysTickTimer.getValue()-start < 100);
if(token != 0xFE) {
return 0; /* If not valid data token, return with error */
}
sd_card.read((uint8_t*)buff, btr);
sd_card.read(SPIMessage::RemainAsserted); /* Discard CRC */
sd_card.read(SPIMessage::RemainAsserted);
sd_card.read(SPIMessage::RemainAsserted); /* Discard CRC */
sd_card.read(SPIMessage::RemainAsserted);
return 1; /* Return with success */
return 1; /* Return with success */
}
@@ -80,11 +80,11 @@ int xmit_datablock ( /* 1:OK, 0:Failed */
return 0;
}
return 1;
return 1;
}
#endif
alignas(4) uint8_t data[6];
alignas(4) uint8_t data[12];
/*-----------------------------------------------------------------------*/
/* Send a command packet to MMC */
@@ -109,7 +109,11 @@ uint8_t send_cmd ( /* Returns command response (bit7==1:Send failed)*/
// wait until card is ready to receive command
Motate::Timeout timeout;
timeout.set(1000);
while ((sd_card.read(SPIMessage::DeassertAfter) != 0xFF) && !timeout.isPast()) {};
data[8] = 0x00;
while ((data[8] != 0xFF) && !timeout.isPast()) {
data[0] = 0xFF;
sd_card.readWrite(data, data + 8, 1, SPIMessage::DeassertAfter);
};
// choose the command CRC
uint8_t n = 0x01; /* Dummy CRC + Stop */
@@ -127,14 +131,18 @@ uint8_t send_cmd ( /* Returns command response (bit7==1:Send failed)*/
sd_card.write(data, 6, SPIMessage::RemainAsserted);
// receive response
if (cmd == CMD12) sd_card.read(SPIMessage::RemainAsserted); /* Skip a stuff byte when stop reading */
uint8_t tries = 0xFF; /* Wait for a valid response in timeout of 10 attempts */
do
res = sd_card.read(SPIMessage::RemainAsserted);
while ((res & 0x80) && --tries); // 7th bit is low in all valid responses
if (cmd == CMD12) {
sd_card.read(SPIMessage::RemainAsserted); /* Skip a stuff byte when stop reading */
}
if (ocr)
uint8_t tries = 10; /* Wait for a valid response in timeout of 10 attempts */
do {
res = sd_card.read(SPIMessage::RemainAsserted);
} while ((res & 0x80) && --tries); // 7th bit is low in all valid responses
if (ocr) {
sd_card.read(ocr, 4);
}
return res; /* Return with the response value */
}
@@ -159,32 +167,32 @@ DSTATUS disk_initialize (
BYTE drv /* Physical drive number (0) */
)
{
BYTE ty, cmd, ocr[4];
BYTE ty, cmd, ocr[4];
if (drv) return STA_NOINIT; /* Supports only single drive */
if (disk_status(drv) & STA_NODISK) return Stat; /* No card in the socket */
if (drv) return STA_NOINIT; /* Supports only single drive */
if (disk_status(drv) & STA_NODISK) return Stat; /* No card in the socket */
// initialization has to be performed at a slower speed
sd_card.setOptions(SD_INIT_SPEED);
sd_card.setSDMode(); /* 80 dummy clocks */
sd_card.setSDMode(); /* 80 dummy clocks */
ty = 0;
ty = 0;
if (send_cmd_until_specific_response(CMD0, 0, 1)) { /* Enter Idle state */
if (send_cmd(CMD8, 0x1AA, &ocr[0]) == 1) { /* SDv2? */
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
if (send_cmd(CMD8, 0x1AA, &ocr[0]) == 1) { /* SDv2? */
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
if (send_cmd_until_specific_response(ACMD41, 1UL << 30, 0, nullptr, 1000)) { /* Wait for leaving idle state (ACMD41 with HCS bit) */
if (send_cmd_until_specific_response(CMD58, 0, 0, &ocr[0])) {
ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* SDv2 */
}
}
}
} else { /* SDv1 or MMCv3 */
if (send_cmd(ACMD41, 0) <= 1) {
ty = CT_SD1; cmd = ACMD41; /* SDv1 */
} else {
ty = CT_MMC; cmd = CMD1; /* MMCv3 */
}
}
} else { /* SDv1 or MMCv3 */
if (send_cmd(ACMD41, 0) <= 1) {
ty = CT_SD1; cmd = ACMD41; /* SDv1 */
} else {
ty = CT_MMC; cmd = CMD1; /* MMCv3 */
}
bool success = false;
if (send_cmd_until_specific_response(cmd, 0, 0, nullptr, 1000)) { /* Wait for leaving idle state */
if (send_cmd(CMD16, 512) == 0) /* Set R/W block length to 512 */
@@ -192,17 +200,17 @@ DSTATUS disk_initialize (
}
if (!success)
ty = 0;
}
}
CardType = ty;
}
}
CardType = ty;
if (ty) { /* Initialization succeeded */
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
}
if (ty) { /* Initialization succeeded */
Stat &= ~STA_NOINIT; /* Clear STA_NOINIT */
}
sd_card.setOptions(SD_ACTIVE_SPEED);
return Stat;
return Stat;
}
@@ -211,7 +219,7 @@ DSTATUS disk_initialize (
/*-----------------------------------------------------------------------*/
DSTATUS disk_status (
BYTE drv /* Physical drive number to identify the drive */
BYTE drv /* Physical drive number to identify the drive */
)
{
if (drv != SD0) return STA_NOINIT;
@@ -233,29 +241,29 @@ DSTATUS disk_status (
/*-----------------------------------------------------------------------*/
DRESULT disk_read (
BYTE drv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to read */
BYTE drv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to read */
)
{
if (drv || !count) return RES_PARERR;
if (drv || !count) return RES_PARERR;
if (disk_status(drv) & (STA_NODISK | STA_NOINIT)) return RES_NOTRDY;
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
BYTE cmd;
cmd = count > 1 ? CMD18 : CMD17; /* READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */
cmd = count > 1 ? CMD18 : CMD17; /* READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */
if (send_cmd_until_specific_response(cmd, sector, 0)) {
do {
if (!rcvr_datablock(buff, 512)) break;
buff += 512;
} while (--count);
if (cmd == CMD18) send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
}
if (send_cmd_until_specific_response(cmd, sector, 0)) {
do {
if (!rcvr_datablock(buff, 512)) break;
buff += 512;
} while (--count);
if (cmd == CMD18) send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
}
return count ? RES_ERROR : RES_OK;
return count ? RES_ERROR : RES_OK;
}
@@ -266,37 +274,37 @@ DRESULT disk_read (
#if _USE_WRITE
DRESULT disk_write (
BYTE drv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to write */
BYTE drv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Sector address in LBA */
UINT count /* Number of sectors to write */
)
{
if (drv || !count) return RES_PARERR;
if (disk_status(drv) & (STA_NODISK | STA_NOINIT)) return RES_NOTRDY;
if (Stat & STA_PROTECT) return RES_WRPRT;
if (Stat & STA_PROTECT) return RES_WRPRT;
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
if (count == 1) { /* Single block write */
if (count == 1) { /* Single block write */
if (send_cmd_until_specific_response(CMD24, sector, 0)
&& xmit_datablock(buff, 0xFE))
count = 0;
}
else { /* Multiple block write */
if (CardType & CT_SDC) send_cmd(ACMD23, count);
if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
do {
if (!xmit_datablock(buff, 0xFC)) break;
buff += 512;
} while (--count);
if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
count = 1;
}
}
&& xmit_datablock(buff, 0xFE))
count = 0;
}
else { /* Multiple block write */
if (CardType & CT_SDC) send_cmd(ACMD23, count);
if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
do {
if (!xmit_datablock(buff, 0xFC)) break;
buff += 512;
} while (--count);
if (!xmit_datablock(0, 0xFD)) /* STOP_TRAN token */
count = 1;
}
}
return count ? RES_ERROR : RES_OK;
return count ? RES_ERROR : RES_OK;
}
#endif
@@ -312,16 +320,16 @@ DRESULT disk_ioctl (
void *buff /* Buffer to send/receive control data */
)
{
DRESULT res;
BYTE n, csd[16], *ptr = (BYTE*)buff;
DWORD cs;
DRESULT res;
BYTE n, csd[16], *ptr = (BYTE*)buff;
DWORD cs;
if (drv) return RES_PARERR;
if (drv) return RES_PARERR;
if (disk_status(drv) & (STA_NODISK | STA_NOINIT)) return RES_NOTRDY;
res = RES_ERROR;
switch (ctrl) {
res = RES_ERROR;
switch (ctrl) {
case CTRL_SYNC : /* Make sure that no pending write process */
res = RES_OK;
break;
@@ -395,10 +403,10 @@ DRESULT disk_ioctl (
default:
res = RES_PARERR;
}
}
// deselect();
return res;
return res;
}
#endif
+44 -18
View File
@@ -43,10 +43,10 @@ struct SDCard final {
template <typename SPIBus_t>
SDCard(SPIBus_t &spi_bus, chipSelect_t &chip_select)
: _device{spi_bus.getDevice(chip_select, // pass it the chip select
100000, SPIDeviceMode::kSPIMode0 | SPIDeviceMode::kSPI8Bit,
400, // min_between_chip_select_delay_ns
400, // cs_to_sck_delay_ns
80 // between_word_delay_ns
400000, SPIDeviceMode::kSPIMode0 | SPIDeviceMode::kSPI8Bit,
0, // min_between_chip_select_delay_ns
0, // cs_to_sck_delay_ns
0 // between_word_delay_ns
)},
_chip_select{chip_select}
{ init(); };
@@ -58,8 +58,7 @@ struct SDCard final {
SDCard(const SDCard &) = delete;
// Toss out buffer
uint8_t _scribble_buffer[SCRIBBLE_BUF_MAX];
uint8_t _out_buffer[512];
alignas(4) uint8_t _scribble_buffer[SCRIBBLE_BUF_MAX];
bool _spi_write = false;
bool _spi_read = false;
@@ -67,6 +66,7 @@ struct SDCard final {
uint16_t _num_bytes = 0;
uint8_t *_spi_data;
uint8_t *_spi_read_data;
void _startNextReadWrite()
{
@@ -76,7 +76,7 @@ struct SDCard final {
// We write before we read -- so we don't lose what we set in the registers when writing
if (_spi_write) {
_spi_write = false;
_message.setup(_spi_data, nullptr, _num_bytes, _deassert_chip_select, SPIMessage::EndTransaction);
_message.setup(_spi_data, _spi_read_data, _num_bytes, _deassert_chip_select, SPIMessage::EndTransaction);
} else if (_spi_read) {
_spi_read = false;
@@ -94,6 +94,11 @@ struct SDCard final {
void init() {
_message.message_done_callback = [&] { this->messageDoneCallback(); };
const auto miso_mode = _device._spi_bus->misoPin.getMode();
_device._spi_bus->misoPin.setMode(Motate::kOutput);
_device._spi_bus->misoPin.clear();
_device._spi_bus->misoPin.setMode(miso_mode);
// Establish default values
_spi_write = false;
_spi_read = false;
@@ -105,24 +110,27 @@ struct SDCard final {
}
void setSDMode() {
// _device._spi_bus->misoPin.setOptions(Motate::kPullUp);
// _device._spi_bus->misoPin.setOptions(Motate::kOutput);
for (size_t i = 100000; i--;) {
/* code */
}
const auto cs_mode = _chip_select.getMode();
_chip_select.setMode(Motate::kOutput);
_chip_select.set();
// const auto cs_mode = _chip_select.getMode();
// _chip_select.setMode(Motate::kOutput);
// _chip_select.set();
// _device._spi_bus->misoPin.setMode(Motate::kOutput);
// _device._spi_bus->misoPin.set();
alignas(4) uint8_t tossme[12];
this->read(tossme, 10); /* 80 dummy clocks */
tossme[0] = 0xff;
uint8_t i = 10;
while (i--) { this->write(tossme, 1); /* 80 dummy clocks */ }
_chip_select.setMode(cs_mode);
// _device._spi_bus->misoPin.setOptions(Motate::kNormal);
// _chip_select.setMode(cs_mode);
};
void setOptions(const uint32_t baud, const uint16_t options = (SPIDeviceMode::kSPIMode0 | SPIDeviceMode::kSPI8Bit), uint32_t min_between_chip_select_delay_ns = 400, uint32_t cs_to_sck_delay_ns = 400, uint32_t between_word_delay_ns = 80) {
void setOptions(const uint32_t baud, const uint16_t options = (SPIDeviceMode::kSPIMode0 | SPIDeviceMode::kSPI8Bit),
uint32_t min_between_chip_select_delay_ns = 0, uint32_t cs_to_sck_delay_ns = 0,
uint32_t between_word_delay_ns = 0) {
_device.setOptions(baud, options, min_between_chip_select_delay_ns, cs_to_sck_delay_ns, between_word_delay_ns);
}
@@ -134,11 +142,29 @@ struct SDCard final {
_startNextReadWrite();
};
void read(uint8_t *data, const uint16_t num_bytes, const bool deassert_chip_select = SPIMessage::DeassertAfter) {
void read(uint8_t *data, const uint16_t num_bytes, const bool deassert_chip_select = SPIMessage::RemainAsserted) {
// Configure multi byte read
_spi_read = true;
_spi_data = data;
_spi_read_data = nullptr;
_deassert_chip_select = deassert_chip_select;
_num_bytes = num_bytes;
// Set up read
_startNextReadWrite();
while (_transmitting) {
;
}
};
void readWrite(uint8_t *data, uint8_t *read, const uint16_t num_bytes, const bool deassert_chip_select = SPIMessage::DeassertAfter) {
// Configure multi byte read
_spi_write = true;
_spi_data = data;
_spi_read_data = read;
_deassert_chip_select = deassert_chip_select;
_num_bytes = num_bytes;
@@ -151,7 +177,6 @@ struct SDCard final {
};
uint8_t read(const bool deassert_chip_select = SPIMessage::DeassertAfter) {
// Configure and set up single byte read
read(_scribble_buffer, 1, deassert_chip_select);
return _scribble_buffer[0];
@@ -162,6 +187,7 @@ struct SDCard final {
// Configure multi byte write
_spi_write = true;
_spi_data = data;
_spi_read_data = nullptr;
_deassert_chip_select = deassert_chip_select;
_num_bytes = num_bytes;
@@ -173,7 +199,7 @@ struct SDCard final {
}
};
void write(uint8_t data, const bool deassert_chip_select = SPIMessage::DeassertAfter) {
void write(uint8_t data, const bool deassert_chip_select = SPIMessage::RemainAsserted) {
_scribble_buffer[0] = data;
// Configure and set up single byte write
write(_scribble_buffer, 1, deassert_chip_select);