From 7e46dc94aa5d6bad9ff7e449878f64938b2437f1 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Tue, 9 Jan 2018 15:39:54 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11242 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c | 175 ++++++++++++++++++++++++----- os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h | 12 ++ 2 files changed, 162 insertions(+), 25 deletions(-) (limited to 'os/hal/ports/STM32') diff --git a/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c b/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c index dbc9d1f1d..855b931cd 100644 --- a/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c +++ b/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.c @@ -75,42 +75,118 @@ static uint32_t dummyrx; /* Driver local functions. */ /*===========================================================================*/ +#if defined(STM32_SPI_BDMA_REQUIRED) /** - * @brief Shared end-of-rx service routine. + * @brief Shared DMA end-of-rx service routine. * * @param[in] spip pointer to the @p SPIDriver object * @param[in] flags pre-shifted content of the ISR register */ -static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) { +static void spi_lld_serve_bdma_rx_interrupt(SPIDriver *spip, uint32_t flags) { /* DMA errors handling.*/ #if defined(STM32_SPI_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + if ((flags & STM32_BDMA_ISR_TEIF) != 0U) { STM32_SPI_DMA_ERROR_HOOK(spip); } #else (void)flags; #endif - /* Stopping SPI.*/ - spip->spi->CR1 |= SPI_CR1_CSUSP; + if (spip->config->circular) { + if ((flags & STM32_BDMA_ISR_HTIF) != 0U) { + /* Half buffer interrupt.*/ + _spi_isr_code_half1(spip); + } + else { + /* End buffer interrupt.*/ + _spi_isr_code_half2(spip); + } + } + else { + /* Stopping SPI.*/ + spip->spi->CR1 |= SPI_CR1_CSUSP; + + /* Stopping DMAs.*/ + bdmaStreamDisable(spip->tx.bdma); + bdmaStreamDisable(spip->rx.bdma); + + /* Portable SPI ISR code defined in the high level driver, note, it is + a macro.*/ + _spi_isr_code(spip); + } +} + +/** + * @brief Shared BDMA end-of-tx service routine. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void spi_lld_serve_bdma_tx_interrupt(SPIDriver *spip, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_SPI_DMA_ERROR_HOOK) + (void)spip; + if ((flags & STM32_BDMA_ISR_TEIF) != 0) { + STM32_SPI_DMA_ERROR_HOOK(spip); + } +#else + (void)spip; + (void)flags; +#endif +} +#endif /* defined(STM32_SPI_BDMA_REQUIRED) */ + +#if defined(STM32_SPI_DMA_REQUIRED) +/** + * @brief Shared DMA end-of-rx service routine. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[in] flags pre-shifted content of the ISR register + */ +static void spi_lld_serve_dma_rx_interrupt(SPIDriver *spip, uint32_t flags) { + + /* DMA errors handling.*/ +#if defined(STM32_SPI_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0U) { + STM32_SPI_DMA_ERROR_HOOK(spip); + } +#else + (void)flags; +#endif - /* Stop everything.*/ - dmaStreamDisable(spip->tx.dma); - dmaStreamDisable(spip->rx.dma); + if (spip->config->circular) { + if ((flags & STM32_DMA_ISR_HTIF) != 0U) { + /* Half buffer interrupt.*/ + _spi_isr_code_half1(spip); + } + else { + /* End buffer interrupt.*/ + _spi_isr_code_half2(spip); + } + } + else { + /* Stopping SPI.*/ + spip->spi->CR1 |= SPI_CR1_CSUSP; - /* Portable SPI ISR code defined in the high level driver, note, it is - a macro.*/ - _spi_isr_code(spip); + /* Stopping DMAs.*/ + dmaStreamDisable(spip->tx.dma); + dmaStreamDisable(spip->rx.dma); + + /* Portable SPI ISR code defined in the high level driver, note, it is + a macro.*/ + _spi_isr_code(spip); + } } /** - * @brief Shared end-of-tx service routine. + * @brief Shared DMA end-of-tx service routine. * * @param[in] spip pointer to the @p SPIDriver object * @param[in] flags pre-shifted content of the ISR register */ -static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) { +static void spi_lld_serve_dma_tx_interrupt(SPIDriver *spip, uint32_t flags) { /* DMA errors handling.*/ #if defined(STM32_SPI_DMA_ERROR_HOOK) @@ -123,6 +199,7 @@ static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) { (void)flags; #endif } +#endif /* defined(STM32_SPI_DMA_REQUIRED) */ /** * @brief Shared SPI service routine. @@ -429,12 +506,12 @@ void spi_lld_start(SPIDriver *spip) { bool b; b = dmaStreamAllocate(spip->rx.dma, STM32_SPI_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt, (void *)spip); osalDbgAssert(!b, "stream already allocated"); b = dmaStreamAllocate(spip->tx.dma, STM32_SPI_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt, (void *)spip); osalDbgAssert(!b, "stream already allocated"); rccEnableSPI1(false); @@ -447,12 +524,12 @@ void spi_lld_start(SPIDriver *spip) { bool b; b = dmaStreamAllocate(spip->rx.dma, STM32_SPI_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt, (void *)spip); osalDbgAssert(!b, "stream already allocated"); b = dmaStreamAllocate(spip->tx.dma, STM32_SPI_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt, (void *)spip); osalDbgAssert(!b, "stream already allocated"); rccEnableSPI2(false); @@ -465,12 +542,12 @@ void spi_lld_start(SPIDriver *spip) { bool b; b = dmaStreamAllocate(spip->rx.dma, STM32_SPI_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt, (void *)spip); osalDbgAssert(!b, "stream already allocated"); b = dmaStreamAllocate(spip->tx.dma, STM32_SPI_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt, (void *)spip); osalDbgAssert(!b, "stream already allocated"); rccEnableSPI3(false); @@ -483,12 +560,12 @@ void spi_lld_start(SPIDriver *spip) { bool b; b = dmaStreamAllocate(spip->rx.dma, STM32_SPI_SPI4_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt, (void *)spip); osalDbgAssert(!b, "stream already allocated"); b = dmaStreamAllocate(spip->tx.dma, STM32_SPI_SPI4_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt, (void *)spip); osalDbgAssert(!b, "stream already allocated"); rccEnableSPI4(false); @@ -501,12 +578,12 @@ void spi_lld_start(SPIDriver *spip) { bool b; b = dmaStreamAllocate(spip->rx.dma, STM32_SPI_SPI5_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (stm32_dmaisr_t)spi_lld_serve_dma_rx_interrupt, (void *)spip); osalDbgAssert(!b, "stream already allocated"); b = dmaStreamAllocate(spip->tx.dma, STM32_SPI_SPI5_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (stm32_dmaisr_t)spi_lld_serve_dma_tx_interrupt, (void *)spip); osalDbgAssert(!b, "stream already allocated"); rccEnableSPI5(false); @@ -519,12 +596,12 @@ void spi_lld_start(SPIDriver *spip) { bool b; b = bdmaStreamAllocate(spip->rx.bdma, STM32_SPI_SPI6_IRQ_PRIORITY, - (stm32_bdmaisr_t)spi_lld_serve_rx_interrupt, + (stm32_bdmaisr_t)spi_lld_serve_bdma_rx_interrupt, (void *)spip); osalDbgAssert(!b, "stream already allocated"); b = bdmaStreamAllocate(spip->tx.bdma, STM32_SPI_SPI6_IRQ_PRIORITY, - (stm32_bdmaisr_t)spi_lld_serve_tx_interrupt, + (stm32_bdmaisr_t)spi_lld_serve_bdma_tx_interrupt, (void *)spip); osalDbgAssert(!b, "stream already allocated"); rccEnableSPI6(false); @@ -582,6 +659,14 @@ void spi_lld_start(SPIDriver *spip) { spip->txdmamode = (spip->txdmamode & ~STM32_BDMA_CR_SIZE_MASK) | STM32_BDMA_CR_PSIZE_WORD | STM32_BDMA_CR_MSIZE_WORD; } + if (spip->config->circular) { + spip->rxdmamode |= (STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE); + spip->txdmamode |= (STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE); + } + else { + spip->rxdmamode &= ~(STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE); + spip->txdmamode &= ~(STM32_BDMA_CR_CIRC | STM32_BDMA_CR_HTIE); + } } #endif #if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) @@ -610,6 +695,14 @@ void spi_lld_start(SPIDriver *spip) { spip->txdmamode = (spip->txdmamode & ~STM32_DMA_CR_SIZE_MASK) | STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD; } + if (spip->config->circular) { + spip->rxdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); + spip->txdmamode |= (STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); + } + else { + spip->rxdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); + spip->txdmamode &= ~(STM32_DMA_CR_CIRC | STM32_DMA_CR_HTIE); + } } #endif @@ -938,6 +1031,38 @@ void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { spip->spi->CR1 |= SPI_CR1_CSTART; } +/** + * @brief Aborts the ongoing SPI operation, if any. + * + * @param[in] spip pointer to the @p SPIDriver object + * + * @api + */ +void spi_lld_abort(SPIDriver *spip) { + + /* Stopping SPI.*/ + spip->spi->CR1 |= SPI_CR1_CSUSP; + + /* Stopping DMAs.*/ +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + if(spip->is_bdma) +#endif +#if defined(STM32_SPI_BDMA_REQUIRED) + { + bdmaStreamDisable(spip->tx.bdma); + bdmaStreamDisable(spip->rx.bdma); + } +#endif +#if defined(STM32_SPI_DMA_REQUIRED) && defined(STM32_SPI_BDMA_REQUIRED) + else +#endif +#if defined(STM32_SPI_DMA_REQUIRED) + { + dmaStreamDisable(spip->tx.dma); + dmaStreamDisable(spip->rx.dma); + } +#endif +} /** * @brief Exchanges one frame using a polled wait. diff --git a/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h b/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h index 9b011eae8..052a2c58c 100644 --- a/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h +++ b/os/hal/ports/STM32/LLD/SPIv3/hal_spi_lld.h @@ -31,6 +31,11 @@ /* Driver constants. */ /*===========================================================================*/ +/** + * @brief Circular mode support flag. + */ +#define SPI_SUPPORTS_CIRCULAR TRUE + /** * @name Register helpers not found in ST headers * @{ @@ -516,6 +521,12 @@ typedef void (*spicallback_t)(SPIDriver *spip); * @brief Driver configuration structure. */ typedef struct { +#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__) + /** + * @brief Enables the circular buffer mode. + */ + bool circular; +#endif /** * @brief Operation complete callback or @p NULL. */ @@ -682,6 +693,7 @@ extern "C" { const void *txbuf, void *rxbuf); void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf); void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf); + void spi_lld_abort(SPIDriver *spip); uint16_t spi_lld_polled_exchange(SPIDriver *spip, uint16_t frame); #ifdef __cplusplus } -- cgit v1.2.3