Experimental SPI v2 code, not finished.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@14915 27425a3e-05d8-49a3-a47f-9c15f0e5edd8
This commit is contained in:
Giovanni Di Sirio 2021-10-17 08:56:23 +00:00
parent a0982b7301
commit e5098d67e4
5 changed files with 900 additions and 159 deletions

View File

@ -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);
bool spiStartExchange(SPIDriver *spip, size_t n,
msg_t 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);

View File

@ -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

View File

@ -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,10 +623,11 @@ 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,
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.

View File

@ -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 */
/** @} */

View File

@ -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 */