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 nRTS after every byte received) Enable this setting workaround
this issue by useing software based management of RTS 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 endmenu
menu "SPI Configuration" menu "SPI Configuration"

View File

@ -208,6 +208,23 @@
# define PM_IDLE_DOMAIN 0 /* Revisit */ # define PM_IDLE_DOMAIN 0 /* Revisit */
#endif #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 USE_SERIALDRIVER
#ifdef HAVE_UART #ifdef HAVE_UART
@ -1720,8 +1737,52 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
break; break;
#endif /* CONFIG_SERIAL_TERMIOS */ #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 */ 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; uint32_t cr1;
irqstate_t flags; irqstate_t flags;
@ -1733,7 +1794,7 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
} }
break; break;
case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */ case TIOCCBRK: /* No BSD compatibility: May turn off break too soon */
{ {
uint32_t cr1; uint32_t cr1;
irqstate_t flags; irqstate_t flags;
@ -1744,6 +1805,7 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg)
leave_critical_section(flags); leave_critical_section(flags);
} }
break; break;
# endif
#endif #endif
default: default:
@ -2132,6 +2194,12 @@ static void up_txint(struct uart_dev_s *dev, bool enable)
ie |= USART_CR1_TCIE; ie |= USART_CR1_TCIE;
} }
# endif # endif
# ifdef CONFIG_STM32L4_SERIALBRK_BSDCOMPAT
if (priv->ie & USART_CR1_IE_BREAK_INPROGRESS)
{
return;
}
# endif
up_restoreusartint(priv, ie); up_restoreusartint(priv, ie);