Skip to content

Commit

Permalink
stmhal/sdcard: Add support for SDMMC2 on F7 MCUs.
Browse files Browse the repository at this point in the history
By default the SDIO (F4) or SDMMC1 (L4, F7) is used as the SD card
peripheral, but if a board config defines MICROPY_HW_SDMMC2_CK and other
pins then the SD card driver will use SDMMC2.
  • Loading branch information
dpgeorge committed Mar 30, 2017
1 parent 43defc9 commit 7876e54
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 11 deletions.
6 changes: 6 additions & 0 deletions stmhal/dma.c
Expand Up @@ -186,6 +186,9 @@ const dma_descr_t dma_I2C_1_TX = { DMA1_Stream6, DMA_CHANNEL_1, DMA_MEMORY_TO_PE
*/

// DMA2 streams
#if defined(MCU_SERIES_F7) && MICROPY_HW_HAS_SDCARD
const dma_descr_t dma_SDMMC_2_RX= { DMA2_Stream0, DMA_CHANNEL_11, DMA_PERIPH_TO_MEMORY, dma_id_8, &dma_init_struct_sdio };
#endif
const dma_descr_t dma_SPI_1_RX = { DMA2_Stream2, DMA_CHANNEL_3, DMA_PERIPH_TO_MEMORY, dma_id_10, &dma_init_struct_spi_i2c };
const dma_descr_t dma_SPI_5_RX = { DMA2_Stream3, DMA_CHANNEL_2, DMA_PERIPH_TO_MEMORY, dma_id_11, &dma_init_struct_spi_i2c };
#if defined(MICROPY_HW_HAS_SDCARD) && MICROPY_HW_HAS_SDCARD
Expand All @@ -196,6 +199,9 @@ const dma_descr_t dma_SPI_5_TX = { DMA2_Stream4, DMA_CHANNEL_2, DMA_MEMORY_TO_PE
const dma_descr_t dma_SPI_4_TX = { DMA2_Stream4, DMA_CHANNEL_5, DMA_MEMORY_TO_PERIPH, dma_id_12, &dma_init_struct_spi_i2c };
const dma_descr_t dma_SPI_6_TX = { DMA2_Stream5, DMA_CHANNEL_1, DMA_MEMORY_TO_PERIPH, dma_id_13, &dma_init_struct_spi_i2c };
const dma_descr_t dma_SPI_1_TX = { DMA2_Stream5, DMA_CHANNEL_3, DMA_MEMORY_TO_PERIPH, dma_id_13, &dma_init_struct_spi_i2c };
#if defined(MCU_SERIES_F7) && MICROPY_HW_HAS_SDCARD
const dma_descr_t dma_SDMMC_2_TX= { DMA2_Stream5, DMA_CHANNEL_11, DMA_MEMORY_TO_PERIPH, dma_id_13, &dma_init_struct_sdio };
#endif
const dma_descr_t dma_SPI_6_RX = { DMA2_Stream6, DMA_CHANNEL_1, DMA_PERIPH_TO_MEMORY, dma_id_14, &dma_init_struct_spi_i2c };
#if defined(MICROPY_HW_HAS_SDCARD) && MICROPY_HW_HAS_SDCARD
const dma_descr_t dma_SDIO_0_TX= { DMA2_Stream6, DMA_CHANNEL_4, DMA_MEMORY_TO_PERIPH, dma_id_14, &dma_init_struct_sdio };
Expand Down
2 changes: 2 additions & 0 deletions stmhal/dma.h
Expand Up @@ -45,6 +45,7 @@ extern const dma_descr_t dma_DAC_2_TX;
extern const dma_descr_t dma_SPI_3_TX;
extern const dma_descr_t dma_I2C_1_TX;
extern const dma_descr_t dma_I2C_2_TX;
extern const dma_descr_t dma_SDMMC_2_RX;
extern const dma_descr_t dma_SPI_1_RX;
extern const dma_descr_t dma_SPI_5_RX;
extern const dma_descr_t dma_SDIO_0_RX;
Expand All @@ -53,6 +54,7 @@ extern const dma_descr_t dma_SPI_5_TX;
extern const dma_descr_t dma_SPI_4_TX;
extern const dma_descr_t dma_SPI_6_TX;
extern const dma_descr_t dma_SPI_1_TX;
extern const dma_descr_t dma_SDMMC_2_TX;
extern const dma_descr_t dma_SPI_6_RX;
extern const dma_descr_t dma_SDIO_0_TX;

Expand Down
69 changes: 58 additions & 11 deletions stmhal/sdcard.c
Expand Up @@ -43,11 +43,29 @@

#if defined(MCU_SERIES_F7) || defined(MCU_SERIES_L4)

// 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
// is used, otherwise SDMMC1 is used.

#if defined(MICROPY_HW_SDMMC2_CK)
#define SDIO SDMMC2
#define SDMMC_CLK_ENABLE() __HAL_RCC_SDMMC2_CLK_ENABLE()
#define SDMMC_CLK_DISABLE() __HAL_RCC_SDMMC2_CLK_DISABLE()
#define SDMMC_IRQn SDMMC2_IRQn
#define SDMMC_TX_DMA dma_SDMMC_2_TX
#define SDMMC_RX_DMA dma_SDMMC_2_RX
#else
#define SDIO SDMMC1
#define SDMMC_CLK_ENABLE() __HAL_RCC_SDMMC1_CLK_ENABLE()
#define SDMMC_CLK_DISABLE() __HAL_RCC_SDMMC1_CLK_DISABLE()
#define SDMMC_IRQn SDMMC1_IRQn
#define SDMMC_TX_DMA dma_SDIO_0_TX
#define SDMMC_RX_DMA dma_SDIO_0_RX
#endif

// The F7 & L4 series calls the peripheral SDMMC rather than SDIO, so provide some
// #defines for backwards compatability.

#define SDIO SDMMC1

#define SDIO_CLOCK_EDGE_RISING SDMMC_CLOCK_EDGE_RISING
#define SDIO_CLOCK_EDGE_FALLING SDMMC_CLOCK_EDGE_FALLING

Expand All @@ -66,6 +84,16 @@

#define SDIO_TRANSFER_CLK_DIV SDMMC_TRANSFER_CLK_DIV

#else

// These are definitions for F4 MCUs so there is a common macro across all MCUs.

#define SDMMC_CLK_ENABLE() __SDIO_CLK_ENABLE()
#define SDMMC_CLK_DISABLE() __SDIO_CLK_DISABLE()
#define SDMMC_IRQn SDIO_IRQn
#define SDMMC_TX_DMA dma_SDIO_0_TX
#define SDMMC_RX_DMA dma_SDIO_0_RX

#endif

// TODO: Since SDIO is fundamentally half-duplex, we really only need to
Expand All @@ -90,12 +118,23 @@ void sdcard_init(void) {
// Note: the mp_hal_pin_config function will configure the GPIO in
// fast mode which can do up to 50MHz. This should be plenty for SDIO
// 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);
#else
// Default SDIO/SDMMC1 config
mp_hal_pin_config(&pin_C8, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO);
mp_hal_pin_config(&pin_C9, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO);
mp_hal_pin_config(&pin_C10, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO);
mp_hal_pin_config(&pin_C11, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO);
mp_hal_pin_config(&pin_C12, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO);
mp_hal_pin_config(&pin_D2, 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
Expand All @@ -104,18 +143,18 @@ void sdcard_init(void) {

void HAL_SD_MspInit(SD_HandleTypeDef *hsd) {
// enable SDIO clock
__SDIO_CLK_ENABLE();
SDMMC_CLK_ENABLE();

// NVIC configuration for SDIO interrupts
HAL_NVIC_SetPriority(SDIO_IRQn, IRQ_PRI_SDIO, IRQ_SUBPRI_SDIO);
HAL_NVIC_EnableIRQ(SDIO_IRQn);
HAL_NVIC_SetPriority(SDMMC_IRQn, IRQ_PRI_SDIO, IRQ_SUBPRI_SDIO);
HAL_NVIC_EnableIRQ(SDMMC_IRQn);

// GPIO have already been initialised by sdcard_init
}

void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) {
HAL_NVIC_DisableIRQ(SDIO_IRQn);
__SDIO_CLK_DISABLE();
HAL_NVIC_DisableIRQ(SDMMC_IRQn);
SDMMC_CLK_DISABLE();
}

bool sdcard_is_present(void) {
Expand Down Expand Up @@ -184,6 +223,14 @@ void SDIO_IRQHandler(void) {
IRQ_EXIT(SDIO_IRQn);
}

#if defined(MCU_SERIES_F7)
void SDMMC2_IRQHandler(void) {
IRQ_ENTER(SDMMC2_IRQn);
HAL_SD_IRQHandler(&sd_handle);
IRQ_EXIT(SDMMC2_IRQn);
}
#endif

mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) {
// check that SD card is initialised
if (sd_handle.Instance == NULL) {
Expand Down Expand Up @@ -214,7 +261,7 @@ 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);

dma_init(&sd_rx_dma, &dma_SDIO_0_RX, &sd_handle);
dma_init(&sd_rx_dma, &SDMMC_RX_DMA, &sd_handle);
sd_handle.hdmarx = &sd_rx_dma;

// make sure cache is flushed and invalidated so when DMA updates the RAM
Expand All @@ -227,7 +274,7 @@ mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blo
err = HAL_SD_CheckReadOperation(&sd_handle, 100000000);
}

dma_deinit(&dma_SDIO_0_RX);
dma_deinit(&SDMMC_RX_DMA);
sd_handle.hdmarx = NULL;

restore_irq_pri(basepri);
Expand Down Expand Up @@ -274,7 +321,7 @@ 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);

dma_init(&sd_tx_dma, &dma_SDIO_0_TX, &sd_handle);
dma_init(&sd_tx_dma, &SDMMC_TX_DMA, &sd_handle);
sd_handle.hdmatx = &sd_tx_dma;

// make sure cache is flushed to RAM so the DMA can read the correct data
Expand All @@ -285,7 +332,7 @@ mp_uint_t sdcard_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t n
// wait for DMA transfer to finish, with a large timeout
err = HAL_SD_CheckWriteOperation(&sd_handle, 100000000);
}
dma_deinit(&dma_SDIO_0_TX);
dma_deinit(&SDMMC_TX_DMA);
sd_handle.hdmatx = NULL;

restore_irq_pri(basepri);
Expand Down
24 changes: 24 additions & 0 deletions stmhal/startup_stm32.S
Expand Up @@ -335,6 +335,12 @@ g_pfnVectors:
.word I2C4_EV_IRQHandler /* I2C4 Event */
.word I2C4_ER_IRQHandler /* I2C4 Error */
.word SPDIF_RX_IRQHandler /* SPDIF_RX */
.word DSIHOST_IRQHandler /* DSI host */
.word DFSDM1_FLT0_IRQHandler /* DFSDM1 filter 0 */
.word DFSDM1_FLT1_IRQHandler /* DFSDM1 filter 1 */
.word DFSDM1_FLT2_IRQHandler /* DFSDM1 filter 2 */
.word DFSDM1_FLT3_IRQHandler /* DFSDM1 filter 3 */
.word SDMMC2_IRQHandler /* SDMMC2 */
#endif

/*******************************************************************************
Expand Down Expand Up @@ -793,6 +799,24 @@ g_pfnVectors:

.weak SPDIF_RX_IRQHandler
.thumb_set SPDIF_RX_IRQHandler,Default_Handler

.weak DSIHOST_IRQHandler
.thumb_set DSIHOST_IRQHandler,Default_Handler

.weak DFSDM1_FLT0_IRQHandler
.thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler

.weak DFSDM1_FLT1_IRQHandler
.thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler

.weak DFSDM1_FLT2_IRQHandler
.thumb_set DFSDM1_FLT2_IRQHandler,Default_Handler

.weak DFSDM1_FLT3_IRQHandler
.thumb_set DFSDM1_FLT3_IRQHandler,Default_Handler

.weak SDMMC2_IRQHandler
.thumb_set SDMMC2_IRQHandler,Default_Handler
#endif

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

0 comments on commit 7876e54

Please sign in to comment.