Support BSD compatible breaks on stm32 U[S]ART

This commit is contained in:
David Sidrane 2016-05-17 12:22:25 -10:00
parent 55d8b0e277
commit b11f49e7f1
2 changed files with 89 additions and 2 deletions

View File

@ -5634,6 +5634,25 @@ config STM32_FLOWCONTROL_BROKEN
nRTS after every byte received) Enable this setting workaround
this issue by useing software based management of RTS
config STM32_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 STM32_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
config STM32_USART_SINGLEWIRE

View File

@ -255,6 +255,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_STM32_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
@ -2057,8 +2074,52 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
break;
#endif /* CONFIG_SERIAL_TERMIOS */
#ifdef CONFIG_USART_BREAKS
#ifdef CONFIG_STM32_USART_BREAKS
# ifdef CONFIG_STM32_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;
@ -2070,7 +2131,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;
@ -2081,6 +2142,7 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
leave_critical_section(flags);
}
break;
# endif
#endif
default:
@ -2469,6 +2531,12 @@ static void up_txint(struct uart_dev_s *dev, bool enable)
ie |= USART_CR1_TCIE;
}
# endif
# ifdef CONFIG_STM32_SERIALBRK_BSDCOMPAT
if (priv->ie & USART_CR1_IE_BREAK_INPROGRESS)
{
return;
}
# endif
up_restoreusartint(priv, ie);