disk: sdhc: use the multiple block transfer for writing
The sdhc_spi_write_multi function is sending the CMD25 for multiple block write operation on the SD card instead of looping the CMD24. This is improving the transfer speed compared to the sdhc_spi_write function when the nb of blocks to write is significant (more than 2). Signed-off-by: Francois Ramu <francois.ramu@st.com>
This commit is contained in:
parent
c505ca38cf
commit
9a94168e78
1 changed files with 94 additions and 5 deletions
|
@ -748,6 +748,85 @@ error:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this function is optimized to write multiple blocks */
|
||||||
|
static int sdhc_spi_write_multi(struct sdhc_spi_data *data,
|
||||||
|
const uint8_t *buf, uint32_t sector, uint32_t count)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
uint32_t addr;
|
||||||
|
uint8_t block[SDHC_CRC16_SIZE];
|
||||||
|
|
||||||
|
err = sdhc_map_disk_status(data->status);
|
||||||
|
if (err != 0) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data->high_capacity) {
|
||||||
|
addr = sector;
|
||||||
|
} else {
|
||||||
|
addr = sector * SDMMC_DEFAULT_BLOCK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sdhc_spi_cmd_r1(data, SDHC_WRITE_MULTIPLE_BLOCK, addr);
|
||||||
|
if (err < 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the blocks */
|
||||||
|
for (; count != 0U; count--) {
|
||||||
|
/* Start the block */
|
||||||
|
block[0] = SDHC_TOKEN_MULTI_WRITE;
|
||||||
|
err = sdhc_spi_tx(data, block, 1);
|
||||||
|
if (err != 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the payload */
|
||||||
|
err = sdhc_spi_tx(data, buf, SDMMC_DEFAULT_BLOCK_SIZE);
|
||||||
|
if (err != 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build and write the trailing CRC */
|
||||||
|
sys_put_be16(crc16_itu_t(0, buf, SDMMC_DEFAULT_BLOCK_SIZE),
|
||||||
|
block);
|
||||||
|
|
||||||
|
err = sdhc_spi_tx(data, block, sizeof(block));
|
||||||
|
if (err != 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = sdhc_map_data_status(sdhc_spi_rx_u8(data));
|
||||||
|
if (err != 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for the card to finish programming */
|
||||||
|
err = sdhc_spi_skip_until_ready(data);
|
||||||
|
if (err != 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf += SDMMC_DEFAULT_BLOCK_SIZE;
|
||||||
|
sector++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop the transmission */
|
||||||
|
sdhc_spi_tx_cmd(data, SDHC_STOP_TRANSMISSION, 0);
|
||||||
|
|
||||||
|
/* Wait for the card to finish operation */
|
||||||
|
err = sdhc_spi_skip_until_ready(data);
|
||||||
|
if (err != 0) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = 0;
|
||||||
|
exit:
|
||||||
|
spi_release(data->spi, &data->cfg);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static int disk_spi_sdhc_init(const struct device *dev);
|
static int disk_spi_sdhc_init(const struct device *dev);
|
||||||
|
|
||||||
static int sdhc_spi_init(const struct device *dev)
|
static int sdhc_spi_init(const struct device *dev)
|
||||||
|
@ -808,14 +887,24 @@ static int disk_spi_sdhc_access_write(struct disk_info *disk,
|
||||||
struct sdhc_spi_data *data = dev->data;
|
struct sdhc_spi_data *data = dev->data;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
LOG_DBG("sector=%u count=%u", sector, count);
|
/* for more than 2 blocks the multiple block is preferred */
|
||||||
|
if (count > 2) {
|
||||||
|
LOG_DBG("multi block sector=%u count=%u", sector, count);
|
||||||
|
|
||||||
|
err = sdhc_spi_write_multi(data, buf, sector, count);
|
||||||
|
if (err != 0 && sdhc_is_retryable(err)) {
|
||||||
|
sdhc_spi_recover(data);
|
||||||
|
err = sdhc_spi_write_multi(data, buf, sector, count);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG_DBG("sector=%u count=%u", sector, count);
|
||||||
|
|
||||||
err = sdhc_spi_write(data, buf, sector, count);
|
|
||||||
if (err != 0 && sdhc_is_retryable(err)) {
|
|
||||||
sdhc_spi_recover(data);
|
|
||||||
err = sdhc_spi_write(data, buf, sector, count);
|
err = sdhc_spi_write(data, buf, sector, count);
|
||||||
|
if (err != 0 && sdhc_is_retryable(err)) {
|
||||||
|
sdhc_spi_recover(data);
|
||||||
|
err = sdhc_spi_write(data, buf, sector, count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue