diff options
Diffstat (limited to 'ports/stm32/sdcard.c')
| -rw-r--r-- | ports/stm32/sdcard.c | 85 |
1 files changed, 64 insertions, 21 deletions
diff --git a/ports/stm32/sdcard.c b/ports/stm32/sdcard.c index 484426b84..27e7a34b2 100644 --- a/ports/stm32/sdcard.c +++ b/ports/stm32/sdcard.c @@ -33,14 +33,13 @@ #include "sdcard.h" #include "pin.h" -#include "genhdr/pins.h" #include "bufhelper.h" #include "dma.h" #include "irq.h" #if MICROPY_HW_HAS_SDCARD -#if defined(MCU_SERIES_F7) || defined(MCU_SERIES_L4) +#if defined(STM32F7) || defined(STM32H7) || defined(STM32L4) // The F7 has 2 SDMMC units but at the moment we only support using one of them in // a given build. If a boards config file defines MICROPY_HW_SDMMC2_CK then SDMMC2 @@ -81,7 +80,15 @@ #define SDIO_HARDWARE_FLOW_CONTROL_DISABLE SDMMC_HARDWARE_FLOW_CONTROL_DISABLE #define SDIO_HARDWARE_FLOW_CONTROL_ENABLE SDMMC_HARDWARE_FLOW_CONTROL_ENABLE +#if defined(STM32H7) +#define GPIO_AF12_SDIO GPIO_AF12_SDIO1 +#define SDIO_IRQHandler SDMMC1_IRQHandler +#define SDIO_TRANSFER_CLK_DIV SDMMC_NSpeed_CLK_DIV +#define SDIO_USE_GPDMA 0 +#else #define SDIO_TRANSFER_CLK_DIV SDMMC_TRANSFER_CLK_DIV +#define SDIO_USE_GPDMA 1 +#endif #else @@ -92,6 +99,7 @@ #define SDMMC_IRQn SDIO_IRQn #define SDMMC_TX_DMA dma_SDIO_0_TX #define SDMMC_RX_DMA dma_SDIO_0_RX +#define SDIO_USE_GPDMA 1 #endif @@ -117,7 +125,9 @@ // if an sd card is detected. This will save approx 260 bytes of RAM // when no sdcard was being used. static SD_HandleTypeDef sd_handle; +#if SDIO_USE_GPDMA static DMA_HandleTypeDef sd_rx_dma, sd_tx_dma; +#endif void sdcard_init(void) { // invalidate the sd_handle @@ -131,33 +141,39 @@ void sdcard_init(void) { // which clocks up to 25MHz maximum. #if defined(MICROPY_HW_SDMMC2_CK) // Use SDMMC2 peripheral with pins provided by the board's config - mp_hal_pin_config_alt(&MICROPY_HW_SDMMC2_CK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2); - mp_hal_pin_config_alt(&MICROPY_HW_SDMMC2_CMD, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2); - mp_hal_pin_config_alt(&MICROPY_HW_SDMMC2_D0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2); - mp_hal_pin_config_alt(&MICROPY_HW_SDMMC2_D1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2); - mp_hal_pin_config_alt(&MICROPY_HW_SDMMC2_D2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2); - mp_hal_pin_config_alt(&MICROPY_HW_SDMMC2_D3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2); + mp_hal_pin_config_alt(MICROPY_HW_SDMMC2_CK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2); + mp_hal_pin_config_alt(MICROPY_HW_SDMMC2_CMD, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2); + mp_hal_pin_config_alt(MICROPY_HW_SDMMC2_D0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2); + mp_hal_pin_config_alt(MICROPY_HW_SDMMC2_D1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2); + mp_hal_pin_config_alt(MICROPY_HW_SDMMC2_D2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2); + mp_hal_pin_config_alt(MICROPY_HW_SDMMC2_D3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2); #else // Default SDIO/SDMMC1 config - mp_hal_pin_config(&MICROPY_HW_SDMMC_D0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO); - mp_hal_pin_config(&MICROPY_HW_SDMMC_D1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO); - mp_hal_pin_config(&MICROPY_HW_SDMMC_D2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO); - mp_hal_pin_config(&MICROPY_HW_SDMMC_D3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO); - mp_hal_pin_config(&MICROPY_HW_SDMMC_CK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO); - mp_hal_pin_config(&MICROPY_HW_SDMMC_CMD, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO); + mp_hal_pin_config(MICROPY_HW_SDMMC_D0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO); + mp_hal_pin_config(MICROPY_HW_SDMMC_D1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO); + mp_hal_pin_config(MICROPY_HW_SDMMC_D2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO); + mp_hal_pin_config(MICROPY_HW_SDMMC_D3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO); + mp_hal_pin_config(MICROPY_HW_SDMMC_CK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO); + mp_hal_pin_config(MICROPY_HW_SDMMC_CMD, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO); #endif // configure the SD card detect pin // we do this here so we can detect if the SD card is inserted before powering it on - mp_hal_pin_config(&MICROPY_HW_SDCARD_DETECT_PIN, MP_HAL_PIN_MODE_INPUT, MICROPY_HW_SDCARD_DETECT_PULL, 0); + mp_hal_pin_config(MICROPY_HW_SDCARD_DETECT_PIN, MP_HAL_PIN_MODE_INPUT, MICROPY_HW_SDCARD_DETECT_PULL, 0); } void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { // enable SDIO clock SDMMC_CLK_ENABLE(); + #if defined(STM32H7) + // Reset SDMMC + __HAL_RCC_SDMMC1_FORCE_RESET(); + __HAL_RCC_SDMMC1_RELEASE_RESET(); + #endif + // NVIC configuration for SDIO interrupts - HAL_NVIC_SetPriority(SDMMC_IRQn, IRQ_PRI_SDIO, IRQ_SUBPRI_SDIO); + NVIC_SetPriority(SDMMC_IRQn, IRQ_PRI_SDIO); HAL_NVIC_EnableIRQ(SDMMC_IRQn); // GPIO have already been initialised by sdcard_init @@ -169,7 +185,7 @@ void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) { } bool sdcard_is_present(void) { - return HAL_GPIO_ReadPin(MICROPY_HW_SDCARD_DETECT_PIN.gpio, MICROPY_HW_SDCARD_DETECT_PIN.pin_mask) == MICROPY_HW_SDCARD_DETECT_PRESENT; + return HAL_GPIO_ReadPin(MICROPY_HW_SDCARD_DETECT_PIN->gpio, MICROPY_HW_SDCARD_DETECT_PIN->pin_mask) == MICROPY_HW_SDCARD_DETECT_PRESENT; } bool sdcard_power_on(void) { @@ -183,7 +199,9 @@ bool sdcard_power_on(void) { // SD device interface configuration sd_handle.Instance = SDIO; sd_handle.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING; + #ifndef STM32H7 sd_handle.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE; + #endif sd_handle.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_ENABLE; sd_handle.Init.BusWide = SDIO_BUS_WIDE_1B; sd_handle.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; @@ -198,6 +216,10 @@ bool sdcard_power_on(void) { } // configure the SD bus width for wide operation + #if defined(STM32F7) + // use maximum SDMMC clock speed on F7 MCUs + sd_handle.Init.ClockBypass = SDMMC_CLOCK_BYPASS_ENABLE; + #endif if (HAL_SD_ConfigWideBusOperation(&sd_handle, SDIO_BUS_WIDE_4B) != HAL_OK) { HAL_SD_DeInit(&sd_handle); goto error; @@ -227,13 +249,15 @@ uint64_t sdcard_get_capacity_in_bytes(void) { return (uint64_t)cardinfo.LogBlockNbr * (uint64_t)cardinfo.LogBlockSize; } +#if !defined(MICROPY_HW_SDMMC2_CK) void SDIO_IRQHandler(void) { IRQ_ENTER(SDIO_IRQn); HAL_SD_IRQHandler(&sd_handle); IRQ_EXIT(SDIO_IRQn); } +#endif -#if defined(MCU_SERIES_F7) +#if defined(STM32F7) void SDMMC2_IRQHandler(void) { IRQ_ENTER(SDMMC2_IRQn); HAL_SD_IRQHandler(&sd_handle); @@ -244,14 +268,23 @@ void SDMMC2_IRQHandler(void) { STATIC HAL_StatusTypeDef sdcard_wait_finished(SD_HandleTypeDef *sd, uint32_t timeout) { // Wait for HAL driver to be ready (eg for DMA to finish) uint32_t start = HAL_GetTick(); - while (sd->State == HAL_SD_STATE_BUSY) { + for (;;) { + // Do an atomic check of the state; WFI will exit even if IRQs are disabled + uint32_t irq_state = disable_irq(); + if (sd->State != HAL_SD_STATE_BUSY) { + enable_irq(irq_state); + break; + } + __WFI(); + enable_irq(irq_state); if (HAL_GetTick() - start >= timeout) { return HAL_TIMEOUT; } } + // Wait for SD card to complete the operation for (;;) { - HAL_SD_CardStateTypeDef state = HAL_SD_GetCardState(sd); + HAL_SD_CardStateTypedef state = HAL_SD_GetCardState(sd); if (state == HAL_SD_CARD_TRANSFER) { return HAL_OK; } @@ -261,6 +294,7 @@ STATIC HAL_StatusTypeDef sdcard_wait_finished(SD_HandleTypeDef *sd, uint32_t tim if (HAL_GetTick() - start >= timeout) { return HAL_TIMEOUT; } + __WFI(); } return HAL_OK; } @@ -295,8 +329,10 @@ mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blo // we must disable USB irqs to prevent MSC contention with SD card uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); + #if SDIO_USE_GPDMA dma_init(&sd_rx_dma, &SDMMC_RX_DMA, &sd_handle); sd_handle.hdmarx = &sd_rx_dma; + #endif // make sure cache is flushed and invalidated so when DMA updates the RAM // from reading the peripheral the CPU then reads the new data @@ -307,8 +343,10 @@ mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blo err = sdcard_wait_finished(&sd_handle, 60000); } + #if SDIO_USE_GPDMA dma_deinit(&SDMMC_RX_DMA); sd_handle.hdmarx = NULL; + #endif restore_irq_pri(basepri); } else { @@ -357,8 +395,10 @@ mp_uint_t sdcard_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t n // we must disable USB irqs to prevent MSC contention with SD card uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS); + #if SDIO_USE_GPDMA dma_init(&sd_tx_dma, &SDMMC_TX_DMA, &sd_handle); sd_handle.hdmatx = &sd_tx_dma; + #endif // 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); @@ -367,8 +407,11 @@ mp_uint_t sdcard_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t n if (err == HAL_OK) { err = sdcard_wait_finished(&sd_handle, 60000); } + + #if SDIO_USE_GPDMA dma_deinit(&SDMMC_TX_DMA); sd_handle.hdmatx = NULL; + #endif restore_irq_pri(basepri); } else { @@ -496,7 +539,7 @@ STATIC mp_obj_t pyb_sdcard_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in return MP_OBJ_NEW_SMALL_INT(0); // success case BP_IOCTL_SEC_COUNT: - return MP_OBJ_NEW_SMALL_INT(0); // TODO + return MP_OBJ_NEW_SMALL_INT(sdcard_get_capacity_in_bytes() / SDCARD_BLOCK_SIZE); case BP_IOCTL_SEC_SIZE: return MP_OBJ_NEW_SMALL_INT(SDCARD_BLOCK_SIZE); |
