Hi,
There is no easy solution to this. I have found a walk-around which is slower but eats less RAM and user only when the read/write buffer is misaligned. On other case the standard multiblock read is used.
/**
* @brief Read Sector(s)
* @param drv : driver index
* @param buff : Pointer to the data buffer to store read data
* @param sector : Start sector number
* param count : Sector count (1..255)
* @retval DSTATUS : operation status
*/
DRESULT disk_read (
BYTE drv, /* Physical drive number (0) */
BYTE *buff, /* Pointer to the data buffer to store read data */
DWORD sector, /* Start sector number (LBA) */
UINT count /* Sector count (1..255) */
)
{
uint32_t timeout = 100000;
SD_Error sdstatus = SD_OK;
DWORD scratch [BLOCK_SIZE / 4] ; // Alignment ensured, need enough stack
portENTER_CRITICAL();
if (SD_Detect() != SD_PRESENT)
{
portEXIT_CRITICAL();
return(RES_NOTRDY);
}
if ((DWORD)buff & 3) // DMA Alignment issue, do single up to aligned buffer
{
while (count--)
{
SD_ReadBlock((BYTE *)scratch, (uint32_t )((sector + count) * BLOCK_SIZE) ,BLOCK_SIZE);
/* Check if the Transfer is finished */
sdstatus = SD_WaitReadOperation();
while(SD_GetStatus() != SD_TRANSFER_OK)
{
if (timeout-- == 0)
{
portEXIT_CRITICAL();
return RES_ERROR;
}
}
memcpy (&buff[count * BLOCK_SIZE] ,scratch, BLOCK_SIZE);
}
}
else
{
SD_ReadMultiBlocks((BYTE *)buff, (uint32_t )(sector * BLOCK_SIZE), BLOCK_SIZE, count);
/* Check if the Transfer is finished */
sdstatus = SD_WaitReadOperation();
while(SD_GetStatus() != SD_TRANSFER_OK)
{
if (timeout-- == 0)
{
portEXIT_CRITICAL();
return RES_ERROR;
}
}
}
if (sdstatus == SD_OK)
{
portEXIT_CRITICAL();
return RES_OK;
}
portEXIT_CRITICAL();
return RES_NOTRDY;
}
/**
* @brief write Sector(s)
* @param drv : driver index
* @param buff : Pointer to the data to be written
* @param sector : Start sector number
* @param count : Sector count (1..255)
* @retval DSTATUS : operation status
*/
#if _READONLY == 0
DRESULT disk_write (
BYTE drv, /* Physical drive number (0) */
const BYTE *buff, /* Pointer to the data to be written */
DWORD sector, /* Start sector number (LBA) */
UINT count /* Sector count (1..255) */
)
{
SD_Error sdstatus = SD_OK;
uint32_t timeout = 1000000;
DWORD scratch [BLOCK_SIZE / 4] ; // Alignment ensured, need enough stack
portENTER_CRITICAL();
if (SD_Detect() != SD_PRESENT)
{
portEXIT_CRITICAL();
return(RES_NOTRDY);
}
if ((DWORD)buff & 3) // DMA Alignment issue, do single up to aligned buffer
{
while (count--)
{
memcpy (scratch, &buff[count * BLOCK_SIZE], BLOCK_SIZE);
SD_WriteBlock((BYTE *)scratch, (uint32_t )((sector + count) * BLOCK_SIZE), BLOCK_SIZE);
/* Check if the Transfer is finished */
sdstatus = SD_WaitWriteOperation();
while(SD_GetStatus() != SD_TRANSFER_OK)
{
if (timeout-- == 0)
{
portEXIT_CRITICAL();
return RES_ERROR;
}
}
}
}
else
{
SD_WriteMultiBlocks((BYTE *)buff, (uint32_t )(sector * BLOCK_SIZE), BLOCK_SIZE, count);
/* Check if the Transfer is finished */
sdstatus = SD_WaitWriteOperation();
while(SD_GetStatus() != SD_TRANSFER_OK)
{
if (timeout-- == 0)
{
portEXIT_CRITICAL();
return RES_ERROR;
}
}
}
if (sdstatus == SD_OK)
{
portEXIT_CRITICAL();
return RES_OK;
}
portEXIT_CRITICAL();
return RES_NOTRDY;
}
#endif /* _READONLY == 0 */