diff options
-rw-r--r-- | ports/stm32/spi.c | 62 |
1 files changed, 47 insertions, 15 deletions
diff --git a/ports/stm32/spi.c b/ports/stm32/spi.c index c578ac7da..e8621b0ab 100644 --- a/ports/stm32/spi.c +++ b/ports/stm32/spi.c @@ -401,8 +401,7 @@ void spi_deinit(const spi_t *spi_obj) { } } -STATIC HAL_StatusTypeDef spi_wait_dma_finished(const spi_t *spi, uint32_t timeout) { - uint32_t start = HAL_GetTick(); +STATIC HAL_StatusTypeDef spi_wait_dma_finished(const spi_t *spi, uint32_t t_start, uint32_t timeout) { volatile HAL_SPI_StateTypeDef *state = &spi->spi->State; for (;;) { // Do an atomic check of the state; WFI will exit even if IRQs are disabled @@ -413,7 +412,7 @@ STATIC HAL_StatusTypeDef spi_wait_dma_finished(const spi_t *spi, uint32_t timeou } __WFI(); enable_irq(irq_state); - if (HAL_GetTick() - start >= timeout) { + if (HAL_GetTick() - t_start >= timeout) { return HAL_TIMEOUT; } } @@ -430,6 +429,8 @@ STATIC void spi_transfer(const spi_t *self, size_t len, const uint8_t *src, uint // time directly after the SPI/DMA is initialised. The cause of this is // unknown but we sidestep the issue by using polling for 1 byte transfer. + // Note: DMA transfers are limited to 65535 bytes at a time. + HAL_StatusTypeDef status; if (dest == NULL) { @@ -442,10 +443,20 @@ STATIC void spi_transfer(const spi_t *self, size_t len, const uint8_t *src, uint self->spi->hdmatx = &tx_dma; self->spi->hdmarx = NULL; MP_HAL_CLEAN_DCACHE(src, len); - status = HAL_SPI_Transmit_DMA(self->spi, (uint8_t*)src, len); - if (status == HAL_OK) { - status = spi_wait_dma_finished(self, timeout); - } + uint32_t t_start = HAL_GetTick(); + do { + uint32_t l = MIN(len, 65535); + status = HAL_SPI_Transmit_DMA(self->spi, (uint8_t*)src, l); + if (status != HAL_OK) { + break; + } + status = spi_wait_dma_finished(self, t_start, timeout); + if (status != HAL_OK) { + break; + } + len -= l; + src += l; + } while (len); dma_deinit(self->tx_dma_descr); } } else if (src == NULL) { @@ -464,10 +475,20 @@ STATIC void spi_transfer(const spi_t *self, size_t len, const uint8_t *src, uint dma_init(&rx_dma, self->rx_dma_descr, self->spi); self->spi->hdmarx = &rx_dma; MP_HAL_CLEANINVALIDATE_DCACHE(dest, len); - status = HAL_SPI_Receive_DMA(self->spi, dest, len); - if (status == HAL_OK) { - status = spi_wait_dma_finished(self, timeout); - } + uint32_t t_start = HAL_GetTick(); + do { + uint32_t l = MIN(len, 65535); + status = HAL_SPI_Receive_DMA(self->spi, dest, l); + if (status != HAL_OK) { + break; + } + status = spi_wait_dma_finished(self, t_start, timeout); + if (status != HAL_OK) { + break; + } + len -= l; + dest += l; + } while (len); if (self->spi->hdmatx != NULL) { dma_deinit(self->tx_dma_descr); } @@ -485,10 +506,21 @@ STATIC void spi_transfer(const spi_t *self, size_t len, const uint8_t *src, uint self->spi->hdmarx = &rx_dma; MP_HAL_CLEAN_DCACHE(src, len); MP_HAL_CLEANINVALIDATE_DCACHE(dest, len); - status = HAL_SPI_TransmitReceive_DMA(self->spi, (uint8_t*)src, dest, len); - if (status == HAL_OK) { - status = spi_wait_dma_finished(self, timeout); - } + uint32_t t_start = HAL_GetTick(); + do { + uint32_t l = MIN(len, 65535); + status = HAL_SPI_TransmitReceive_DMA(self->spi, (uint8_t*)src, dest, l); + if (status != HAL_OK) { + break; + } + status = spi_wait_dma_finished(self, t_start, timeout); + if (status != HAL_OK) { + break; + } + len -= l; + src += l; + dest += l; + } while (len); dma_deinit(self->tx_dma_descr); dma_deinit(self->rx_dma_descr); } |