Merged in juniskane/nuttx_stm32l4/stm32_serial_patches_pr (pull request #504)
Stm32, stm32l4 serial patches * stm32: serial: add interface to get uart_dev_t by USART number, stm32_serial_get_uart * stm32: serial: do not stop processing input in SW flow-control mode * stm32l4: serial: do not stop processing input in SW flow-control mode * stm32l4: serial: suspend serial for Stop mode Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
parent
ecf6dda2c5
commit
798d03cb3d
@ -277,6 +277,10 @@ struct up_dev_s
|
|||||||
uint16_t ie; /* Saved interrupt mask bits value */
|
uint16_t ie; /* Saved interrupt mask bits value */
|
||||||
uint16_t sr; /* Saved status bits */
|
uint16_t sr; /* Saved status bits */
|
||||||
|
|
||||||
|
/* Has been initialized and HW is setup. */
|
||||||
|
|
||||||
|
bool initialized;
|
||||||
|
|
||||||
/* If termios are supported, then the following fields may vary at
|
/* If termios are supported, then the following fields may vary at
|
||||||
* runtime.
|
* runtime.
|
||||||
*/
|
*/
|
||||||
@ -1559,6 +1563,11 @@ static int up_setup(struct uart_dev_s *dev)
|
|||||||
/* Set up the cached interrupt enables value */
|
/* Set up the cached interrupt enables value */
|
||||||
|
|
||||||
priv->ie = 0;
|
priv->ie = 0;
|
||||||
|
|
||||||
|
/* Mark device as initialized. */
|
||||||
|
|
||||||
|
priv->initialized = true;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1638,6 +1647,10 @@ static void up_shutdown(struct uart_dev_s *dev)
|
|||||||
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
|
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
|
|
||||||
|
/* Mark device as uninitialized. */
|
||||||
|
|
||||||
|
priv->initialized = false;
|
||||||
|
|
||||||
/* Disable all interrupts */
|
/* Disable all interrupts */
|
||||||
|
|
||||||
up_disableusartint(priv, NULL);
|
up_disableusartint(priv, NULL);
|
||||||
@ -2287,6 +2300,22 @@ static bool up_rxflowcontrol(struct uart_dev_s *dev,
|
|||||||
/* Assert/de-assert nRTS set it high resume/stop sending */
|
/* Assert/de-assert nRTS set it high resume/stop sending */
|
||||||
|
|
||||||
stm32_gpiowrite(priv->rts_gpio, upper);
|
stm32_gpiowrite(priv->rts_gpio, upper);
|
||||||
|
|
||||||
|
if (upper)
|
||||||
|
{
|
||||||
|
/* With heavy Rx traffic, RXNE might be set and data pending.
|
||||||
|
* Returning 'true' in such case would cause RXNE left unhandled
|
||||||
|
* and causing interrupt storm. Sending end might be also be slow
|
||||||
|
* to react on nRTS, and returning 'true' here would prevent
|
||||||
|
* processing that data.
|
||||||
|
*
|
||||||
|
* Therefore, return 'false' so input data is still being processed
|
||||||
|
* until sending end reacts on nRTS signal and stops sending more.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return upper;
|
return upper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2645,6 +2674,31 @@ static int up_pm_prepare(struct pm_callback_s *cb, int domain,
|
|||||||
|
|
||||||
#ifdef USE_SERIALDRIVER
|
#ifdef USE_SERIALDRIVER
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: stm32_serial_get_uart
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Get serial driver structure for STM32 USART
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
FAR uart_dev_t *stm32_serial_get_uart(int uart_num)
|
||||||
|
{
|
||||||
|
int uart_idx = uart_num - 1;
|
||||||
|
|
||||||
|
if (uart_idx < 0 || uart_idx >= STM32_NUSART || !uart_devs[uart_idx])
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!uart_devs[uart_idx]->initialized)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &uart_devs[uart_idx]->dev;
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: up_earlyserialinit
|
* Name: up_earlyserialinit
|
||||||
*
|
*
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
#include <nuttx/config.h>
|
#include <nuttx/config.h>
|
||||||
|
#include <nuttx/serial/serial.h>
|
||||||
|
|
||||||
#include "chip.h"
|
#include "chip.h"
|
||||||
|
|
||||||
@ -412,6 +413,16 @@ extern "C"
|
|||||||
* Public Functions
|
* Public Functions
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
|
||||||
|
/************************************************************************************
|
||||||
|
* Name: stm32_serial_get_uart
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Get serial driver structure for STM32 USART
|
||||||
|
*
|
||||||
|
************************************************************************************/
|
||||||
|
|
||||||
|
FAR uart_dev_t *stm32_serial_get_uart(int uart_num);
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: stm32_serial_dma_poll
|
* Name: stm32_serial_dma_poll
|
||||||
*
|
*
|
||||||
|
@ -213,6 +213,12 @@ struct stm32l4_serial_s
|
|||||||
|
|
||||||
bool initialized;
|
bool initialized;
|
||||||
|
|
||||||
|
bool suspended; /* UART device has been suspended. */
|
||||||
|
|
||||||
|
/* Interrupt mask value stored before suspending for stop mode. */
|
||||||
|
|
||||||
|
uint16_t suspended_ie;
|
||||||
|
|
||||||
/* If termios are supported, then the following fields may vary at
|
/* If termios are supported, then the following fields may vary at
|
||||||
* runtime.
|
* runtime.
|
||||||
*/
|
*/
|
||||||
@ -262,6 +268,7 @@ struct stm32l4_serial_s
|
|||||||
#ifdef SERIAL_HAVE_DMA
|
#ifdef SERIAL_HAVE_DMA
|
||||||
DMA_HANDLE rxdma; /* currently-open receive DMA stream */
|
DMA_HANDLE rxdma; /* currently-open receive DMA stream */
|
||||||
bool rxenable; /* DMA-based reception en/disable */
|
bool rxenable; /* DMA-based reception en/disable */
|
||||||
|
bool rxdmasusp; /* Rx DMA suspended */
|
||||||
uint32_t rxdmanext; /* Next byte in the DMA buffer to be read */
|
uint32_t rxdmanext; /* Next byte in the DMA buffer to be read */
|
||||||
char *const rxfifo; /* Receive DMA buffer */
|
char *const rxfifo; /* Receive DMA buffer */
|
||||||
#endif
|
#endif
|
||||||
@ -305,6 +312,10 @@ static int stm32l4serial_dmasetup(FAR struct uart_dev_s *dev);
|
|||||||
static void stm32l4serial_dmashutdown(FAR struct uart_dev_s *dev);
|
static void stm32l4serial_dmashutdown(FAR struct uart_dev_s *dev);
|
||||||
static int stm32l4serial_dmareceive(FAR struct uart_dev_s *dev,
|
static int stm32l4serial_dmareceive(FAR struct uart_dev_s *dev,
|
||||||
FAR unsigned int *status);
|
FAR unsigned int *status);
|
||||||
|
static void stm32l4serial_dmareenable(struct stm32l4_serial_s *priv);
|
||||||
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||||
|
static bool stm32l4serial_dmaiflowrestart(struct stm32l4_serial_s *priv);
|
||||||
|
#endif
|
||||||
static void stm32l4serial_dmarxint(FAR struct uart_dev_s *dev, bool enable);
|
static void stm32l4serial_dmarxint(FAR struct uart_dev_s *dev, bool enable);
|
||||||
static bool stm32l4serial_dmarxavailable(struct uart_dev_s *dev);
|
static bool stm32l4serial_dmarxavailable(struct uart_dev_s *dev);
|
||||||
|
|
||||||
@ -749,6 +760,8 @@ static struct pm_callback_s g_serialcb =
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool serial_suspended_for_stop = false;
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Functions
|
* Private Functions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -1030,6 +1043,127 @@ static void stm32l4serial_setformat(FAR struct uart_dev_s *dev)
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_SUPPRESS_UART_CONFIG */
|
#endif /* CONFIG_SUPPRESS_UART_CONFIG */
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: stm32l4serial_setsuspend
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Suspend or resume serial peripheral.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void stm32l4serial_setsuspend(struct uart_dev_s *dev, bool suspend)
|
||||||
|
{
|
||||||
|
FAR struct stm32l4_serial_s *priv = (struct stm32l4_serial_s *)dev->priv;
|
||||||
|
#ifdef SERIAL_HAVE_DMA
|
||||||
|
bool dmarestored = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (priv->suspended == suspend)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->suspended = suspend;
|
||||||
|
|
||||||
|
if (suspend)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||||
|
if (priv->iflow)
|
||||||
|
{
|
||||||
|
/* Force RTS high to prevent further Rx. */
|
||||||
|
|
||||||
|
stm32l4_configgpio((priv->rts_gpio & ~GPIO_MODE_MASK)
|
||||||
|
| (GPIO_OUTPUT | GPIO_OUTPUT_SET));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Disable interrupts to prevent Tx. */
|
||||||
|
|
||||||
|
stm32l4serial_disableusartint(priv, &priv->suspended_ie);
|
||||||
|
|
||||||
|
/* Wait last Tx to complete. */
|
||||||
|
|
||||||
|
while ((stm32l4serial_getreg(priv, STM32L4_USART_ISR_OFFSET) & USART_ISR_TC) == 0);
|
||||||
|
|
||||||
|
#ifdef SERIAL_HAVE_DMA
|
||||||
|
if (priv->dev.ops == &g_uart_dma_ops && !priv->rxdmasusp)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||||
|
if (priv->iflow && priv->rxdmanext == RXDMA_BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
/* Rx DMA in non-circular iflow mode and already stopped
|
||||||
|
* at end of DMA buffer. No need to suspend. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* Suspend Rx DMA. */
|
||||||
|
|
||||||
|
stm32l4_dmastop(priv->rxdma);
|
||||||
|
priv->rxdmasusp = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef SERIAL_HAVE_DMA
|
||||||
|
if (priv->dev.ops == &g_uart_dma_ops && priv->rxdmasusp)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||||
|
if (priv->iflow)
|
||||||
|
{
|
||||||
|
(void)stm32l4serial_dmaiflowrestart(priv);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* This USART does not have HW flow-control. Unconditionally
|
||||||
|
* re-enable DMA (might loss unprocessed bytes received
|
||||||
|
* to DMA buffer before suspending). */
|
||||||
|
|
||||||
|
stm32l4serial_dmareenable(priv);
|
||||||
|
priv->rxdmasusp = false;
|
||||||
|
}
|
||||||
|
dmarestored = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Re-enable interrupts to resume Tx. */
|
||||||
|
|
||||||
|
stm32l4serial_restoreusartint(priv, priv->suspended_ie);
|
||||||
|
|
||||||
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||||
|
if (priv->iflow)
|
||||||
|
{
|
||||||
|
/* Restore peripheral RTS control. */
|
||||||
|
|
||||||
|
stm32l4_configgpio(priv->rts_gpio);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SERIAL_HAVE_DMA
|
||||||
|
if (dmarestored)
|
||||||
|
{
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
|
flags = enter_critical_section();
|
||||||
|
|
||||||
|
/* Perform initial Rx DMA buffer fetch to wake-up serial device
|
||||||
|
* activity.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (priv->rxdma != NULL)
|
||||||
|
{
|
||||||
|
stm32l4serial_dmarxcallback(priv->rxdma, 0, priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
leave_critical_section(flags);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32l4serial_setapbclock
|
* Name: stm32l4serial_setapbclock
|
||||||
*
|
*
|
||||||
@ -1945,6 +2079,22 @@ static bool stm32l4serial_rxflowcontrol(FAR struct uart_dev_s *dev,
|
|||||||
/* Assert/de-assert nRTS set it high resume/stop sending */
|
/* Assert/de-assert nRTS set it high resume/stop sending */
|
||||||
|
|
||||||
stm32l4_gpiowrite(priv->rts_gpio, upper);
|
stm32l4_gpiowrite(priv->rts_gpio, upper);
|
||||||
|
|
||||||
|
if (upper)
|
||||||
|
{
|
||||||
|
/* With heavy Rx traffic, RXNE might be set and data pending.
|
||||||
|
* Returning 'true' in such case would cause RXNE left unhandled
|
||||||
|
* and causing interrupt storm. Sending end might be also be slow
|
||||||
|
* to react on nRTS, and returning 'true' here would prevent
|
||||||
|
* processing that data.
|
||||||
|
*
|
||||||
|
* Therefore, return 'false' so input data is still being processed
|
||||||
|
* until sending end reacts on nRTS signal and stops sending more.
|
||||||
|
*/
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return upper;
|
return upper;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2040,16 +2190,31 @@ static int stm32l4serial_dmareceive(FAR struct uart_dev_s *dev,
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
#if defined(SERIAL_HAVE_DMA) && defined(CONFIG_SERIAL_IFLOWCONTROL)
|
#if defined(SERIAL_HAVE_DMA)
|
||||||
static void stm32l4serial_dmareenable(FAR struct stm32l4_serial_s *priv)
|
static void stm32l4serial_dmareenable(FAR struct stm32l4_serial_s *priv)
|
||||||
{
|
{
|
||||||
/* Configure for non-circular DMA reception into the RX fifo */
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||||
|
if (priv->iflow)
|
||||||
|
{
|
||||||
|
/* Configure for non-circular DMA reception into the RX FIFO */
|
||||||
|
|
||||||
stm32l4_dmasetup(priv->rxdma,
|
stm32l4_dmasetup(priv->rxdma,
|
||||||
priv->usartbase + STM32L4_USART_RDR_OFFSET,
|
priv->usartbase + STM32L4_USART_RDR_OFFSET,
|
||||||
(uint32_t)priv->rxfifo,
|
(uint32_t)priv->rxfifo,
|
||||||
RXDMA_BUFFER_SIZE,
|
RXDMA_BUFFER_SIZE,
|
||||||
SERIAL_DMA_IFLOW_CONTROL_WORD);
|
SERIAL_DMA_IFLOW_CONTROL_WORD);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* Configure for circular DMA reception into the RX FIFO */
|
||||||
|
|
||||||
|
stm32l4_dmasetup(priv->rxdma,
|
||||||
|
priv->usartbase + STM32L4_USART_RDR_OFFSET,
|
||||||
|
(uint32_t)priv->rxfifo,
|
||||||
|
RXDMA_BUFFER_SIZE,
|
||||||
|
SERIAL_DMA_CONTROL_WORD);
|
||||||
|
}
|
||||||
|
|
||||||
/* Reset our DMA shadow pointer to match the address just
|
/* Reset our DMA shadow pointer to match the address just
|
||||||
* programmed above.
|
* programmed above.
|
||||||
@ -2057,16 +2222,79 @@ static void stm32l4serial_dmareenable(FAR struct stm32l4_serial_s *priv)
|
|||||||
|
|
||||||
priv->rxdmanext = 0;
|
priv->rxdmanext = 0;
|
||||||
|
|
||||||
/* Start the DMA channel, and arrange for callbacks at the full point in
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||||
* the FIFO. After buffer gets full, hardware flow-control kicks in and
|
if (priv->iflow)
|
||||||
* DMA transfer is stopped.
|
{
|
||||||
*/
|
/* Start the DMA channel, and arrange for callbacks at the full point
|
||||||
|
* in the FIFO. After buffer gets full, hardware flow-control kicks
|
||||||
|
* in and DMA transfer is stopped.
|
||||||
|
*/
|
||||||
|
|
||||||
stm32l4_dmastart(priv->rxdma, stm32l4serial_dmarxcallback, (FAR void *)priv,
|
stm32l4_dmastart(priv->rxdma, stm32l4serial_dmarxcallback, (void *)priv, false);
|
||||||
false);
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* Start the DMA channel, and arrange for callbacks at the half and
|
||||||
|
* full points in the FIFO. This ensures that we have half a FIFO
|
||||||
|
* worth of time to claim bytes before they are overwritten.
|
||||||
|
*/
|
||||||
|
|
||||||
|
stm32l4_dmastart(priv->rxdma, stm32l4serial_dmarxcallback, (void *)priv, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear DMA suspended flag. */
|
||||||
|
|
||||||
|
priv->rxdmasusp = false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: stm32l4serial_dmaiflowrestart
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Call to restart RX DMA for input flow-controlled USART
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#if defined(SERIAL_HAVE_DMA) && defined(CONFIG_SERIAL_IFLOWCONTROL)
|
||||||
|
static bool stm32l4serial_dmaiflowrestart(struct stm32l4_serial_s *priv)
|
||||||
|
{
|
||||||
|
if (!priv->rxenable)
|
||||||
|
{
|
||||||
|
/* Rx not enabled by upper layer. */
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv->rxdmanext != RXDMA_BUFFER_SIZE)
|
||||||
|
{
|
||||||
|
if (priv->rxdmasusp)
|
||||||
|
{
|
||||||
|
/* Rx DMA in suspended state. */
|
||||||
|
|
||||||
|
if (stm32l4serial_dmarxavailable(&priv->dev))
|
||||||
|
{
|
||||||
|
/* DMA buffer has unprocessed data, do not re-enable yet. */
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DMA is stopped or suspended and DMA buffer does not have pending data,
|
||||||
|
* re-enabling without data loss is now safe. */
|
||||||
|
|
||||||
|
stm32l4serial_dmareenable(priv);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32l4serial_dmarxint
|
* Name: stm32l4serial_dmarxint
|
||||||
*
|
*
|
||||||
@ -2091,11 +2319,11 @@ static void stm32l4serial_dmarxint(FAR struct uart_dev_s *dev, bool enable)
|
|||||||
priv->rxenable = enable;
|
priv->rxenable = enable;
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||||
if (priv->iflow && priv->rxenable && (priv->rxdmanext == RXDMA_BUFFER_SIZE))
|
if (priv->iflow)
|
||||||
{
|
{
|
||||||
/* Re-enable RX DMA. */
|
/* Re-enable RX DMA. */
|
||||||
|
|
||||||
stm32l4serial_dmareenable(priv);
|
(void)stm32l4serial_dmaiflowrestart(priv);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -2245,15 +2473,32 @@ static void stm32l4serial_dmarxcallback(DMA_HANDLE handle, uint8_t status,
|
|||||||
uart_recvchars(&priv->dev);
|
uart_recvchars(&priv->dev);
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
#ifdef CONFIG_SERIAL_IFLOWCONTROL
|
||||||
if (priv->iflow && priv->rxenable &&
|
if (priv->iflow)
|
||||||
(priv->rxdmanext == RXDMA_BUFFER_SIZE))
|
|
||||||
{
|
{
|
||||||
/* Re-enable RX DMA. */
|
/* Re-enable RX DMA. */
|
||||||
|
|
||||||
stm32l4serial_dmareenable(priv);
|
(void)stm32l4serial_dmaiflowrestart(priv);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Get the masked USART status word to check and clear error flags.
|
||||||
|
*
|
||||||
|
* When wake-up from low power mode was not fast enough, UART is resumed too
|
||||||
|
* late and sometimes exactly when character was coming over UART, resulting
|
||||||
|
* to frame error.
|
||||||
|
|
||||||
|
* If error flag is not cleared, Rx DMA will be stuck. Clearing errors
|
||||||
|
* will release Rx DMA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
priv->sr = stm32l4serial_getreg(priv, STM32L4_USART_ISR_OFFSET);
|
||||||
|
|
||||||
|
if ((priv->sr & (USART_ISR_ORE | USART_ISR_NF | USART_ISR_FE)) != 0)
|
||||||
|
{
|
||||||
|
stm32l4serial_putreg(priv, STM32L4_USART_ICR_OFFSET,
|
||||||
|
(USART_ICR_NCF | USART_ICR_ORECF | USART_ICR_FECF));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2287,29 +2532,27 @@ static void stm32l4serial_pmnotify(FAR struct pm_callback_s *cb, int domain,
|
|||||||
{
|
{
|
||||||
case(PM_NORMAL):
|
case(PM_NORMAL):
|
||||||
{
|
{
|
||||||
/* Logic for PM_NORMAL goes here */
|
stm32l4_serial_set_suspend(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case(PM_IDLE):
|
case(PM_IDLE):
|
||||||
{
|
{
|
||||||
/* Logic for PM_IDLE goes here */
|
stm32l4_serial_set_suspend(false);
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case(PM_STANDBY):
|
case(PM_STANDBY):
|
||||||
{
|
{
|
||||||
/* Logic for PM_STANDBY goes here */
|
/* TODO: logic for enabling serial in Stop 1 mode with HSI16 missing */
|
||||||
|
|
||||||
|
stm32l4_serial_set_suspend(true);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case(PM_SLEEP):
|
case(PM_SLEEP):
|
||||||
{
|
{
|
||||||
/* Logic for PM_SLEEP goes here */
|
stm32l4_serial_set_suspend(true);
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2371,6 +2614,49 @@ static int stm32l4serial_pmprepare(FAR struct pm_callback_s *cb, int domain,
|
|||||||
|
|
||||||
#ifdef USE_SERIALDRIVER
|
#ifdef USE_SERIALDRIVER
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: stm32l4_is_serial_suspended
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Check if serial peripherals have been suspended for deep-sleep/stop modes.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
bool stm32l4_is_serial_suspended(void)
|
||||||
|
{
|
||||||
|
return (serial_suspended_for_stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: stm32_serial_set_suspend
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Suspend or resume serial peripherals for/from deep-sleep/stop modes.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void stm32l4_serial_set_suspend(bool suspend)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
/* Already in desired state? */
|
||||||
|
|
||||||
|
if (suspend == serial_suspended_for_stop)
|
||||||
|
return;
|
||||||
|
|
||||||
|
serial_suspended_for_stop = suspend;
|
||||||
|
|
||||||
|
for (n = 0; n < STM32L4_NUSART+STM32L4_NUART; n++)
|
||||||
|
{
|
||||||
|
struct stm32l4_serial_s *priv = uart_devs[n];
|
||||||
|
|
||||||
|
if (!priv || !priv->initialized)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
stm32l4serial_setsuspend(&priv->dev, suspend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: stm32l4_serial_get_uart
|
* Name: stm32l4_serial_get_uart
|
||||||
*
|
*
|
||||||
|
@ -248,6 +248,26 @@ extern "C"
|
|||||||
|
|
||||||
FAR uart_dev_t *stm32l4_serial_get_uart(int uart_num);
|
FAR uart_dev_t *stm32l4_serial_get_uart(int uart_num);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: stm32l4_is_serial_suspended
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Check if serial peripherals have been suspended for deep-sleep/stop modes.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
bool stm32l4_is_serial_suspended(void);
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: stm32_serial_set_suspend
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* Suspend or resume serial peripherals for/from deep-sleep/stop modes.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void stm32l4_serial_set_suspend(bool suspend);
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: stm32l4_serial_dma_poll
|
* Name: stm32l4_serial_dma_poll
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user