mirror of
https://github.com/apache/nuttx.git
synced 2026-06-02 01:21:26 +08:00
stm32f0l0g0/stm32_spi.c: fix receiving data for half duplex mode
This commit is contained in:
@@ -184,6 +184,8 @@ struct stm32_spidev_s
|
|||||||
struct pm_callback_s pm_cb; /* PM callbacks */
|
struct pm_callback_s pm_cb; /* PM callbacks */
|
||||||
#endif
|
#endif
|
||||||
enum spi_config_e config; /* full/half duplex, simplex transmit/read only */
|
enum spi_config_e config; /* full/half duplex, simplex transmit/read only */
|
||||||
|
bool rx_now; /* Half duplex only: receiving data now */
|
||||||
|
bool rx_mode; /* Half duplex only: SPI_CR1_BIDIOE bit status */
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -196,6 +198,7 @@ static inline uint16_t spi_getreg(struct stm32_spidev_s *priv,
|
|||||||
uint8_t offset);
|
uint8_t offset);
|
||||||
static inline void spi_putreg(struct stm32_spidev_s *priv,
|
static inline void spi_putreg(struct stm32_spidev_s *priv,
|
||||||
uint8_t offset, uint16_t value);
|
uint8_t offset, uint16_t value);
|
||||||
|
static inline void spi_rx_mode(struct stm32_spidev_s *priv, bool enable);
|
||||||
static inline uint16_t spi_readword(struct stm32_spidev_s *priv);
|
static inline uint16_t spi_readword(struct stm32_spidev_s *priv);
|
||||||
static inline void spi_writeword(struct stm32_spidev_s *priv,
|
static inline void spi_writeword(struct stm32_spidev_s *priv,
|
||||||
uint16_t byte);
|
uint16_t byte);
|
||||||
@@ -430,6 +433,62 @@ static inline void spi_putreg(struct stm32_spidev_s *priv,
|
|||||||
putreg16(value, priv->spibase + offset);
|
putreg16(value, priv->spibase + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: spi_rx_mode
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Activate SPI RX or SPI TX for the half-duplex mode
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static inline void spi_rx_mode(struct stm32_spidev_s *priv, bool enable)
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
{
|
||||||
|
/* Enable RX */
|
||||||
|
|
||||||
|
if (!priv->rx_mode)
|
||||||
|
{
|
||||||
|
/* Disable SPI */
|
||||||
|
|
||||||
|
spi_modifycr(STM32_SPI_CR1_OFFSET, priv, 0, SPI_CR1_SPE);
|
||||||
|
|
||||||
|
/* Disable output for half-duplex mode - SPI starts to
|
||||||
|
* automatically output clocks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
spi_modifycr(STM32_SPI_CR1_OFFSET, priv, 0, SPI_CR1_BIDIOE);
|
||||||
|
|
||||||
|
/* Enable SPI */
|
||||||
|
|
||||||
|
spi_modifycr(STM32_SPI_CR1_OFFSET, priv, SPI_CR1_SPE, 0);
|
||||||
|
|
||||||
|
priv->rx_mode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Enable TX */
|
||||||
|
|
||||||
|
if (priv->rx_mode)
|
||||||
|
{
|
||||||
|
/* Disable SPI */
|
||||||
|
|
||||||
|
spi_modifycr(STM32_SPI_CR1_OFFSET, priv, 0, SPI_CR1_SPE);
|
||||||
|
|
||||||
|
/* Enable TX output */
|
||||||
|
|
||||||
|
spi_modifycr(STM32_SPI_CR1_OFFSET, priv, SPI_CR1_BIDIOE, 0);
|
||||||
|
|
||||||
|
/* Enable SPI */
|
||||||
|
|
||||||
|
spi_modifycr(STM32_SPI_CR1_OFFSET, priv, SPI_CR1_SPE, 0);
|
||||||
|
|
||||||
|
priv->rx_mode = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: spi_getreg8
|
* Name: spi_getreg8
|
||||||
*
|
*
|
||||||
@@ -495,15 +554,18 @@ static inline uint16_t spi_readword(struct stm32_spidev_s *priv)
|
|||||||
|
|
||||||
if (priv->config == HALF_DUPLEX)
|
if (priv->config == HALF_DUPLEX)
|
||||||
{
|
{
|
||||||
/* Disable output for half-duplex mode */
|
spi_rx_mode(priv, true);
|
||||||
|
|
||||||
spi_modifycr(STM32_SPI_CR1_OFFSET, priv, 0, SPI_CR1_BIDIOE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait until the receive buffer is not empty */
|
/* Wait until the receive buffer is not empty */
|
||||||
|
|
||||||
while ((spi_getreg(priv, STM32_SPI_SR_OFFSET) & SPI_SR_RXNE) == 0);
|
while ((spi_getreg(priv, STM32_SPI_SR_OFFSET) & SPI_SR_RXNE) == 0);
|
||||||
|
|
||||||
|
if (priv->config == HALF_DUPLEX)
|
||||||
|
{
|
||||||
|
spi_rx_mode(priv, false);
|
||||||
|
}
|
||||||
|
|
||||||
/* Then return the received byte */
|
/* Then return the received byte */
|
||||||
|
|
||||||
return spi_getreg(priv, STM32_SPI_DR_OFFSET);
|
return spi_getreg(priv, STM32_SPI_DR_OFFSET);
|
||||||
@@ -536,9 +598,7 @@ static inline void spi_writeword(struct stm32_spidev_s *priv,
|
|||||||
|
|
||||||
if (priv->config == HALF_DUPLEX)
|
if (priv->config == HALF_DUPLEX)
|
||||||
{
|
{
|
||||||
/* Enable output for half-duplex mode */
|
spi_rx_mode(priv, false);
|
||||||
|
|
||||||
spi_modifycr(STM32_SPI_CR1_OFFSET, priv, SPI_CR1_BIDIOE, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait until the transmit buffer is empty */
|
/* Wait until the transmit buffer is empty */
|
||||||
@@ -576,6 +636,13 @@ static inline void spi_writeword(struct stm32_spidev_s *priv,
|
|||||||
{
|
{
|
||||||
spi_putreg(priv, STM32_SPI_DR_OFFSET, word);
|
spi_putreg(priv, STM32_SPI_DR_OFFSET, word);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (priv->config == HALF_DUPLEX)
|
||||||
|
{
|
||||||
|
/* Wait for data transfer to be completed */
|
||||||
|
|
||||||
|
while ((spi_getreg(priv, STM32_SPI_SR_OFFSET) & SPI_SR_BSY) != 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@@ -1289,12 +1356,32 @@ static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd)
|
|||||||
{
|
{
|
||||||
struct stm32_spidev_s *priv = (struct stm32_spidev_s *)dev;
|
struct stm32_spidev_s *priv = (struct stm32_spidev_s *)dev;
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
uint32_t ret;
|
uint32_t ret = 0;
|
||||||
|
|
||||||
DEBUGASSERT(priv && priv->spibase);
|
DEBUGASSERT(priv && priv->spibase);
|
||||||
|
|
||||||
spi_writeword(priv, (uint16_t)(wd & 0xffff));
|
if (priv->config != HALF_DUPLEX)
|
||||||
ret = (uint32_t)spi_readword(priv);
|
{
|
||||||
|
spi_writeword(priv, (uint16_t)(wd & 0xffff));
|
||||||
|
ret = (uint32_t)spi_readword(priv);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* In half duplex we must send data and receive data in separate
|
||||||
|
* spi_send() calls.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!priv->rx_now)
|
||||||
|
{
|
||||||
|
spi_writeword(priv, (uint16_t)(wd & 0xffff));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = (uint32_t)spi_readword(priv);
|
||||||
|
|
||||||
|
priv->rx_now = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Check and clear any error flags (Reading from the SR clears the error
|
/* Check and clear any error flags (Reading from the SR clears the error
|
||||||
* flags)
|
* flags)
|
||||||
@@ -1361,10 +1448,12 @@ static void spi_exchange_nodma(struct spi_dev_s *dev,
|
|||||||
if (src)
|
if (src)
|
||||||
{
|
{
|
||||||
word = *src++;
|
word = *src++;
|
||||||
|
priv->rx_now = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
word = 0xffff;
|
word = 0xffff;
|
||||||
|
priv->rx_now = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Exchange one word */
|
/* Exchange one word */
|
||||||
@@ -1394,10 +1483,12 @@ static void spi_exchange_nodma(struct spi_dev_s *dev,
|
|||||||
if (src)
|
if (src)
|
||||||
{
|
{
|
||||||
word = *src++;
|
word = *src++;
|
||||||
|
priv->rx_now = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
word = 0xff;
|
word = 0xff;
|
||||||
|
priv->rx_now = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Exchange one word */
|
/* Exchange one word */
|
||||||
@@ -1746,8 +1837,9 @@ static void spi_bus_initialize(struct stm32_spidev_s *priv)
|
|||||||
setbits |= SPI_CR1_RXONLY;
|
setbits |= SPI_CR1_RXONLY;
|
||||||
break;
|
break;
|
||||||
case HALF_DUPLEX:
|
case HALF_DUPLEX:
|
||||||
clrbits |= SPI_CR1_BIDIOE | SPI_CR1_RXONLY;
|
clrbits |= SPI_CR1_RXONLY;
|
||||||
setbits |= SPI_CR1_BIDIMODE;
|
setbits |= SPI_CR1_BIDIOE | SPI_CR1_BIDIMODE; /* TX mode */
|
||||||
|
priv->rx_mode = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1787,8 +1879,9 @@ static void spi_bus_initialize(struct stm32_spidev_s *priv)
|
|||||||
setbits |= SPI_CR1_RXONLY;
|
setbits |= SPI_CR1_RXONLY;
|
||||||
break;
|
break;
|
||||||
case HALF_DUPLEX:
|
case HALF_DUPLEX:
|
||||||
clrbits |= SPI_CR1_BIDIOE | SPI_CR1_RXONLY;
|
clrbits |= SPI_CR1_RXONLY;
|
||||||
setbits |= SPI_CR1_BIDIMODE;
|
setbits |= SPI_CR1_BIDIOE | SPI_CR1_BIDIMODE; /* TX mode */
|
||||||
|
priv->rx_mode = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user