summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2021-05-14 14:10:37 +1000
committerDamien George <damien@micropython.org>2021-05-21 00:08:13 +1000
commita96afae90f6e5d693173382561d06e583b0b5fa5 (patch)
tree1ed84c071f5913770c24d830d90f4d6d0417217d
parent5176a2d7325d941d8f2f41b31eab87b6e7a83f06 (diff)
stm32/sdio: Fix case of SDIO DMA turning off mid transfer.
The DMA driver will turn off DMA if it hasn't been used for an amount of time (to save power). The SDIO driver for cyw43 WLAN was not informing the DMA driver that it was using DMA and there was a chance that the DMA would turn off in the middle of an SDIO DMA transfer. The symptoms of this would be printing of SDIO error messages and a failure to communicate with the cyw43 WLAN module. This commit fixes this issue by changing the SDIO driver to use the dma_nohal_XXX API to initialise and start the DMA. Signed-off-by: Damien George <damien@micropython.org>
-rw-r--r--ports/stm32/dma.c2
-rw-r--r--ports/stm32/sdio.c35
2 files changed, 20 insertions, 17 deletions
diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c
index 4320315ba..d4b41771b 100644
--- a/ports/stm32/dma.c
+++ b/ports/stm32/dma.c
@@ -40,7 +40,7 @@
#define DMA_IDLE_TICK_MAX (8) // 8*8 = 64 msec
#define DMA_IDLE_TICK(tick) (((tick) & ~(SYSTICK_DISPATCH_NUM_SLOTS - 1) & DMA_SYSTICK_MASK) == 0)
-#define ENABLE_SDIO (MICROPY_HW_ENABLE_SDCARD || MICROPY_HW_ENABLE_MMCARD)
+#define ENABLE_SDIO (MICROPY_HW_ENABLE_SDCARD || MICROPY_HW_ENABLE_MMCARD || MICROPY_PY_NETWORK_CYW43)
typedef enum {
dma_id_not_defined=-1,
diff --git a/ports/stm32/sdio.c b/ports/stm32/sdio.c
index dfd409257..0291e3e81 100644
--- a/ports/stm32/sdio.c
+++ b/ports/stm32/sdio.c
@@ -28,6 +28,7 @@
#include "py/mperrno.h"
#include "py/mphal.h"
+#include "dma.h"
#include "pin.h"
#include "pin_static_af.h"
#include "pendsv.h"
@@ -382,27 +383,21 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le
}
#if defined(STM32F7)
- DMA2->LIFCR = 0x3f << 22;
- DMA2_Stream3->FCR = 0x07; // ?
- DMA2_Stream3->PAR = (uint32_t)&SDMMC->FIFO;
if ((uint32_t)buf & 3) {
printf("sdio_transfer_cmd53: buf=%p is not aligned for DMA\n", buf);
return -MP_EINVAL;
}
- DMA2_Stream3->M0AR = (uint32_t)buf;
- DMA2_Stream3->NDTR = ((len + block_size - 1) & ~(block_size - 1)) / 4;
- DMA2_Stream3->CR = 4 << 25 // channel 4
- | 1 << 23 // MBURST INCR4
- | 1 << 21 // PBURST INCR4
- | 3 << 16 // PL very high
- | 2 << 13 // MSIZE word
- | 2 << 11 // PSIZE word
- | 1 << 10 // MINC enabled
- | 0 << 9 // PINC disabled
- | write << 6 // DIR mem-to-periph
- | 1 << 5 // PFCTRL periph is flow controller
- | 1 << 0 // EN
+ uint32_t dma_config =
+ 2 << DMA_SxCR_MSIZE_Pos // MSIZE word
+ | 2 << DMA_SxCR_PSIZE_Pos // PSIZE word
+ | write << DMA_SxCR_DIR_Pos // DIR mem-to-periph
+ | 1 << DMA_SxCR_PFCTRL_Pos // PFCTRL periph is flow controller
;
+ uint32_t dma_src = (uint32_t)buf;
+ uint32_t dma_dest = (uint32_t)&SDMMC->FIFO;
+ uint32_t dma_len = ((len + block_size - 1) & ~(block_size - 1)) / 4;
+ dma_nohal_init(&dma_SDIO_0, dma_config);
+ dma_nohal_start(&dma_SDIO_0, dma_src, dma_dest, dma_len);
#else
SDMMC->IDMABASE0 = (uint32_t)buf;
SDMMC->IDMACTRL = SDMMC_IDMA_IDMAEN;
@@ -456,6 +451,9 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le
#else
printf("sdio_transfer_cmd53: timeout wr=%d len=%u dma=%u buf_idx=%u STA=%08x SDMMC=%08x:%08x IDMA=%08x\n", write, (uint)len, (uint)dma, sdmmc_buf_cur - buf, (uint)SDMMC->STA, (uint)SDMMC->DCOUNT, (uint)SDMMC->DCTRL, (uint)SDMMC->IDMACTRL);
#endif
+ if (sdmmc_dma) {
+ dma_nohal_deinit(&dma_SDIO_0);
+ }
return -MP_ETIMEDOUT;
}
}
@@ -468,6 +466,9 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le
#else
printf("sdio_transfer_cmd53: error=%08lx wr=%d len=%u dma=%u buf_idx=%u STA=%08x SDMMC=%08x:%08x IDMA=%08x\n", sdmmc_error, write, (uint)len, (uint)dma, sdmmc_buf_cur - buf, (uint)SDMMC->STA, (uint)SDMMC->DCOUNT, (uint)SDMMC->DCTRL, (uint)SDMMC->IDMACTRL);
#endif
+ if (sdmmc_dma) {
+ dma_nohal_deinit(&dma_SDIO_0);
+ }
return -(0x1000000 | sdmmc_error);
}
@@ -476,6 +477,8 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le
printf("sdio_transfer_cmd53: didn't transfer correct length: cur=%p top=%p\n", sdmmc_buf_cur, sdmmc_buf_top);
return -MP_EIO;
}
+ } else {
+ dma_nohal_deinit(&dma_SDIO_0);
}
return 0;