8000 stm32/sdio: Fix case of SDIO DMA turning off mid transfer. · larsks/micropython@a96afae · GitHub
[go: up one dir, main page]

Skip to content

Commit a96afae

Browse files
committed
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>
1 parent 5176a2d commit a96afae

File tree

2 files changed

+20
-17
lines changed

2 files changed

+20
-17
lines changed

ports/stm32/dma.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
#define DMA_IDLE_TICK_MAX (8) // 8*8 = 64 msec
4141
#define DMA_IDLE_TICK(tick) (((tick) & ~(SYSTICK_DISPATCH_NUM_SLOTS - 1) & DMA_SYSTICK_MASK) == 0)
4242

43-
#define ENABLE_SDIO (MICROPY_HW_ENABLE_SDCARD || MICROPY_HW_ENABLE_MMCARD)
43+
#define ENABLE_SDIO (MICROPY_HW_ENABLE_SDCARD || MICROPY_HW_ENABLE_MMCARD || MICROPY_PY_NETWORK_CYW43)
4444

4545
typedef enum {
4646
dma_id_not_defined=-1,

ports/stm32/sdio.c

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#include "py/mperrno.h"
3030
#include "py/mphal.h"
31+
#include "dma.h"
3132
#include "pin.h"
3233
#include "pin_static_af.h"
3334
#include "pendsv.h"
@@ -382,27 +383,21 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le
382383
}
383384

384385
#if defined(STM32F7)
385-
DMA2->LIFCR = 0x3f << 22;
386-
DMA2_Stream3->FCR = 0x07; // ?
387-
DMA2_Stream3->PAR = (uint32_t)&SDMMC->FIFO;
388386
if ((uint32_t)buf & 3) {
389387
printf("sdio_transfer_cmd53: buf=%p is not aligned for DMA\n", buf);
390388
return -MP_EINVAL;
391389
}
392-
DMA2_Stream3->M0AR = (uint32_t)buf;
393-
DMA2_Stream3->NDTR = ((len + block_size - 1) & ~(block_size - 1)) / 4;
394-
DMA2_Stream3->CR = 4 << 25 // channel 4
395-
| 1 << 23 // MBURST INCR4
396-
| 1 << 21 // PBURST INCR4
397-
| 3 << 16 // PL very high
398-
| 2 << 13 // MSIZE word
399-
| 2 << 11 // PSIZE word
400-
| 1 << 10 // MINC enabled
401-
| 0 << 9 // PINC disabled
402-
| write << 6 // DIR mem-to-periph
403-
| 1 << 5 // PFCTRL periph is flow controller
404-
| 1 << 0 // EN
390+
uint32_t dma_config =
391+
2 << DMA_SxCR_MSIZE_Pos // MSIZE word
392+
| 2 << DMA_SxCR_PSIZE_Pos // PSIZE word
393+
| write << DMA_SxCR_DIR_Pos // DIR mem-to-periph
394+
| 1 << DMA_SxCR_PFCTRL_Pos // PFCTRL periph is flow controller
405395
;
396+
uint32_t dma_src = (uint32_t)buf;
397+
uint32_t dma_dest = (uint32_t)&SDMMC->FIFO;
398+
uint32_t dma_len = ((len + block_size - 1) & ~(block_size - 1)) / 4;
399+
dma_nohal_init(&dma_SDIO_0, dma_config);
400+
dma_nohal_start(&dma_SDIO_0, dma_src, dma_dest, dma_len);
406401
#else
407402
SDMMC->IDMABASE0 = (uint32_t)buf;
408403
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
456451
#else
457452
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);
458453
#endif
454+
if (sdmmc_dma) {
455+
dma_nohal_deinit(&dma_SDIO_0);
456+
}
459457
return -MP_ETIMEDOUT;
460458
}
461459
}
@@ -468,6 +466,9 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le
468466
#else
469467
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);
470468
#endif
469+
if (sdmmc_dma) {
470+
dma_nohal_deinit(&dma_SDIO_0);
471+
}
471472
return -(0x1000000 | sdmmc_error);
472473
}
473474

@@ -476,6 +477,8 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le
476477
printf("sdio_transfer_cmd53: didn't transfer correct length: cur=%p top=%p\n", sdmmc_buf_cur, sdmmc_buf_top);
477478
return -MP_EIO;
478479
}
480+
} else {
481+
dma_nohal_deinit(&dma_SDIO_0);
479482
}
480483

481484
return 0;

0 commit comments

Comments
 (0)
0