SD access part from #1644

This commit is contained in:
bsongis
2014-09-15 12:19:19 +02:00
parent 6190c399c5
commit 141e8322ec
2 changed files with 75 additions and 45 deletions
+74 -44
View File
@@ -246,6 +246,12 @@ BYTE wait_ready (void)
}
static void spi_reset()
{
for(int n=0; n < 520; ++n) {
stm32_spi_rw(0xFF);
}
}
/*-----------------------------------------------------------------------*/
/* Deselect the card and release SPI bus */
@@ -475,7 +481,10 @@ BOOL rcvr_datablock (
do { /* Wait for data packet in timeout of 100ms */
token = rcvr_spi();
} while ((token == 0xFF) && Timer1);
if(token != 0xFE) return FALSE; /* If not valid data token, return with error */
if(token != 0xFE) {
spi_reset();
return FALSE; /* If not valid data token, return with error */
}
#ifdef STM32_SD_USE_DMA
stm32_dma_transfer( TRUE, buff, btr );
@@ -500,6 +509,8 @@ BOOL rcvr_datablock (
/* Send a data packet to MMC */
/*-----------------------------------------------------------------------*/
#define DATA_RESPONSE_TIMEOUT 10
static
BOOL xmit_datablock (
const BYTE *buff, /* 512 byte data block to be transmitted */
@@ -511,7 +522,10 @@ BOOL xmit_datablock (
BYTE wc;
#endif
if (wait_ready() != 0xFF) return FALSE;
if (wait_ready() != 0xFF) {
spi_reset();
return FALSE;
}
xmit_spi(token); /* transmit data token */
if (token != 0xFD) { /* Is data token */
@@ -528,9 +542,25 @@ BOOL xmit_datablock (
xmit_spi(0xFF); /* CRC (Dummy) */
xmit_spi(0xFF);
resp = rcvr_spi(); /* Receive data response */
if ((resp & 0x1F) != 0x05) /* If not accepted, return with error */
return FALSE;
/*
Despite what the SD card standard says, the reality is that (at least for some SD cards)
the Data Response byte does not come immediately after the last byte of data.
This delay only happens very rarely, but it does happen. Typical response delay is some 10ms
*/
Timer2 = DATA_RESPONSE_TIMEOUT;
do {
resp = rcvr_spi(); /* Receive data response */
if ((resp & 0x1F) == 0x05) { /* If not accepted, return with error */
return TRUE;
}
if (resp != 0xFF) {
spi_reset();
return FALSE;
}
} while (Timer2);
}
return TRUE;
@@ -559,6 +589,7 @@ BYTE send_cmd (
/* Select the card and wait for ready */
SELECT();
if (wait_ready() != 0xFF) {
spi_reset();
return 0xFF;
}
@@ -577,9 +608,9 @@ BYTE send_cmd (
if (cmd == CMD12) rcvr_spi(); /* Skip a stuff byte when stop reading */
n = 10; /* Wait for a valid response in timeout of 10 attempts */
do
do {
res = rcvr_spi();
while ((res & 0x80) && --n);
} while ((res & 0x80) && --n);
return res; /* Return with the response value */
}
@@ -675,6 +706,9 @@ int8_t SD_ReadSectors(uint8_t *buff, uint32_t sector, uint32_t count)
count = 0;
}
}
else {
spi_reset();
}
}
else { /* Multiple block read */
if (send_cmd(CMD18, sector) == 0) { /* READ_MULTIPLE_BLOCK */
@@ -686,11 +720,14 @@ int8_t SD_ReadSectors(uint8_t *buff, uint32_t sector, uint32_t count)
} while (--count);
send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
}
else {
spi_reset();
}
}
release_spi();
return 0;
return count ? -1 : 0;
}
DRESULT disk_read (
@@ -702,10 +739,8 @@ DRESULT disk_read (
{
if (drv || !count) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
SD_ReadSectors(buff, sector, count);
return RES_OK;
int8_t res = SD_ReadSectors(buff, sector, count);
return (res != 0) ? RES_ERROR : RES_OK;
}
@@ -715,22 +750,37 @@ DRESULT disk_read (
/*-----------------------------------------------------------------------*/
// TODO quick & dirty
int8_t SD_WriteSectors(uint8_t *buff, uint32_t sector, uint32_t count)
int8_t SD_WriteSectors(const uint8_t *buff, uint32_t sector, uint32_t count)
{
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
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;
if (count == 1) { /* Single block write */
if (send_cmd(CMD24, sector) == 0) { /* WRITE_BLOCK */
if (xmit_datablock(buff, 0xFE)) {
count = 0;
}
}
else {
spi_reset();
}
}
else {
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;
}
else {
spi_reset();
}
}
release_spi();
return 0;
return count ? -1 : 0;
}
#if _FS_READONLY == 0
@@ -745,28 +795,8 @@ DRESULT disk_write (
if (drv || !count) return RES_PARERR;
if (Stat & STA_NOINIT) return RES_NOTRDY;
if (Stat & STA_PROTECT) return RES_WRPRT;
if (!(CardType & CT_BLOCK)) sector *= 512; /* Convert to byte address if needed */
if (count == 1) { /* Single block write */
if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */
&& 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;
}
}
release_spi();
return count ? RES_ERROR : RES_OK;
int8_t res = SD_WriteSectors(buff, sector, count);
return (res != 0) ? RES_ERROR : RES_OK;
}
#endif /* _READONLY == 0 */
@@ -265,7 +265,7 @@ int8_t STORAGE_Read (uint8_t lun,
* @retval Status
*/
int8_t SD_WriteSectors(uint8_t *buf, uint32_t sector, uint32_t count);
int8_t SD_WriteSectors(const uint8_t *buf, uint32_t sector, uint32_t count);
int8_t STORAGE_Write (uint8_t lun,
uint8_t *buf,