mirror of
https://github.com/espruino/Espruino.git
synced 2025-12-08 19:06:15 +00:00
Fix SD card IO that can corrupt SD card on file append since 1v73 (fix #536)
This commit is contained in:
parent
46f15d6db1
commit
80cb0d0d1d
@ -1,4 +1,4 @@
|
||||
1v80 : ...
|
||||
1v80 : Fix SD card IO that can corrupt SD card on file append since 1v73 (fix #536)
|
||||
|
||||
1v79 : Fix Mac address parsing for top nibbles
|
||||
Make bind reference function internals not copy them. Fix scoped vars in bind (fix #533)
|
||||
|
||||
@ -101,16 +101,22 @@ void sdSPISetup(JsVar *spi, Pin csPin) {
|
||||
if (isSdSPISetup()) DESELECT();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* Receive a byte from MMC via SPI */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
static void xmit_spi_buf (BYTE *data, UINT len)
|
||||
/* Transmit bytes from MMC via SPI - leave array alone */
|
||||
static void write_spi_buf (BYTE *data, UINT len)
|
||||
{
|
||||
jsspiSend(sdSPI, JSSPI_NO_RECEIVE, (char*)data, len);
|
||||
}
|
||||
|
||||
/* Transmit bytes from MMC via SPI - writes result back into array */
|
||||
static void xfer_spi_buf (BYTE *data, UINT len)
|
||||
{
|
||||
jsspiSend(sdSPI, 0, (char*)data, len);
|
||||
}
|
||||
|
||||
static BYTE rcvr_spi (void)
|
||||
|
||||
/* Receive a byte from MMC via SPI */
|
||||
static BYTE read_spi_byte (void)
|
||||
{
|
||||
char data = 0xFF;
|
||||
jsspiSend(sdSPI, 0, &data, 1);
|
||||
@ -131,9 +137,9 @@ BYTE wait_ready (void)
|
||||
|
||||
JsSysTime endTime = jshGetSystemTime()+jshGetTimeFromMilliseconds(500); /* Wait for ready in timeout of 500ms */
|
||||
|
||||
rcvr_spi();
|
||||
read_spi_byte();
|
||||
do
|
||||
res = rcvr_spi();
|
||||
res = read_spi_byte();
|
||||
while ((res != 0xFF) && (jshGetSystemTime() < endTime));
|
||||
|
||||
return res;
|
||||
@ -149,7 +155,7 @@ static
|
||||
void release_spi (void)
|
||||
{
|
||||
DESELECT();
|
||||
rcvr_spi();
|
||||
read_spi_byte();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
@ -199,17 +205,17 @@ bool rcvr_datablock (
|
||||
|
||||
JsSysTime endTime = jshGetSystemTime()+jshGetTimeFromMilliseconds(100); /* Wait for data packet in timeout of 100ms */
|
||||
do {
|
||||
token = rcvr_spi();
|
||||
token = read_spi_byte();
|
||||
} while ((token == 0xFF) && (jshGetSystemTime() < endTime));
|
||||
if(token != 0xFE) return FALSE; /* If not valid data token, return with error */
|
||||
|
||||
UINT i;
|
||||
for (i=0;i<btr;i++)
|
||||
buff[i] = 0xFF; // make sure we send 0xFF
|
||||
xmit_spi_buf(buff, btr);
|
||||
xfer_spi_buf(buff, btr);
|
||||
|
||||
BYTE crc[2] = {0xFF,0xFF};
|
||||
xmit_spi_buf(crc, 2); // discard 2 byte CRC
|
||||
write_spi_buf(crc, 2); // discard 2 byte CRC
|
||||
|
||||
return TRUE; /* Return with success */
|
||||
}
|
||||
@ -229,13 +235,12 @@ bool xmit_datablock (
|
||||
{
|
||||
if (wait_ready() != 0xFF) return FALSE;
|
||||
|
||||
xmit_spi_buf(&token, 1); /* Xmit data token */
|
||||
write_spi_buf(&token, 1); /* Xmit data token */
|
||||
if (token != 0xFD) { /* Is data token */
|
||||
|
||||
xmit_spi_buf((BYTE *)buff, 512); /* Xmit the 512 byte data block to MMC */
|
||||
write_spi_buf((BYTE *)buff, 512); /* Xmit the 512 byte data block to MMC */
|
||||
|
||||
BYTE resp[3] = {0xFF,0xFF,0xFF};
|
||||
xmit_spi_buf(resp, 3); // discard 2 byte CRC and get 1 byte response
|
||||
xfer_spi_buf(resp, 3); // discard 2 byte CRC and get 1 byte response
|
||||
if ((resp[2] & 0x1F) != 0x05) /* If not accepted, return with error */
|
||||
return FALSE;
|
||||
}
|
||||
@ -284,14 +289,14 @@ BYTE send_cmd (
|
||||
/* Argument[7..0] */
|
||||
/* CRC */
|
||||
BYTE packet[6] = {cmd, (BYTE)(arg >> 24), (BYTE)(arg >> 16), (BYTE)(arg >> 8), (BYTE)(arg), n};
|
||||
xmit_spi_buf(packet, 6); // discard 2 byte CRC and get 1 byte response
|
||||
xfer_spi_buf(packet, 6); // discard 2 byte CRC and get 1 byte response
|
||||
|
||||
/* Receive command response */
|
||||
if (cmd == CMD12) rcvr_spi(); /* Skip a stuff byte when stop reading */
|
||||
if (cmd == CMD12) read_spi_byte(); /* Skip a stuff byte when stop reading */
|
||||
|
||||
n = 10; /* Wait for a valid response in timeout of 10 attempts */
|
||||
do
|
||||
res = rcvr_spi();
|
||||
res = read_spi_byte();
|
||||
while ((res & 0x80) && --n);
|
||||
|
||||
return res; /* Return with the response value */
|
||||
@ -321,17 +326,17 @@ DSTATUS disk_initialize (
|
||||
if (Stat & STA_NODISK) return Stat; /* No card in the socket */
|
||||
|
||||
power_on(); /* Force socket power on */
|
||||
for (n = 10; n; n--) rcvr_spi(); /* 80 dummy clocks */
|
||||
for (n = 10; n; n--) read_spi_byte(); /* 80 dummy clocks */
|
||||
|
||||
ty = 0;
|
||||
if (send_cmd(CMD0, 0) == 1) { /* Enter Idle state */
|
||||
JsSysTime endTime = jshGetSystemTime()+jshGetTimeFromMilliseconds(1000); /* Initialization timeout of 1000 msec */
|
||||
if (send_cmd(CMD8, 0x1AA) == 1) { /* SDHC */
|
||||
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi(); /* Get trailing return value of R7 resp */
|
||||
for (n = 0; n < 4; n++) ocr[n] = read_spi_byte(); /* Get trailing return value of R7 resp */
|
||||
if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* The card can work at vdd range of 2.7-3.6V */
|
||||
while ((jshGetSystemTime()<endTime) && send_cmd(ACMD41, 1UL << 30)); /* Wait for leaving idle state (ACMD41 with HCS bit) */
|
||||
if ((jshGetSystemTime()<endTime) && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */
|
||||
for (n = 0; n < 4; n++) ocr[n] = rcvr_spi();
|
||||
for (n = 0; n < 4; n++) ocr[n] = read_spi_byte();
|
||||
ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;
|
||||
}
|
||||
}
|
||||
@ -530,9 +535,9 @@ DRESULT disk_ioctl (
|
||||
case GET_BLOCK_SIZE : /* Get erase block size in unit of sector (DWORD) */
|
||||
if (CardType & CT_SD2) { /* SDC ver 2.00 */
|
||||
if (send_cmd(ACMD13, 0) == 0) { /* Read SD status */
|
||||
rcvr_spi();
|
||||
read_spi_byte();
|
||||
if (rcvr_datablock(csd, 16)) { /* Read partial block */
|
||||
for (n = 64 - 16; n; n--) rcvr_spi(); /* Purge trailing data */
|
||||
for (n = 64 - 16; n; n--) read_spi_byte(); /* Purge trailing data */
|
||||
*(DWORD*)buff = 16UL << (csd[10] >> 4);
|
||||
res = RES_OK;
|
||||
}
|
||||
@ -568,14 +573,14 @@ DRESULT disk_ioctl (
|
||||
|
||||
case MMC_GET_OCR : /* Receive OCR as an R3 resp (4 bytes) */
|
||||
if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */
|
||||
for (n = 4; n; n--) *ptr++ = rcvr_spi();
|
||||
for (n = 4; n; n--) *ptr++ = read_spi_byte();
|
||||
res = RES_OK;
|
||||
}
|
||||
break;
|
||||
|
||||
case MMC_GET_SDSTAT : /* Receive SD status as a data block (64 bytes) */
|
||||
if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */
|
||||
rcvr_spi();
|
||||
read_spi_byte();
|
||||
if (rcvr_datablock(ptr, 64))
|
||||
res = RES_OK;
|
||||
}
|
||||
|
||||
12
src/jsspi.c
12
src/jsspi.c
@ -134,17 +134,25 @@ bool jsspiSend(JsVar *spiDevice, JsSpiSendFlags flags, char *buf, size_t len) {
|
||||
spi_sender_data spiSendData;
|
||||
if (!jsspiGetSendFunction(spiDevice, &spiSend, &spiSendData))
|
||||
return false;
|
||||
// TODO: we could go faster if JSSPI_NO_RECEIVE is set
|
||||
|
||||
size_t txPtr = 0;
|
||||
size_t rxPtr = 0;
|
||||
// transmit the data
|
||||
while (txPtr<len && !jspIsInterrupted()) {
|
||||
int data = spiSend(buf[txPtr++], &spiSendData);
|
||||
if (data>=0) buf[rxPtr++] = (char)data;
|
||||
if (data>=0) {
|
||||
if (!(flags&JSSPI_NO_RECEIVE))
|
||||
buf[rxPtr] = (char)data;
|
||||
rxPtr++;
|
||||
}
|
||||
}
|
||||
// clear the rx buffer
|
||||
while (rxPtr<len && !jspIsInterrupted()) {
|
||||
buf[rxPtr++] = (char)spiSend(-1, &spiSendData);
|
||||
int data = spiSend(-1, &spiSendData);
|
||||
if (!(flags&JSSPI_NO_RECEIVE))
|
||||
buf[rxPtr] = (char)data;
|
||||
rxPtr++;
|
||||
}
|
||||
// wait if we need to
|
||||
if (flags & JSSPI_WAIT) {
|
||||
|
||||
@ -23,7 +23,7 @@ void jsspiPopulateSPIInfo(JshSPIInfo *inf, JsVar *options);
|
||||
bool jsspiGetSendFunction(JsVar *spiDevice, spi_sender *spiSend, spi_sender_data *spiSendData);
|
||||
|
||||
typedef enum {
|
||||
// JSSPI_NO_RECEIVE = 1, // currently we *always* receive
|
||||
JSSPI_NO_RECEIVE = 1,
|
||||
JSSPI_WAIT = 2,
|
||||
} JsSpiSendFlags;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user