stm32/sdio: Add support for H7 MCUs.
The cyw43 driver on stm32 will now work with H7 MCUs.
This commit is contained in:
parent
d494e47855
commit
257b17ec10
@ -62,12 +62,18 @@ void sdio_init(uint32_t irq_pri) {
|
||||
__HAL_RCC_SDMMC1_CLK_ENABLE(); // enable SDIO peripheral
|
||||
|
||||
SDMMC_TypeDef *SDIO = SDMMC1;
|
||||
SDIO->CLKCR = SDMMC_CLKCR_HWFC_EN | SDMMC_CLKCR_PWRSAV | 118; // 1-bit, 400kHz
|
||||
#if defined(STM32F7)
|
||||
SDIO->CLKCR = SDMMC_CLKCR_HWFC_EN | SDMMC_CLKCR_PWRSAV | (120 - 2); // 1-bit, 400kHz
|
||||
#else
|
||||
SDIO->CLKCR = SDMMC_CLKCR_HWFC_EN | SDMMC_CLKCR_PWRSAV | (120 / 2); // 1-bit, 400kHz
|
||||
#endif
|
||||
mp_hal_delay_us(10);
|
||||
SDIO->POWER = 3; // the card is clocked
|
||||
mp_hal_delay_us(10);
|
||||
SDIO->DCTRL = 1 << 10; // RWMOD is SDIO_CK
|
||||
SDIO->DCTRL = SDMMC_DCTRL_RWMOD; // RWMOD is SDIO_CK
|
||||
#if defined(STM32F7)
|
||||
SDIO->CLKCR |= SDMMC_CLKCR_CLKEN;
|
||||
#endif
|
||||
mp_hal_delay_us(10);
|
||||
|
||||
__HAL_RCC_DMA2_CLK_ENABLE(); // enable DMA2 peripheral
|
||||
@ -79,20 +85,28 @@ void sdio_init(uint32_t irq_pri) {
|
||||
}
|
||||
|
||||
void sdio_deinit(void) {
|
||||
RCC->APB2ENR &= ~RCC_APB2ENR_SDMMC1EN; // disable SDIO peripheral
|
||||
RCC->AHB1ENR &= ~RCC_AHB1ENR_DMA2EN; // disable DMA2 peripheral
|
||||
__HAL_RCC_SDMMC1_CLK_DISABLE();
|
||||
#if defined(STM32F7)
|
||||
__HAL_RCC_DMA2_CLK_DISABLE();
|
||||
#endif
|
||||
}
|
||||
|
||||
void sdio_enable_high_speed_4bit(void) {
|
||||
SDMMC_TypeDef *SDIO = SDMMC1;
|
||||
SDIO->POWER = 0; // power off
|
||||
mp_hal_delay_us(10);
|
||||
#if defined(STM32F7)
|
||||
SDIO->CLKCR = SDMMC_CLKCR_HWFC_EN | SDMMC_CLKCR_WIDBUS_0 | SDMMC_CLKCR_BYPASS /*| SDMMC_CLKCR_PWRSAV*/; // 4-bit, 48MHz
|
||||
#else
|
||||
SDIO->CLKCR = SDMMC_CLKCR_HWFC_EN | SDMMC_CLKCR_WIDBUS_0; // 4-bit, 48MHz
|
||||
#endif
|
||||
mp_hal_delay_us(10);
|
||||
SDIO->POWER = 3; // the card is clocked
|
||||
mp_hal_delay_us(10);
|
||||
SDIO->DCTRL = 1 << 11 | 1 << 10; // SDIOEN, RWMOD is SDIO_CK
|
||||
SDIO->DCTRL = SDMMC_DCTRL_SDIOEN | SDMMC_DCTRL_RWMOD; // SDIOEN, RWMOD is SDIO_CK
|
||||
#if defined(STM32F7)
|
||||
SDIO->CLKCR |= SDMMC_CLKCR_CLKEN;
|
||||
#endif
|
||||
SDIO->MASK = DEFAULT_MASK;
|
||||
mp_hal_delay_us(10);
|
||||
}
|
||||
@ -108,6 +122,14 @@ void SDMMC1_IRQHandler(void) {
|
||||
sdmmc_irq_state = SDMMC_IRQ_STATE_DONE;
|
||||
return;
|
||||
}
|
||||
#if defined(STM32H7)
|
||||
if (!sdmmc_dma) {
|
||||
while (sdmmc_buf_cur < sdmmc_buf_top && (SDMMC1->STA & SDMMC_STA_DPSMACT) && !(SDMMC1->STA & SDMMC_STA_RXFIFOE)) {
|
||||
*(uint32_t*)sdmmc_buf_cur = SDMMC1->FIFO;
|
||||
sdmmc_buf_cur += 4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (sdmmc_buf_cur >= sdmmc_buf_top) {
|
||||
// data transfer finished, so we are done
|
||||
SDMMC1->MASK &= SDMMC_MASK_SDIOITIE;
|
||||
@ -115,7 +137,16 @@ void SDMMC1_IRQHandler(void) {
|
||||
return;
|
||||
}
|
||||
if (sdmmc_write) {
|
||||
SDMMC1->DCTRL = (sdmmc_block_size_log2 << 4) | 1 | (1 << 11) | (!sdmmc_write << 1) | (sdmmc_dma << 3) | (0 << 10);
|
||||
SDMMC1->DCTRL =
|
||||
SDMMC_DCTRL_SDIOEN
|
||||
| SDMMC_DCTRL_RWMOD
|
||||
| sdmmc_block_size_log2 << SDMMC_DCTRL_DBLOCKSIZE_Pos
|
||||
#if defined(STM32F7)
|
||||
| (sdmmc_dma << SDMMC_DCTRL_DMAEN_Pos)
|
||||
#endif
|
||||
| (!sdmmc_write) << SDMMC_DCTRL_DTDIR_Pos
|
||||
| SDMMC_DCTRL_DTEN
|
||||
;
|
||||
if (!sdmmc_dma) {
|
||||
SDMMC1->MASK |= SDMMC_MASK_TXFIFOHEIE;
|
||||
}
|
||||
@ -125,6 +156,7 @@ void SDMMC1_IRQHandler(void) {
|
||||
// data transfer complete
|
||||
// note: it's possible to get DATAEND before CMDREND
|
||||
SDMMC1->ICR = SDMMC_ICR_DATAENDC;
|
||||
#if defined(STM32F7)
|
||||
// check if there is some remaining data in RXFIFO
|
||||
if (!sdmmc_dma) {
|
||||
while (SDMMC1->STA & SDMMC_STA_RXDAVL) {
|
||||
@ -132,6 +164,7 @@ void SDMMC1_IRQHandler(void) {
|
||||
sdmmc_buf_cur += 4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (sdmmc_irq_state == SDMMC_IRQ_STATE_CMD_DONE) {
|
||||
// command and data finished, so we are done
|
||||
SDMMC1->MASK &= SDMMC_MASK_SDIOITIE;
|
||||
@ -177,9 +210,11 @@ void SDMMC1_IRQHandler(void) {
|
||||
}
|
||||
|
||||
int sdio_transfer(uint32_t cmd, uint32_t arg, uint32_t *resp) {
|
||||
#if defined(STM32F7)
|
||||
// Wait for any outstanding TX to complete
|
||||
while (SDMMC1->STA & SDMMC_STA_TXACT) {
|
||||
}
|
||||
#endif
|
||||
|
||||
DMA2_Stream3->CR = 0; // ensure DMA is reset
|
||||
SDMMC1->ICR = SDMMC_STATIC_FLAGS; // clear interrupts
|
||||
@ -226,9 +261,11 @@ int sdio_transfer(uint32_t cmd, uint32_t arg, uint32_t *resp) {
|
||||
}
|
||||
|
||||
int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t len, uint8_t *buf) {
|
||||
#if defined(STM32F7)
|
||||
// Wait for any outstanding TX to complete
|
||||
while (SDMMC1->STA & SDMMC_STA_TXACT) {
|
||||
}
|
||||
#endif
|
||||
|
||||
// for SDIO_BYTE_MODE the SDIO chuck of data must be a single block of the length of buf
|
||||
int block_size_log2 = 0;
|
||||
@ -264,8 +301,10 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le
|
||||
if (dma) {
|
||||
// prepare DMA so it's ready when the DPSM starts its transfer
|
||||
|
||||
#if defined(STM32F7)
|
||||
// enable DMA2 peripheral in case it was turned off by someone else
|
||||
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN;
|
||||
#endif
|
||||
|
||||
if (write) {
|
||||
// make sure cache is flushed to RAM so the DMA can read the correct data
|
||||
@ -276,6 +315,7 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le
|
||||
MP_HAL_CLEANINVALIDATE_DCACHE(buf, len);
|
||||
}
|
||||
|
||||
#if defined(STM32F7)
|
||||
DMA2->LIFCR = 0x3f << 22;
|
||||
DMA2_Stream3->FCR = 0x07; // ?
|
||||
DMA2_Stream3->PAR = (uint32_t)&SDMMC1->FIFO;
|
||||
@ -297,6 +337,14 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le
|
||||
| 1 << 5 // PFCTRL periph is flow controller
|
||||
| 1 << 0 // EN
|
||||
;
|
||||
#else
|
||||
SDMMC1->IDMABASE0 = (uint32_t)buf;
|
||||
SDMMC1->IDMACTRL = SDMMC_IDMA_IDMAEN;
|
||||
#endif
|
||||
} else {
|
||||
#if defined(STM32H7)
|
||||
SDMMC1->IDMACTRL = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// for reading, need to initialise the DPSM before starting the CPSM
|
||||
@ -304,7 +352,16 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le
|
||||
// (and in case we get a long-running unrelated IRQ here on the host just
|
||||
// after writing to CMD to initiate the command)
|
||||
if (!write) {
|
||||
SDMMC1->DCTRL = (block_size_log2 << 4) | 1 | (1 << 11) | (!write << 1) | (dma << 3);
|
||||
SDMMC1->DCTRL =
|
||||
SDMMC_DCTRL_SDIOEN
|
||||
| SDMMC_DCTRL_RWMOD
|
||||
| block_size_log2 << SDMMC_DCTRL_DBLOCKSIZE_Pos
|
||||
#if defined(STM32F7)
|
||||
| (dma << SDMMC_DCTRL_DMAEN_Pos)
|
||||
#endif
|
||||
| (!write) << SDMMC_DCTRL_DTDIR_Pos
|
||||
| SDMMC_DCTRL_DTEN
|
||||
;
|
||||
}
|
||||
|
||||
SDMMC1->ARG = arg;
|
||||
@ -328,7 +385,11 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le
|
||||
}
|
||||
if (mp_hal_ticks_ms() - start > 200) {
|
||||
SDMMC1->MASK &= SDMMC_MASK_SDIOITIE;
|
||||
#if defined(STM32F7)
|
||||
printf("sdio_transfer_cmd53: timeout wr=%d len=%u dma=%u buf_idx=%u STA=%08x SDMMC=%08x:%08x DMA=%08x:%08x:%08x RCC=%08x\n", write, (uint)len, (uint)dma, sdmmc_buf_cur - buf, (uint)SDMMC1->STA, (uint)SDMMC1->DCOUNT, (uint)SDMMC1->FIFOCNT, (uint)DMA2->LISR, (uint)DMA2->HISR, (uint)DMA2_Stream3->NDTR, (uint)RCC->AHB1ENR);
|
||||
#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)SDMMC1->STA, (uint)SDMMC1->DCOUNT, (uint)SDMMC1->DCTRL, (uint)SDMMC1->IDMACTRL);
|
||||
#endif
|
||||
return -MP_ETIMEDOUT;
|
||||
}
|
||||
}
|
||||
@ -336,7 +397,11 @@ int sdio_transfer_cmd53(bool write, uint32_t block_size, uint32_t arg, size_t le
|
||||
SDMMC1->MASK &= SDMMC_MASK_SDIOITIE;
|
||||
|
||||
if (sdmmc_error) {
|
||||
#if defined(STM32F7)
|
||||
printf("sdio_transfer_cmd53: error=%08lx wr=%d len=%u dma=%u buf_idx=%u STA=%08x SDMMC=%08x:%08x DMA=%08x:%08x:%08x RCC=%08x\n", sdmmc_error, write, (uint)len, (uint)dma, sdmmc_buf_cur - buf, (uint)SDMMC1->STA, (uint)SDMMC1->DCOUNT, (uint)SDMMC1->FIFOCNT, (uint)DMA2->LISR, (uint)DMA2->HISR, (uint)DMA2_Stream3->NDTR, (uint)RCC->AHB1ENR);
|
||||
#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)SDMMC1->STA, (uint)SDMMC1->DCOUNT, (uint)SDMMC1->DCTRL, (uint)SDMMC1->IDMACTRL);
|
||||
#endif
|
||||
return -(0x1000000 | sdmmc_error);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user