Support BSD compatible breaks on stm32fl4 U[S]ART

This commit is contained in:
David Sidrane 2016-05-17 13:08:50 -10:00
parent 3ffe7c378f
commit bef5552eba
2 changed files with 90 additions and 2 deletions

View File

@ -782,6 +782,26 @@ config STM32L4_FLOWCONTROL_BROKEN
nRTS after every byte received) Enable this setting workaround
this issue by useing software based management of RTS
config STM32L4_USART_BREAKS
bool "Add TIOxSBRK to support sending Breaks"
depends on STM32_USART
default n
---help---
Add TIOCxBRK routines to send a line break per the STM32 manual, the
break will be a pulse based on the value M. This is not a BSD compatible
break.
config STM32L4_SERIALBRK_BSDCOMPAT
bool "Use GPIO To send Break"
depends on STM32_USART && STM32_USART_BREAKS
default n
---help---
Enable using GPIO on the TX pin to send a BSD compatible break:
TIOCSBRK will start the break and TIOCCBRK will end the break.
The current STM32 U[S]ARTS have no way to leave the break (TX=LOW)
on because the SW starts the break and then the HW automatically clears
the break. This makes it is difficult to sent a long break.
endmenu
menu "SPI Configuration"

View File

@ -208,6 +208,23 @@
# define PM_IDLE_DOMAIN 0 /* Revisit */
#endif
/*
* Keep track if a Break was set
*
* Note:
*
* 1) This value is set in the priv->ie but never written to the control
* register. It must not collide with USART_CR1_USED_INTS or USART_CR3_EIE
* 2) USART_CR3_EIE is also carried in the up_dev_s ie member.
*
* see up_restoreusartint where the masking is done.
*/
#ifdef CONFIG_STM32L4_SERIALBRK_BSDCOMPAT
# define USART_CR1_IE_BREAK_INPROGRESS_SHFTS 15
# define USART_CR1_IE_BREAK_INPROGRESS (1 << USART_CR1_IE_BREAK_INPROGRESS_SHFTS)
#endif
#ifdef USE_SERIALDRIVER
#ifdef HAVE_UART
@ -1720,8 +1737,52 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
break;
#endif /* CONFIG_SERIAL_TERMIOS */
#ifdef CONFIG_USART_BREAKS
#ifdef CONFIG_STM32L4_USART_BREAKS
# ifdef CONFIG_STM32L4_SERIALBRK_BSDCOMPAT
case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */
{
irqstate_t flags;
uint32_t tx_break;
flags = enter_critical_section();
/* Disable any further tx activity */
priv->ie |= USART_CR1_IE_BREAK_INPROGRESS;
up_txint(dev, false);
/* Configure TX as a GPIO output pin and Send a break signal*/
tx_break = GPIO_OUTPUT | (~(GPIO_MODE_MASK|GPIO_OUTPUT_SET) & priv->tx_gpio);
stm32_configgpio(tx_break);
leave_critical_section(flags);
}
break;
case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */
{
uint32_t cr1;
irqstate_t flags;
flags = enter_critical_section();
/* Configure TX back to U(S)ART */
stm32_configgpio(priv->tx_gpio);
priv->ie &= ~USART_CR1_IE_BREAK_INPROGRESS;
/* Enable further tx activity */
up_txint(dev, true);
leave_critical_section(flags);
}
break;
# else
case TIOCSBRK: /* No BSD compatibility: Turn break on for M bit times */
{
uint32_t cr1;
irqstate_t flags;
@ -1733,7 +1794,7 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
}
break;
case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */
case TIOCCBRK: /* No BSD compatibility: May turn off break too soon */
{
uint32_t cr1;
irqstate_t flags;
@ -1744,6 +1805,7 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
leave_critical_section(flags);
}
break;
# endif
#endif
default:
@ -2132,6 +2194,12 @@ static void up_txint(struct uart_dev_s *dev, bool enable)
ie |= USART_CR1_TCIE;
}
# endif
# ifdef CONFIG_STM32L4_SERIALBRK_BSDCOMPAT
if (priv->ie & USART_CR1_IE_BREAK_INPROGRESS)
{
return;
}
# endif
up_restoreusartint(priv, ie);