summaryrefslogtreecommitdiff
path: root/ports/stm32/sdcard.c
diff options
context:
space:
mode:
Diffstat (limited to 'ports/stm32/sdcard.c')
-rw-r--r--ports/stm32/sdcard.c85
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);