Work around yet another ChibiOS DMA/Cache bug
This commit is contained in:
parent
8bf95a1128
commit
cd4c389e48
@ -12,26 +12,39 @@
|
|||||||
#include "gfile_fatfs_wrapper.h"
|
#include "gfile_fatfs_wrapper.h"
|
||||||
|
|
||||||
#if HAL_USE_MMC_SPI && HAL_USE_SDC
|
#if HAL_USE_MMC_SPI && HAL_USE_SDC
|
||||||
#error "cannot specify both MMC_SPI and SDC drivers"
|
#error "cannot specify both MMC_SPI and SDC drivers"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAL_USE_MMC_SPI
|
#if HAL_USE_MMC_SPI
|
||||||
extern MMCDriver MMCD1;
|
extern MMCDriver MMCD1;
|
||||||
#elif HAL_USE_SDC
|
#elif HAL_USE_SDC
|
||||||
extern SDCDriver SDCD1;
|
extern SDCDriver SDCD1;
|
||||||
#else
|
#else
|
||||||
#error "MMC_SPI or SDC driver must be specified"
|
#error "MMC_SPI or SDC driver must be specified"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Correspondence between physical drive number and physical drive. */
|
/* Correspondence between physical drive number and physical drive. */
|
||||||
|
|
||||||
#define MMC 0
|
#define MMC 0
|
||||||
#define SDC 0
|
#define SDC 0
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Initialize a Drive */
|
|
||||||
|
|
||||||
|
// WOW - Bugs galore!!! (in ChibiOS)
|
||||||
|
// Bugs:
|
||||||
|
// 1. ChibiOS DMA operations do not do the appropriate cache flushing or invalidating
|
||||||
|
// on cpu's that require it eg STM32F7 series.
|
||||||
|
// Instead they provide explicit dmaBufferInvalidate and dmaBufferFlush calls
|
||||||
|
// and rely on the user to explicitly flush the cache.
|
||||||
|
// Solution: We explicitly flush the cache after any possible DMA operation.
|
||||||
|
// 2. Unfortunately these explicit routines also have a bug. They assume that the
|
||||||
|
// specified data structure is aligned on a cache line boundary - not a good assumption.
|
||||||
|
// Solution: We increase the size provided to ChibiOS so that it does it properly.
|
||||||
|
// This assumes of course that we know the size of the cpu cache line.
|
||||||
|
#define CPU_CACHE_LINE_SIZE 32
|
||||||
|
#define CACHE_FLUSH(buf, sz) dmaBufferFlush((buf), (sz)+(CPU_CACHE_LINE_SIZE-1))
|
||||||
|
#define CACHE_INVALIDATE(buf, sz) dmaBufferInvalidate((buf), (sz)+(CPU_CACHE_LINE_SIZE-1))
|
||||||
|
|
||||||
|
/* Initialize a Drive */
|
||||||
DSTATUS disk_initialize (
|
DSTATUS disk_initialize (
|
||||||
BYTE drv /* Physical drive nmuber (0..) */
|
BYTE drv /* Physical drive nmuber (0..) */
|
||||||
)
|
)
|
||||||
@ -116,7 +129,7 @@ DRESULT disk_read (
|
|||||||
return RES_NOTRDY;
|
return RES_NOTRDY;
|
||||||
if (mmcStartSequentialRead(&MMCD1, sector))
|
if (mmcStartSequentialRead(&MMCD1, sector))
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
dmaBufferFlush(buff, MMCSD_BLOCK_SIZE*count);
|
CACHE_FLUSH(buff, MMCSD_BLOCK_SIZE*count);
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
if (mmcSequentialRead(&MMCD1, buff))
|
if (mmcSequentialRead(&MMCD1, buff))
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
@ -125,16 +138,16 @@ DRESULT disk_read (
|
|||||||
}
|
}
|
||||||
if (mmcStopSequentialRead(&MMCD1))
|
if (mmcStopSequentialRead(&MMCD1))
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
dmaBufferInvalidate(buff, MMCSD_BLOCK_SIZE*count);
|
CACHE_INVALIDATE(buff, MMCSD_BLOCK_SIZE*count);
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
#else
|
#else
|
||||||
case SDC:
|
case SDC:
|
||||||
if (blkGetDriverState(&SDCD1) != BLK_READY)
|
if (blkGetDriverState(&SDCD1) != BLK_READY)
|
||||||
return RES_NOTRDY;
|
return RES_NOTRDY;
|
||||||
dmaBufferFlush(buff, MMCSD_BLOCK_SIZE*count);
|
CACHE_FLUSH(buff, MMCSD_BLOCK_SIZE*count);
|
||||||
if (sdcRead(&SDCD1, sector, buff, count))
|
if (sdcRead(&SDCD1, sector, buff, count))
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
dmaBufferInvalidate(buff, MMCSD_BLOCK_SIZE*count);
|
CACHE_INVALIDATE(buff, MMCSD_BLOCK_SIZE*count);
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -163,7 +176,7 @@ DRESULT disk_write (
|
|||||||
return RES_WRPRT;
|
return RES_WRPRT;
|
||||||
if (mmcStartSequentialWrite(&MMCD1, sector))
|
if (mmcStartSequentialWrite(&MMCD1, sector))
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
dmaBufferFlush(buff, MMCSD_BLOCK_SIZE*count);
|
CACHE_FLUSH(buff, MMCSD_BLOCK_SIZE*count);
|
||||||
while (count > 0) {
|
while (count > 0) {
|
||||||
if (mmcSequentialWrite(&MMCD1, buff))
|
if (mmcSequentialWrite(&MMCD1, buff))
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
@ -177,7 +190,7 @@ DRESULT disk_write (
|
|||||||
case SDC:
|
case SDC:
|
||||||
if (blkGetDriverState(&SDCD1) != BLK_READY)
|
if (blkGetDriverState(&SDCD1) != BLK_READY)
|
||||||
return RES_NOTRDY;
|
return RES_NOTRDY;
|
||||||
dmaBufferFlush(buff, MMCSD_BLOCK_SIZE*count);
|
CACHE_FLUSH(buff, MMCSD_BLOCK_SIZE*count);
|
||||||
if (sdcWrite(&SDCD1, sector, buff, count))
|
if (sdcWrite(&SDCD1, sector, buff, count))
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
@ -247,7 +260,7 @@ DRESULT disk_ioctl (
|
|||||||
|
|
||||||
DWORD get_fattime(void) {
|
DWORD get_fattime(void) {
|
||||||
RTCDateTime timespec;
|
RTCDateTime timespec;
|
||||||
|
|
||||||
rtcGetTime(&RTCD1, ×pec);
|
rtcGetTime(&RTCD1, ×pec);
|
||||||
return rtcConvertDateTimeToFAT(×pec);
|
return rtcConvertDateTimeToFAT(×pec);
|
||||||
}
|
}
|
||||||
|
@ -10,21 +10,35 @@
|
|||||||
#if GFX_USE_GFILE && GFILE_NEED_PETITFS && GFX_USE_OS_CHIBIOS && !GFILE_PETITFS_EXTERNAL_LIB
|
#if GFX_USE_GFILE && GFILE_NEED_PETITFS && GFX_USE_OS_CHIBIOS && !GFILE_PETITFS_EXTERNAL_LIB
|
||||||
|
|
||||||
#include "gfile_petitfs_wrapper.h"
|
#include "gfile_petitfs_wrapper.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#if HAL_USE_MMC_SPI && HAL_USE_SDC
|
#if HAL_USE_MMC_SPI && HAL_USE_SDC
|
||||||
#error "cannot specify both MMC_SPI and SDC drivers"
|
#error "cannot specify both MMC_SPI and SDC drivers"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HAL_USE_MMC_SPI
|
#if HAL_USE_MMC_SPI
|
||||||
extern MMCDriver MMCD1;
|
extern MMCDriver MMCD1;
|
||||||
#elif HAL_USE_SDC
|
#elif HAL_USE_SDC
|
||||||
extern SDCDriver SDCD1;
|
extern SDCDriver SDCD1;
|
||||||
#else
|
#else
|
||||||
#error "MMC_SPI or SDC driver must be specified"
|
#error "MMC_SPI or SDC driver must be specified"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// WOW - Bugs galore!!! (in ChibiOS)
|
||||||
|
// Bugs:
|
||||||
|
// 1. ChibiOS DMA operations do not do the appropriate cache flushing or invalidating
|
||||||
|
// on cpu's that require it eg STM32F7 series.
|
||||||
|
// Instead they provide explicit dmaBufferInvalidate and dmaBufferFlush calls
|
||||||
|
// and rely on the user to explicitly flush the cache.
|
||||||
|
// Solution: We explicitly flush the cache after any possible DMA operation.
|
||||||
|
// 2. Unfortunately these explicit routines also have a bug. They assume that the
|
||||||
|
// specified data structure is aligned on a cache line boundary - not a good assumption.
|
||||||
|
// Solution: We increase the size provided to ChibiOS so that it does it properly.
|
||||||
|
// This assumes of course that we know the size of the cpu cache line.
|
||||||
|
#define CPU_CACHE_LINE_SIZE 32
|
||||||
|
#define CACHE_FLUSH(buf, sz) dmaBufferFlush((buf), (sz)+(CPU_CACHE_LINE_SIZE-1))
|
||||||
|
#define CACHE_INVALIDATE(buf, sz) dmaBufferInvalidate((buf), (sz)+(CPU_CACHE_LINE_SIZE-1))
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
/* Initialize a Drive */
|
/* Initialize a Drive */
|
||||||
|
|
||||||
@ -72,7 +86,7 @@ DRESULT disk_readp (
|
|||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
#endif
|
#endif
|
||||||
sectpos = sector;
|
sectpos = sector;
|
||||||
dmaBufferInvalidate(sectBuf, sizeof(sectBuf));
|
CACHE_INVALIDATE(sectBuf, sizeof(sectBuf));
|
||||||
}
|
}
|
||||||
memcpy(buff, sectBuf + offset, count);
|
memcpy(buff, sectBuf + offset, count);
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
|
Loading…
Reference in New Issue
Block a user