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.
This commit is contained in:
Jean-François Milants 2016-11-23 22:16:14 +01:00 committed by Damien George
parent a081b49d55
commit 08bd7d1d31
2 changed files with 14 additions and 0 deletions

View File

@ -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

View File

@ -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