serial.c: Finish implementation of TCDRAIN. Based partly on logic from Sebastien Lorquet.

This commit is contained in:
Gregory Nutt 2017-08-01 07:39:08 -06:00
parent 2c504003f3
commit 4f0238339e

View File

@ -1001,12 +1001,94 @@ static int uart_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
break;
#if 0
case TCDRN:
{
/* Get exclusive access to the to dev->tmit. We cannot permit
* new data to be written while we are trying to flush the old
* data.
*
* A signal received while waiting for access to the xmit.head
* will abort the operation with EINTR.
*/
ret = (ssize_t)uart_takesem(&dev->xmit.sem, true);
if (ret >= 0)
{
irqstate_t flags;
/* Trigger emission to flush the contents of the tx buffer */
flags = enter_critical_section();
#ifdef CONFIG_SERIAL_REMOVABLE
/* Check if the removable device is no longer connected
* while we have interrupts off. We do not want the
* transition to occur as a race condition before we begin
* the wait.
*/
if (dev->disconnected)
{
ret = -ENOTCONN;
}
else
#endif
{
/* Continue waiting while the TX buffer is not empty */
ret = OK;
while (ret >= 0 && dev->xmit.head != dev->xmit.tail)
{
/* Inform the interrupt level logic that we are
* waiting.
*/
dev->xmitwaiting = true;
/* Wait for some characters to be sent from the
* buffer with the TX interrupt enabled. When the
* TX interrupt is enabled, uart_xmitchars()
* should execute and remove some of the data from
* the TX buffer. We mayhave to wait several
* times for the TX buffer to be entirely emptied.
*
* NOTE that interrupts will be re-enabled while we
* wait for the semaphore.
*/
#ifdef CONFIG_SERIAL_DMA
uart_dmatxavail(dev);
#endif
uart_enabletxint(dev);
ret = uart_takesem(&dev->xmitsem, true);
uart_disabletxint(dev);
}
}
leave_critical_section(flags);
/* The TX buffer is empty (or an error occurred). But
* there still may be data in the UART TX FIFO. We get no
* asynchronous indication of this event, so we have to do
* a busy wait poll.
*/
if (ret >= 0)
{
while (!uart_txempty(dev))
{
#ifndef CONFIG_DISABLE_SIGNALS
usleep(HALF_SECOND_USEC);
#else
up_mdelay(HALF_SECOND_MSEC);
#endif
}
}
uart_givesem(&dev->xmit.sem);
}
}
break;
#endif
#endif
}
}