diff --git a/os/hal/include/hal_spi_v2.h b/os/hal/include/hal_spi_v2.h index d1ddbad42..bfd2278ad 100644 --- a/os/hal/include/hal_spi_v2.h +++ b/os/hal/include/hal_spi_v2.h @@ -63,6 +63,13 @@ #endif #endif +/** + * @brief Inserts an assertion on function errors before returning. + */ +#if !defined(SPI_USE_ASSERT_ON_ERROR) || defined(__DOXYGEN__) +#define SPI_USE_ASSERT_ON_ERROR TRUE +#endif + /** * @brief Enables circular transfers APIs. * @note Disabling this option saves both code and data space. @@ -358,13 +365,13 @@ do { \ * * @notapi */ -#define _spi_wakeup_isr(spip) { \ +#define __spi_wakeup_isr(spip) { \ osalSysLockFromISR(); \ osalThreadResumeI(&(spip)->sync_transfer, MSG_OK); \ osalSysUnlockFromISR(); \ } #else /* !SPI_USE_SYNCHRONIZATION */ -#define _spi_wakeup_isr(spip) +#define __spi_wakeup_isr(spip) #endif /* !SPI_USE_SYNCHRONIZATION */ /** @@ -381,7 +388,7 @@ do { \ * * @notapi */ -#define _spi_isr_code(spip) { \ +#define __spi_isr_code(spip) { \ if ((spip)->config->end_cb) { \ (spip)->state = SPI_COMPLETE; \ (spip)->config->end_cb(spip); \ @@ -390,7 +397,7 @@ do { \ } \ else \ (spip)->state = SPI_READY; \ - _spi_wakeup_isr(spip); \ + __spi_wakeup_isr(spip); \ } /** @@ -405,7 +412,7 @@ do { \ * * @notapi */ -#define _spi_isr_half_code(spip) { \ +#define __spi_isr_half_code(spip) { \ if ((spip)->config->end_cb) { \ (spip)->config->end_cb(spip); \ } \ @@ -424,7 +431,7 @@ do { \ * * @notapi */ -#define _spi_isr_full_code(spip) { \ +#define __spi_isr_full_code(spip) { \ if ((spip)->config->end_cb) { \ (spip)->state = SPI_COMPLETE; \ (spip)->config->end_cb(spip); \ @@ -447,25 +454,25 @@ extern "C" { void spiStop(SPIDriver *spip); void spiSelect(SPIDriver *spip); void spiUnselect(SPIDriver *spip); - bool spiStartIgnoreI(SPIDriver *spip, size_t n); - bool spiStartIgnore(SPIDriver *spip, size_t n); - bool spiStartExchangeI(SPIDriver *spip, size_t n, + msg_t spiStartIgnoreI(SPIDriver *spip, size_t n); + msg_t spiStartIgnore(SPIDriver *spip, size_t n); + msg_t spiStartExchangeI(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf); + msg_t spiStartExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf); - bool spiStartExchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf); - bool spiStartSendI(SPIDriver *spip, size_t n, const void *txbuf); - bool spiStartSend(SPIDriver *spip, size_t n, const void *txbuf); - bool spiStartReceiveI(SPIDriver *spip, size_t n, void *rxbuf); - bool spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf); - size_t spiStopTransferI(SPIDriver *spip); - size_t spiStopTransfer(SPIDriver *spip); + msg_t spiStartSendI(SPIDriver *spip, size_t n, const void *txbuf); + msg_t spiStartSend(SPIDriver *spip, size_t n, const void *txbuf); + msg_t spiStartReceiveI(SPIDriver *spip, size_t n, void *rxbuf); + msg_t spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf); + msg_t spiStopTransferI(SPIDriver *spip, size_t *sizep); + msg_t spiStopTransfer(SPIDriver *spip, size_t *sizep); #if SPI_USE_SYNCHRONIZATION == TRUE msg_t spiSynchronizeS(SPIDriver *spip, sysinterval_t timeout); msg_t spiSynchronize(SPIDriver *spip, sysinterval_t timeout); - void spiIgnore(SPIDriver *spip, size_t n); - void spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf); - void spiSend(SPIDriver *spip, size_t n, const void *txbuf); - void spiReceive(SPIDriver *spip, size_t n, void *rxbuf); + msg_t spiIgnore(SPIDriver *spip, size_t n); + msg_t spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf); + msg_t spiSend(SPIDriver *spip, size_t n, const void *txbuf); + msg_t spiReceive(SPIDriver *spip, size_t n, void *rxbuf); #endif #if SPI_USE_MUTUAL_EXCLUSION == TRUE void spiAcquireBus(SPIDriver *spip); diff --git a/os/hal/ports/STM32/LLD/SPIv2/driver_v2.mk b/os/hal/ports/STM32/LLD/SPIv2/driver_v2.mk new file mode 100644 index 000000000..3b68f5ce9 --- /dev/null +++ b/os/hal/ports/STM32/LLD/SPIv2/driver_v2.mk @@ -0,0 +1,13 @@ +ifeq ($(USE_SMART_BUILD),yes) +ifneq ($(findstring HAL_USE_I2S TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.c +endif +ifneq ($(findstring HAL_USE_SPI TRUE,$(HALCONF)),) +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/hal_spi_v2_lld.c +endif +else +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/hal_i2s_lld.c +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2/hal_spi_v2_lld.c +endif + +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/SPIv2 diff --git a/os/hal/ports/STM32/LLD/SPIv2/hal_spi_v2_lld.c b/os/hal/ports/STM32/LLD/SPIv2/hal_spi_v2_lld.c index d21abf415..01726ec94 100644 --- a/os/hal/ports/STM32/LLD/SPIv2/hal_spi_v2_lld.c +++ b/os/hal/ports/STM32/LLD/SPIv2/hal_spi_v2_lld.c @@ -143,11 +143,11 @@ static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) { if (spip->config->circular) { if ((flags & STM32_DMA_ISR_HTIF) != 0U) { /* Half buffer interrupt.*/ - _spi_isr_half_code(spip); + __spi_isr_half_code(spip); } if ((flags & STM32_DMA_ISR_TCIF) != 0U) { /* End buffer interrupt.*/ - _spi_isr_full_code(spip); + __spi_isr_full_code(spip); } } else { @@ -157,7 +157,7 @@ static void spi_lld_serve_rx_interrupt(SPIDriver *spip, uint32_t flags) { /* Portable SPI ISR code defined in the high level driver, note, it is a macro.*/ - _spi_isr_code(spip); + __spi_isr_code(spip); } } @@ -181,6 +181,36 @@ static void spi_lld_serve_tx_interrupt(SPIDriver *spip, uint32_t flags) { #endif } +static msg_t spi_lld_get_dma(SPIDriver *spip, uint32_t rxstream, + uint32_t txstream, uint32_t priority){ + + spip->dmarx = dmaStreamAllocI(rxstream, priority, + (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, + (void *)spip); + if (spip->dmarx == NULL) { + return HAL_RET_NO_RESOURCE; + } + + spip->dmatx = dmaStreamAllocI(txstream, priority, + (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, + (void *)spip); + if (spip->dmatx == NULL) { + dmaStreamFreeI(spip->dmarx); + return HAL_RET_NO_RESOURCE; + } + + return HAL_RET_SUCCESS; +} + + +static msg_t spi_lld_wait_not_busy(SPIDriver *spip) { + + while ((spip->spi->SR & SPI_SR_BSY) != 0U) { + } + + return HAL_RET_SUCCESS; +} + /*===========================================================================*/ /* Driver interrupt handlers. */ /*===========================================================================*/ @@ -309,122 +339,120 @@ void spi_lld_init(void) { * @brief Configures and activates the SPI peripheral. * * @param[in] spip pointer to the @p SPIDriver object + * @return The operation status. * * @notapi */ -void spi_lld_start(SPIDriver *spip) { +msg_t spi_lld_start(SPIDriver *spip) { uint32_t ds; + msg_t msg; /* If in stopped state then enables the SPI and DMA clocks.*/ if (spip->state == SPI_STOP) { + if (false) { + } + #if STM32_SPI_USE_SPI1 - if (&SPID1 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI1_RX_DMA_STREAM, - STM32_SPI_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI1_TX_DMA_STREAM, - STM32_SPI_SPI1_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + else if (&SPID1 == spip) { + msg = spi_lld_get_dma(spip, + STM32_SPI_SPI1_RX_DMA_STREAM, + STM32_SPI_SPI1_TX_DMA_STREAM, + STM32_SPI_SPI1_IRQ_PRIORITY); + if (msg != HAL_RET_SUCCESS) { + return msg; + } rccEnableSPI1(true); + rccResetSPI1(); #if STM32_DMA_SUPPORTS_DMAMUX dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI1_RX); dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI1_TX); #endif } #endif + #if STM32_SPI_USE_SPI2 if (&SPID2 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI2_RX_DMA_STREAM, - STM32_SPI_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI2_TX_DMA_STREAM, - STM32_SPI_SPI2_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + msg = spi_lld_get_dma(spip, + STM32_SPI_SPI2_RX_DMA_STREAM, + STM32_SPI_SPI2_TX_DMA_STREAM, + STM32_SPI_SPI2_IRQ_PRIORITY); + if (msg != HAL_RET_SUCCESS) { + return msg; + } rccEnableSPI2(true); + rccResetSPI2(); #if STM32_DMA_SUPPORTS_DMAMUX dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI2_RX); dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI2_TX); #endif } #endif + #if STM32_SPI_USE_SPI3 - if (&SPID3 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI3_RX_DMA_STREAM, - STM32_SPI_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI3_TX_DMA_STREAM, - STM32_SPI_SPI3_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + else if (&SPID3 == spip) { + msg = spi_lld_get_dma(spip, + STM32_SPI_SPI3_RX_DMA_STREAM, + STM32_SPI_SPI3_TX_DMA_STREAM, + STM32_SPI_SPI3_IRQ_PRIORITY); + if (msg != HAL_RET_SUCCESS) { + return msg; + } rccEnableSPI3(true); + rccResetSPI3(); #if STM32_DMA_SUPPORTS_DMAMUX dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI3_RX); dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI3_TX); #endif } #endif + #if STM32_SPI_USE_SPI4 - if (&SPID4 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI4_RX_DMA_STREAM, - STM32_SPI_SPI4_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI4_TX_DMA_STREAM, - STM32_SPI_SPI4_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + else if (&SPID4 == spip) { + msg = spi_lld_get_dma(spip, + STM32_SPI_SPI4_RX_DMA_STREAM, + STM32_SPI_SPI4_TX_DMA_STREAM, + STM32_SPI_SPI4_IRQ_PRIORITY); + if (msg != HAL_RET_SUCCESS) { + return msg; + } rccEnableSPI4(true); + rccResetSPI4(); #if STM32_DMA_SUPPORTS_DMAMUX dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI4_RX); dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI4_TX); #endif } #endif + #if STM32_SPI_USE_SPI5 - if (&SPID5 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI5_RX_DMA_STREAM, - STM32_SPI_SPI5_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI5_TX_DMA_STREAM, - STM32_SPI_SPI5_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + else if (&SPID5 == spip) { + msg = spi_lld_get_dma(spip, + STM32_SPI_SPI5_RX_DMA_STREAM, + STM32_SPI_SPI5_TX_DMA_STREAM, + STM32_SPI_SPI5_IRQ_PRIORITY); + if (msg != HAL_RET_SUCCESS) { + return msg; + } rccEnableSPI5(true); + rccResetSPI5(); #if STM32_DMA_SUPPORTS_DMAMUX dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI5_RX); dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI5_TX); #endif } #endif + #if STM32_SPI_USE_SPI6 if (&SPID6 == spip) { - spip->dmarx = dmaStreamAllocI(STM32_SPI_SPI6_RX_DMA_STREAM, - STM32_SPI_SPI6_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_rx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmarx != NULL, "unable to allocate stream"); - spip->dmatx = dmaStreamAllocI(STM32_SPI_SPI6_TX_DMA_STREAM, - STM32_SPI_SPI6_IRQ_PRIORITY, - (stm32_dmaisr_t)spi_lld_serve_tx_interrupt, - (void *)spip); - osalDbgAssert(spip->dmatx != NULL, "unable to allocate stream"); + msg = spi_lld_get_dma(spip, + STM32_SPI_SPI6_RX_DMA_STREAM, + STM32_SPI_SPI6_TX_DMA_STREAM, + STM32_SPI_SPI6_IRQ_PRIORITY); + if (msg != HAL_RET_SUCCESS) { + return msg; + } rccEnableSPI6(true); + rccResetSPI6(); #if STM32_DMA_SUPPORTS_DMAMUX dmaSetRequestSource(spip->dmarx, STM32_DMAMUX1_SPI6_RX); dmaSetRequestSource(spip->dmatx, STM32_DMAMUX1_SPI6_TX); @@ -432,6 +460,10 @@ void spi_lld_start(SPIDriver *spip) { } #endif + else { + osalDbgAssert(false, "invalid SPI instance"); + } + /* DMA setup.*/ dmaStreamSetPeripheral(spip->dmarx, &spip->spi->DR); dmaStreamSetPeripheral(spip->dmatx, &spip->spi->DR); @@ -469,6 +501,8 @@ void spi_lld_start(SPIDriver *spip) { spip->spi->CR2 = spip->config->cr2 | SPI_CR2_FRXTH | SPI_CR2_SSOE | SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN; spip->spi->CR1 |= SPI_CR1_SPE; + + return HAL_RET_SUCCESS; } /** @@ -555,10 +589,11 @@ void spi_lld_unselect(SPIDriver *spip) { * * @param[in] spip pointer to the @p SPIDriver object * @param[in] n number of words to be ignored + * @return The operation status. * * @notapi */ -bool spi_lld_ignore(SPIDriver *spip, size_t n) { +msg_t spi_lld_ignore(SPIDriver *spip, size_t n) { osalDbgAssert(n < 65536, "unsupported DMA transfer size"); @@ -573,7 +608,7 @@ bool spi_lld_ignore(SPIDriver *spip, size_t n) { dmaStreamEnable(spip->dmarx); dmaStreamEnable(spip->dmatx); - return false; + return HAL_RET_SUCCESS; } /** @@ -588,11 +623,12 @@ bool spi_lld_ignore(SPIDriver *spip, size_t n) { * @param[in] n number of words to be exchanged * @param[in] txbuf the pointer to the transmit buffer * @param[out] rxbuf the pointer to the receive buffer + * @return The operation status. * * @notapi */ -bool spi_lld_exchange(SPIDriver *spip, size_t n, - const void *txbuf, void *rxbuf) { +msg_t spi_lld_exchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf) { osalDbgAssert(n < 65536, "unsupported DMA transfer size"); @@ -607,7 +643,7 @@ bool spi_lld_exchange(SPIDriver *spip, size_t n, dmaStreamEnable(spip->dmarx); dmaStreamEnable(spip->dmatx); - return false; + return HAL_RET_SUCCESS; } /** @@ -620,10 +656,11 @@ bool spi_lld_exchange(SPIDriver *spip, size_t n, * @param[in] spip pointer to the @p SPIDriver object * @param[in] n number of words to send * @param[in] txbuf the pointer to the transmit buffer + * @return The operation status. * * @notapi */ -void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { +msg_t spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { osalDbgAssert(n < 65536, "unsupported DMA transfer size"); @@ -637,6 +674,8 @@ void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { dmaStreamEnable(spip->dmarx); dmaStreamEnable(spip->dmatx); + + return HAL_RET_SUCCESS; } /** @@ -649,10 +688,11 @@ void spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf) { * @param[in] spip pointer to the @p SPIDriver object * @param[in] n number of words to receive * @param[out] rxbuf the pointer to the receive buffer + * @return The operation status. * * @notapi */ -void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { +msg_t spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { osalDbgAssert(n < 65536, "unsupported DMA transfer size"); @@ -666,23 +706,38 @@ void spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf) { dmaStreamEnable(spip->dmarx); dmaStreamEnable(spip->dmatx); + + return HAL_RET_SUCCESS; } -#if (SPI_SUPPORTS_CIRCULAR == TRUE) || defined(__DOXYGEN__) /** * @brief Aborts the ongoing SPI operation, if any. * * @param[in] spip pointer to the @p SPIDriver object + * @param[out sizep pointer to the counter of frames not yet transferred + * or @p NULL + * @return The operation status. * * @notapi */ -void spi_lld_abort(SPIDriver *spip) { +msg_t spi_lld_stop_transfer(SPIDriver *spip, size_t *sizep) { + msg_t msg; - /* Stopping DMAs.*/ + /* Stopping TX DMA.*/ dmaStreamDisable(spip->dmatx); + + /* Waiting for the SPI to become not busy.*/ + msg = spi_lld_wait_not_busy(spip); + + /* Stopping RX DMA.*/ dmaStreamDisable(spip->dmarx); + + if (sizep != NULL) { + *sizep = dmaStreamGetTransactionSize(spip->dmatx); + } + + return msg; } -#endif /* SPI_SUPPORTS_CIRCULAR == TRUE */ /** * @brief Exchanges one frame using a polled wait. diff --git a/os/hal/ports/STM32/LLD/SPIv2/hal_spi_v2_lld.h b/os/hal/ports/STM32/LLD/SPIv2/hal_spi_v2_lld.h new file mode 100644 index 000000000..48c0406c8 --- /dev/null +++ b/os/hal/ports/STM32/LLD/SPIv2/hal_spi_v2_lld.h @@ -0,0 +1,554 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file SPIv2/hal_spi_lld.h + * @brief STM32 SPI subsystem low level driver header. + * + * @addtogroup SPI + * @{ + */ + +#ifndef HAL_SPI_LLD_H +#define HAL_SPI_LLD_H + +#if HAL_USE_SPI || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Circular mode support flag. + */ +#define SPI_SUPPORTS_CIRCULAR TRUE + +/** + * @brief Slave mode support flag. + */ +#define SPI_SUPPORTS_SLAVE_MODE FALSE + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief SPI1 driver enable switch. + * @details If set to @p TRUE the support for SPI1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI1) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI1 FALSE +#endif + +/** + * @brief SPI2 driver enable switch. + * @details If set to @p TRUE the support for SPI2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI2) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI2 FALSE +#endif + +/** + * @brief SPI3 driver enable switch. + * @details If set to @p TRUE the support for SPI3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI3) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI3 FALSE +#endif + +/** + * @brief SPI4 driver enable switch. + * @details If set to @p TRUE the support for SPI4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI4) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI4 FALSE +#endif + +/** + * @brief SPI5 driver enable switch. + * @details If set to @p TRUE the support for SPI5 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI5) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI5 FALSE +#endif + +/** + * @brief SPI6 driver enable switch. + * @details If set to @p TRUE the support for SPI6 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_SPI_USE_SPI6) || defined(__DOXYGEN__) +#define STM32_SPI_USE_SPI6 FALSE +#endif + +/** + * @brief SPI1 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI1_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI2 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI2_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI3 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI3_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI4 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI4_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI5 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI5_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI5_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI6 interrupt priority level setting. + */ +#if !defined(STM32_SPI_SPI6_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI6_IRQ_PRIORITY 10 +#endif + +/** + * @brief SPI1 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI1_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI2 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI2_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI3 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI3_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI4 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI4_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI4_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI5 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI5_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI5_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI6 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_SPI_SPI6_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_SPI_SPI6_DMA_PRIORITY 1 +#endif + +/** + * @brief SPI DMA error hook. + */ +#if !defined(STM32_SPI_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_SPI_DMA_ERROR_HOOK(spip) osalSysHalt("DMA failure") +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if STM32_SPI_USE_SPI1 && !STM32_HAS_SPI1 +#error "SPI1 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI2 && !STM32_HAS_SPI2 +#error "SPI2 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI3 && !STM32_HAS_SPI3 +#error "SPI3 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI4 && !STM32_HAS_SPI4 +#error "SPI4 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI5 && !STM32_HAS_SPI5 +#error "SPI5 not present in the selected device" +#endif + +#if STM32_SPI_USE_SPI6 && !STM32_HAS_SPI6 +#error "SPI6 not present in the selected device" +#endif + +#if !STM32_SPI_USE_SPI1 && !STM32_SPI_USE_SPI2 && !STM32_SPI_USE_SPI3 && \ + !STM32_SPI_USE_SPI4 && !STM32_SPI_USE_SPI5 && !STM32_SPI_USE_SPI6 +#error "SPI driver activated but no SPI peripheral assigned" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI1" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI2" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI3" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI4" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI5_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI5" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_SPI_SPI6_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to SPI6" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI1" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI2" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI3" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI4_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI4" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI5_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI5" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_SPI_SPI6_DMA_PRIORITY) +#error "Invalid DMA priority assigned to SPI6" +#endif + +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_SPI_USE_SPI1 && (!defined(STM32_SPI_SPI1_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI1_TX_DMA_STREAM)) +#error "SPI1 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI2 && (!defined(STM32_SPI_SPI2_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI2_TX_DMA_STREAM)) +#error "SPI2 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI3 && (!defined(STM32_SPI_SPI3_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI3_TX_DMA_STREAM)) +#error "SPI3 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI4 && (!defined(STM32_SPI_SPI4_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI4_TX_DMA_STREAM)) +#error "SPI4 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI5 && (!defined(STM32_SPI_SPI5_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI5_TX_DMA_STREAM)) +#error "SPI5 DMA streams not defined" +#endif + +#if STM32_SPI_USE_SPI6 && (!defined(STM32_SPI_SPI6_RX_DMA_STREAM) || \ + !defined(STM32_SPI_SPI6_TX_DMA_STREAM)) +#error "SPI6 DMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI1_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI1 TX" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI2_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI2 RX" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI2_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI2 TX" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI3_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI3 RX" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI3_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI3 TX" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI4_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI4 RX" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI4_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI4 TX" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI5_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI5 RX" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI5_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI5 TX" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI6_RX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI6 RX" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !STM32_DMA_IS_VALID_STREAM(STM32_SPI_SPI6_TX_DMA_STREAM) +#error "Invalid DMA channel assigned to SPI6 TX" +#endif + +/* Devices without DMAMUX require an additional check.*/ +#if STM32_ADVANCED_DMA && !STM32_DMA_SUPPORTS_DMAMUX + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_RX_DMA_STREAM, STM32_SPI1_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI1 RX" +#endif + +#if STM32_SPI_USE_SPI1 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI1_TX_DMA_STREAM, STM32_SPI1_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI1 TX" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_RX_DMA_STREAM, STM32_SPI2_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI2 RX" +#endif + +#if STM32_SPI_USE_SPI2 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI2_TX_DMA_STREAM, STM32_SPI2_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI2 TX" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_RX_DMA_STREAM, STM32_SPI3_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI3 RX" +#endif + +#if STM32_SPI_USE_SPI3 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI3_TX_DMA_STREAM, STM32_SPI3_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI3 TX" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI4_RX_DMA_STREAM, STM32_SPI4_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI4 RX" +#endif + +#if STM32_SPI_USE_SPI4 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI4_TX_DMA_STREAM, STM32_SPI4_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI4 TX" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI5_RX_DMA_STREAM, STM32_SPI5_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI5 RX" +#endif + +#if STM32_SPI_USE_SPI5 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI5_TX_DMA_STREAM, STM32_SPI5_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI5 TX" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI6_RX_DMA_STREAM, STM32_SPI6_RX_DMA_MSK) +#error "invalid DMA stream associated to SPI6 RX" +#endif + +#if STM32_SPI_USE_SPI6 && \ + !STM32_DMA_IS_VALID_ID(STM32_SPI_SPI6_TX_DMA_STREAM, STM32_SPI6_TX_DMA_MSK) +#error "invalid DMA stream associated to SPI6 TX" +#endif + +#endif /* STM32_ADVANCED_DMA && !STM32_DMA_SUPPORTS_DMAMUX */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +#if SPI_SELECT_MODE == SPI_SELECT_MODE_LLD +#error "SPI_SELECT_MODE_LLD not supported by this driver" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Low level fields of the SPI driver structure. + */ +#define spi_lld_driver_fields \ + /* Pointer to the SPIx registers block.*/ \ + SPI_TypeDef *spi; \ + /* Receive DMA stream.*/ \ + const stm32_dma_stream_t *dmarx; \ + /* Transmit DMA stream.*/ \ + const stm32_dma_stream_t *dmatx; \ + /* RX DMA mode bit mask.*/ \ + uint32_t rxdmamode; \ + /* TX DMA mode bit mask.*/ \ + uint32_t txdmamode + +/** + * @brief Low level fields of the SPI configuration structure. + */ +#define spi_lld_config_fields \ + /* SPI CR1 register initialization data.*/ \ + uint16_t cr1; \ + /* SPI CR2 register initialization data.*/ \ + uint16_t cr2 + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if STM32_SPI_USE_SPI1 && !defined(__DOXYGEN__) +extern SPIDriver SPID1; +#endif + +#if STM32_SPI_USE_SPI2 && !defined(__DOXYGEN__) +extern SPIDriver SPID2; +#endif + +#if STM32_SPI_USE_SPI3 && !defined(__DOXYGEN__) +extern SPIDriver SPID3; +#endif + +#if STM32_SPI_USE_SPI4 && !defined(__DOXYGEN__) +extern SPIDriver SPID4; +#endif + +#if STM32_SPI_USE_SPI5 && !defined(__DOXYGEN__) +extern SPIDriver SPID5; +#endif + +#if STM32_SPI_USE_SPI6 && !defined(__DOXYGEN__) +extern SPIDriver SPID6; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void spi_lld_init(void); + msg_t spi_lld_start(SPIDriver *spip); + void spi_lld_stop(SPIDriver *spip); +#if (SPI_SELECT_MODE == SPI_SELECT_MODE_LLD) || defined(__DOXYGEN__) + void spi_lld_select(SPIDriver *spip); + void spi_lld_unselect(SPIDriver *spip); +#endif + msg_t spi_lld_ignore(SPIDriver *spip, size_t n); + msg_t spi_lld_exchange(SPIDriver *spip, size_t n, + const void *txbuf, void *rxbuf); + msg_t spi_lld_send(SPIDriver *spip, size_t n, const void *txbuf); + msg_t spi_lld_receive(SPIDriver *spip, size_t n, void *rxbuf); + msg_t spi_lld_stop_transfer(SPIDriver *spip, size_t *sizep); +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_SPI */ + +#endif /* HAL_SPI_LLD_H */ + +/** @} */ diff --git a/os/hal/src/hal_spi_v2.inc b/os/hal/src/hal_spi_v2.inc index 7417637e0..3e8f6d070 100644 --- a/os/hal/src/hal_spi_v2.inc +++ b/os/hal/src/hal_spi_v2.inc @@ -98,13 +98,8 @@ msg_t spiStart(SPIDriver *spip, const SPIConfig *config) { spip->config = config; -#if defined(SPI_LLD_ENHANCED_API) msg = spi_lld_start(spip); -#else - spi_lld_start(spip); - msg = HAL_START_SUCCESS; -#endif - if (msg == HAL_START_SUCCESS) { + if (msg == HAL_RET_SUCCESS) { spip->state = SPI_READY; } else { @@ -113,6 +108,10 @@ msg_t spiStart(SPIDriver *spip, const SPIConfig *config) { osalSysUnlock(); +#if SPI_USE_ASSERT_ON_ERROR == TRUE + osalDbgAssert(msg == HAL_RET_SUCCESS, "function failed"); +#endif + return msg; } @@ -185,12 +184,13 @@ void spiUnselect(SPIDriver *spip) { * @param[in] spip pointer to the @p SPIDriver object * @param[in] n number of words to be ignored * @return The operation status. - * @retval false if the operation started correctly. - * @retval true if the operation did not start. * * @iclass */ -bool spiStartIgnoreI(SPIDriver *spip, size_t n) { +msg_t spiStartIgnoreI(SPIDriver *spip, size_t n) { + msg_t msg; + + osalDbgCheckClassI(); osalDbgCheck((spip != NULL) && (n > 0U)); #if SPI_SUPPORTS_CIRCULAR @@ -200,7 +200,13 @@ bool spiStartIgnoreI(SPIDriver *spip, size_t n) { osalDbgAssert(spip->state == SPI_READY, "not ready"); spip->state = SPI_ACTIVE; - return spi_lld_ignore(spip, n); + msg = spi_lld_ignore(spip, n); + +#if SPI_USE_ASSERT_ON_ERROR == TRUE + osalDbgAssert(msg == HAL_RET_SUCCESS, "function failed"); +#endif + + return msg; } /** @@ -214,19 +220,17 @@ bool spiStartIgnoreI(SPIDriver *spip, size_t n) { * @param[in] spip pointer to the @p SPIDriver object * @param[in] n number of words to be ignored * @return The operation status. - * @retval false if the operation started correctly. - * @retval true if the operation did not start. * * @api */ -bool spiStartIgnore(SPIDriver *spip, size_t n) { - bool ret; +msg_t spiStartIgnore(SPIDriver *spip, size_t n) { + msg_t msg; osalSysLock(); - ret = spiStartIgnoreI(spip, n); + msg = spiStartIgnoreI(spip, n); osalSysUnlock(); - return ret; + return msg; } /** @@ -244,13 +248,14 @@ bool spiStartIgnore(SPIDriver *spip, size_t n) { * @param[in] txbuf the pointer to the transmit buffer * @param[out] rxbuf the pointer to the receive buffer * @return The operation status. - * @retval false if the operation started correctly. - * @retval true if the operation did not start. * * @iclass */ -bool spiStartExchangeI(SPIDriver *spip, size_t n, +msg_t spiStartExchangeI(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf) { + msg_t msg; + + osalDbgCheckClassI(); osalDbgCheck((spip != NULL) && (n > 0U) && (rxbuf != NULL) && (txbuf != NULL)); @@ -261,7 +266,13 @@ bool spiStartExchangeI(SPIDriver *spip, size_t n, osalDbgAssert(spip->state == SPI_READY, "not ready"); spip->state = SPI_ACTIVE; - return spi_lld_exchange(spip, n, txbuf, rxbuf); + msg = spi_lld_exchange(spip, n, txbuf, rxbuf); + +#if SPI_USE_ASSERT_ON_ERROR == TRUE + osalDbgAssert(msg == HAL_RET_SUCCESS, "function failed"); +#endif + + return msg; } /** @@ -279,20 +290,18 @@ bool spiStartExchangeI(SPIDriver *spip, size_t n, * @param[in] txbuf the pointer to the transmit buffer * @param[out] rxbuf the pointer to the receive buffer * @return The operation status. - * @retval false if the operation started correctly. - * @retval true if the operation did not start. * * @api */ -bool spiStartExchange(SPIDriver *spip, size_t n, +msg_t spiStartExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf) { - bool ret; + msg_t msg; osalSysLock(); - ret = spiStartExchangeI(spip, n, txbuf, rxbuf); + msg = spiStartExchangeI(spip, n, txbuf, rxbuf); osalSysUnlock(); - return ret; + return msg; } /** @@ -308,12 +317,13 @@ bool spiStartExchange(SPIDriver *spip, size_t n, * @param[in] n number of words to send * @param[in] txbuf the pointer to the transmit buffer * @return The operation status. - * @retval false if the operation started correctly. - * @retval true if the operation did not start. * * @iclass */ -bool spiStartSendI(SPIDriver *spip, size_t n, const void *txbuf) { +msg_t spiStartSendI(SPIDriver *spip, size_t n, const void *txbuf) { + msg_t msg; + + osalDbgCheckClassI(); osalDbgCheck((spip != NULL) && (n > 0U) && (txbuf != NULL)); #if SPI_SUPPORTS_CIRCULAR @@ -323,7 +333,13 @@ bool spiStartSendI(SPIDriver *spip, size_t n, const void *txbuf) { osalDbgAssert(spip->state == SPI_READY, "not ready"); spip->state = SPI_ACTIVE; - return spi_lld_send(spip, n, txbuf); + msg = spi_lld_send(spip, n, txbuf); + +#if SPI_USE_ASSERT_ON_ERROR == TRUE + osalDbgAssert(msg == HAL_RET_SUCCESS, "function failed"); +#endif + + return msg; } /** @@ -339,19 +355,17 @@ bool spiStartSendI(SPIDriver *spip, size_t n, const void *txbuf) { * @param[in] n number of words to send * @param[in] txbuf the pointer to the transmit buffer * @return The operation status. - * @retval false if the operation started correctly. - * @retval true if the operation did not start. * * @api */ -bool spiStartSend(SPIDriver *spip, size_t n, const void *txbuf) { - bool ret; +msg_t spiStartSend(SPIDriver *spip, size_t n, const void *txbuf) { + msg_t msg; osalSysLock(); - ret = spiStartSendI(spip, n, txbuf); + msg = spiStartSendI(spip, n, txbuf); osalSysUnlock(); - return ret; + return msg; } /** @@ -367,12 +381,13 @@ bool spiStartSend(SPIDriver *spip, size_t n, const void *txbuf) { * @param[in] n number of words to receive * @param[out] rxbuf the pointer to the receive buffer * @return The operation status. - * @retval false if the operation started correctly. - * @retval true if the operation did not start. * * @iclass */ -bool spiStartReceiveI(SPIDriver *spip, size_t n, void *rxbuf) { +msg_t spiStartReceiveI(SPIDriver *spip, size_t n, void *rxbuf) { + msg_t msg; + + osalDbgCheckClassI(); osalDbgCheck((spip != NULL) && (n > 0U) && (rxbuf != NULL)); #if SPI_SUPPORTS_CIRCULAR @@ -382,7 +397,13 @@ bool spiStartReceiveI(SPIDriver *spip, size_t n, void *rxbuf) { osalDbgAssert(spip->state == SPI_READY, "not ready"); spip->state = SPI_ACTIVE; - return spi_lld_receive(spip, n, rxbuf); + msg = spi_lld_receive(spip, n, rxbuf); + +#if SPI_USE_ASSERT_ON_ERROR == TRUE + osalDbgAssert(msg == HAL_RET_SUCCESS, "function failed"); +#endif + + return msg; } /** @@ -398,19 +419,79 @@ bool spiStartReceiveI(SPIDriver *spip, size_t n, void *rxbuf) { * @param[in] n number of words to receive * @param[out] rxbuf the pointer to the receive buffer * @return The operation status. - * @retval false if the operation started correctly. - * @retval true if the operation did not start. * * @api */ -bool spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf) { - bool ret; +msg_t spiStartReceive(SPIDriver *spip, size_t n, void *rxbuf) { + msg_t msg; osalSysLock(); - ret = spiStartReceiveI(spip, n, rxbuf); + msg = spiStartReceiveI(spip, n, rxbuf); osalSysUnlock(); - return ret; + return msg; +} + +/** + * @brief Stops the ongoing SPI operation. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[out sizep pointer to the counter of frames not yet transferred + * or @p NULL + * @return The operation status. + * + * @iclass + */ +msg_t spiStopTranferI(SPIDriver *spip, size_t *sizep) { + msg_t msg; + + osalDbgCheckClassI(); + + osalDbgCheck(spip != NULL); + + osalDbgAssert((spip->state == SPI_READY) || + (spip->state == SPI_ACTIVE) || + (spip->state == SPI_COMPLETE), + "invalid state"); + + if ((spip->state == SPI_ACTIVE) || (spip->state == SPI_COMPLETE)) { + + /* Stopping transfer at low level.*/ + msg = spi_lld_stop_transfer(spip, sizep); + spip->state = SPI_READY; + +#if SPI_USE_SYNCHRONIZATION == TRUE + osalThreadResumeI(&spip->sync_transfer, MSG_OK); +#endif + } + else { + msg = HAL_RET_SUCCESS; + } + + return msg; +} + +/** + * @brief Stops the ongoing SPI operation, if any. + * + * @param[in] spip pointer to the @p SPIDriver object + * @param[out sizep pointer to the counter of frames not yet transferred + * or @p NULL + * @return The operation status. + * + * @api + */ +msg_t spiStopTranfer(SPIDriver *spip, size_t *sizep) { + msg_t msg; + + osalSysLock(); + + msg = spiStopTranferI(spip, sizep); + osalOsRescheduleS(); + + osalSysUnlock(); + + return msg; } #if (SPI_USE_SYNCHRONIZATION == TRUE) || defined(__DOXYGEN__) @@ -474,16 +555,23 @@ msg_t spiSynchronize(SPIDriver *spip, sysinterval_t timeout) { * * @param[in] spip pointer to the @p SPIDriver object * @param[in] n number of words to be ignored + * @return The operation status. * * @api */ -void spiIgnore(SPIDriver *spip, size_t n) { - bool ret; +msg_t spiIgnore(SPIDriver *spip, size_t n) { + msg_t msg; osalSysLock(); - spiStartIgnoreI(spip, n); - (void) spiSynchronizeS(spip, TIME_INFINITE); + + msg = spiStartIgnoreI(spip, n); + if (msg != MSG_OK) { + msg = spiSynchronizeS(spip, TIME_INFINITE); + } + osalSysUnlock(); + + return msg; } /** @@ -499,16 +587,24 @@ void spiIgnore(SPIDriver *spip, size_t n) { * @param[in] n number of words to be exchanged * @param[in] txbuf the pointer to the transmit buffer * @param[out] rxbuf the pointer to the receive buffer + * @return The operation status. * * @api */ -void spiExchange(SPIDriver *spip, size_t n, +msg_t spiExchange(SPIDriver *spip, size_t n, const void *txbuf, void *rxbuf) { + msg_t msg; osalSysLock(); - spiStartExchangeI(spip, n, txbuf, rxbuf); - (void) spiSynchronizeS(spip, TIME_INFINITE); + + msg = spiStartExchangeI(spip, n, txbuf, rxbuf); + if (msg != MSG_OK) { + msg = spiSynchronizeS(spip, TIME_INFINITE); + } + osalSysUnlock(); + + return msg; } /** @@ -522,15 +618,23 @@ void spiExchange(SPIDriver *spip, size_t n, * @param[in] spip pointer to the @p SPIDriver object * @param[in] n number of words to send * @param[in] txbuf the pointer to the transmit buffer + * @return The operation status. * * @api */ -void spiSend(SPIDriver *spip, size_t n, const void *txbuf) { +msg_t spiSend(SPIDriver *spip, size_t n, const void *txbuf) { + msg_t msg; osalSysLock(); - spiStartSendI(spip, n, txbuf); - (void) spiSynchronizeS(spip, TIME_INFINITE); + + msg = spiStartSendI(spip, n, txbuf); + if (msg != MSG_OK) { + msg = spiSynchronizeS(spip, TIME_INFINITE); + } + osalSysUnlock(); + + return msg; } /** @@ -544,15 +648,23 @@ void spiSend(SPIDriver *spip, size_t n, const void *txbuf) { * @param[in] spip pointer to the @p SPIDriver object * @param[in] n number of words to receive * @param[out] rxbuf the pointer to the receive buffer + * @return The operation status. * * @api */ -void spiReceive(SPIDriver *spip, size_t n, void *rxbuf) { +msg_t spiReceive(SPIDriver *spip, size_t n, void *rxbuf) { + msg_t msg; osalSysLock(); - spiStartReceiveI(spip, n, rxbuf); - (void) spiSynchronizeS(spip, TIME_INFINITE); + + msg = spiStartReceiveI(spip, n, rxbuf); + if (msg != MSG_OK) { + msg = spiSynchronizeS(spip, TIME_INFINITE); + } + osalSysUnlock(); + + return msg; } #endif /* SPI_USE_SYNCHRONIZATION == TRUE */