summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-François Milants <jf@codingfield.com>2016-11-23 22:16:14 +0100
committerDamien George <damien.p.george@gmail.com>2016-12-02 13:51:09 +1100
commit08bd7d1d31a95331dad403adce8834c2d39ab3e8 (patch)
tree132141f1b0fed8e706c8a183d9e1e1d0c5d60cb4
parenta081b49d55ef409d612666d79a97e79259c8adba (diff)
stmhal/sdcard: Clean/invalidate cache before DMA transfers with SD card.
Add 2 macros in mphalport.h that clean and invalidate data caches only on STM32F7 MCUs. They are needed to ensure the cache coherency before/after DMA transferts. * MP_HAL_CLEANINVALIDATE_DCACHE cleans and invalidate the data cache. It must be called before starting a DMA transfer from the peripheral to the RAM memory. * MP_HAL_CLEAN_DCACHE cleans the data cache. It must be called before starting a DMA transfert from the RAM memory to the peripheral. These macros are called in sdcard.c, before reading from and writing to the SDCard, when DMA is used.
-rw-r--r--stmhal/mphalport.h6
-rw-r--r--stmhal/sdcard.c8
2 files changed, 14 insertions, 0 deletions
diff --git a/stmhal/mphalport.h b/stmhal/mphalport.h
index 5df053fa2..b55c9ccdc 100644
--- a/stmhal/mphalport.h
+++ b/stmhal/mphalport.h
@@ -6,10 +6,16 @@
// go in some MCU-specific header, but for now it lives here.
#if defined(MCU_SERIES_F4)
#define MP_HAL_UNIQUE_ID_ADDRESS (0x1fff7a10)
+#define MP_HAL_CLEANINVALIDATE_DCACHE(addr, size)
+#define MP_HAL_CLEAN_DCACHE(addr, size)
#elif defined(MCU_SERIES_F7)
#define MP_HAL_UNIQUE_ID_ADDRESS (0x1ff0f420)
+#define MP_HAL_CLEANINVALIDATE_DCACHE(addr, size) (SCB_CleanInvalidateDCache_by_Addr((uint32_t*)((uint32_t)addr & ~0x1f), ((uint32_t)(addr + size + 0x1f) & ~0x1f) - ((uint32_t)addr & ~0x1f)))
+#define MP_HAL_CLEAN_DCACHE(addr, size) (SCB_CleanDCache_by_Addr((uint32_t*)((uint32_t)addr & ~0x1f), ((uint32_t)(addr + size + 0x1f) & ~0x1f) - ((uint32_t)addr & ~0x1f)))
#elif defined(MCU_SERIES_L4)
#define MP_HAL_UNIQUE_ID_ADDRESS (0x1fff7590)
+#define MP_HAL_CLEANINVALIDATE_DCACHE(addr, size)
+#define MP_HAL_CLEAN_DCACHE(addr, size)
#else
#error mphalport.h: Unrecognized MCU_SERIES
#endif
diff --git a/stmhal/sdcard.c b/stmhal/sdcard.c
index a2aa4c84d..f7cf15343 100644
--- a/stmhal/sdcard.c
+++ b/stmhal/sdcard.c
@@ -30,6 +30,7 @@
#include "py/runtime.h"
#include "lib/fatfs/ff.h"
#include "extmod/fsusermount.h"
+#include "mphalport.h"
#include "sdcard.h"
#include "pin.h"
@@ -221,6 +222,10 @@ mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blo
dma_init(&sd_rx_dma, &dma_SDIO_0_RX, &sd_handle);
sd_handle.hdmarx = &sd_rx_dma;
+ // make sure cache is flushed and invalidated so when DMA updates the RAM
+ // from reading the peripheral the CPU then reads the new data
+ MP_HAL_CLEANINVALIDATE_DCACHE(dest, num_blocks * SDCARD_BLOCK_SIZE);
+
err = HAL_SD_ReadBlocks_BlockNumber_DMA(&sd_handle, (uint32_t*)dest, block_num, SDCARD_BLOCK_SIZE, num_blocks);
if (err == SD_OK) {
// wait for DMA transfer to finish, with a large timeout
@@ -277,6 +282,9 @@ mp_uint_t sdcard_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t n
dma_init(&sd_tx_dma, &dma_SDIO_0_TX, &sd_handle);
sd_handle.hdmatx = &sd_tx_dma;
+ // make sure cache is flushed to RAM so the DMA can read the correct data
+ MP_HAL_CLEAN_DCACHE(src, num_blocks * SDCARD_BLOCK_SIZE);
+
err = HAL_SD_WriteBlocks_BlockNumber_DMA(&sd_handle, (uint32_t*)src, block_num, SDCARD_BLOCK_SIZE, num_blocks);
if (err == SD_OK) {
// wait for DMA transfer to finish, with a large timeout