Skip to content

Commit

Permalink
stm32/sdio: Fix case of SDIO DMA turning off mid transfer.
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
dpgeorge committed May 20, 2021
1 parent 5176a2d commit a96afae
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 17 deletions.
2 changes: 1 addition & 1 deletion ports/stm32/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
35 changes: 19 additions & 16 deletions ports/stm32/sdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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);
}

Expand All @@ -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;
Expand Down

0 comments on commit a96afae

Please sign in to comment.