sdmmc: fix reads/writes to/from unaligned buffers

SDMMC hardware treats all buffers as aligned, and ignores 2 LSBs of
addresses written into DMA descriptors. Previously SDMMC host driver
assumed that data buffers passed from SDDMC command layer would be
aligned. However alignment checks were never implemented in the command
layer, as were the checks that the buffer coming from the application
would be in DMA capable memory. Most of the time this was indeed true.
However in some cases FATFS library can pass buffers offset by 2 bytes
from word boundary. “DMA capable” restriction may be broken if pSRAM
support is used.

This change adds buffer checks to the SDMMC host driver (alignment and
DMA capability), so that the host layer will error out for incompatible
buffers. In SDMMC command layer, a check is added to read and write
functions. If an incompatible buffer is passed from the application, new
buffer (512 bytes size) is allocated, and the transfer is performed
using {READ,WRITE}_SINGLE_BLOCK commands.
This commit is contained in:
Ivan Grokhotkov
2017-08-01 02:24:25 +08:00
parent 9314bf0d37
commit 512898edee
4 changed files with 173 additions and 36 deletions

View File

@@ -142,6 +142,8 @@ esp_err_t sdmmc_host_set_card_clk(int slot, uint32_t freq_khz);
* can call sdmmc_host_do_transaction as long as other sdmmc_host_*
* functions are not called.
*
* @attention Data buffer passed in cmdinfo->data must be in DMA capable memory
*
* @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1)
* @param cmdinfo pointer to structure describing command and data to transfer
* @return
@@ -149,6 +151,8 @@ esp_err_t sdmmc_host_set_card_clk(int slot, uint32_t freq_khz);
* - ESP_ERR_TIMEOUT if response or data transfer has timed out
* - ESP_ERR_INVALID_CRC if response or data transfer CRC check has failed
* - ESP_ERR_INVALID_RESPONSE if the card has sent an invalid response
* - ESP_ERR_INVALID_SIZE if the size of data transfer is not valid in SD protocol
* - ESP_ERR_INVALID_ARG if the data buffer is not in DMA capable memory
*/
esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo);