Serial driver IOCTL_SERIAL_WAIT_FOR_TC blocks waiting for TC flag (draining UART) & IOCTL_SERIAL_TX_DRAINED question

Showing results for 
Search instead for 
Did you mean: 

Serial driver IOCTL_SERIAL_WAIT_FOR_TC blocks waiting for TC flag (draining UART) & IOCTL_SERIAL_TX_DRAINED question

Contributor I

I am running MQX 3.8 on a Kinetis K20 device where I have serial driver issues. I'm using the interrupt-driven itty0: device. So I have a couple of related questions:

  1. In the MQX serial driver in serl_pol_kuart.c, the _kuart_polled_ioctl function will block indefinitely while waiting for the TC transmit complete flag to become set in the IO_IOCTL_SERIAL_WAIT_FOR_TC sub-command. The code gets stuck in a while loop indefinitely (which triggers a WDOG timeout) while it sits there waiting for the TC bit in the S1 register to become set indicating that the there is no more outgoing data in the FIFO waiting to drain.


/* wait for transmission end signal */
while( ! sci_ptr->S1 & UART_S1_TC_MASK )
{ };                                       <-- stuck here - never exits while

Is there any reason that the Kinetis UART could get stuck while attempting to drain the contents of the UART FIFO, and as a result will fail to set the TC bit in the S1 status register?  I don't expect this to block.

2. I'm looking for more background on whether there ever was a single MQX ioctl sub-command IO_IOCTL_SERIAL_TX_DRAINED which flushes both the serial driver circular queue ring buffers AND also ensures that the Kinetis UART is drained. In the MQX IO User Guide documentation there was an IO control sub-command titled IO_IOCTL_SERIAL_TX_DRAINED which stated that it "Returns TRUE if there are no transmit characters in the FIFOs or in the software rings".  Effectively, what I expect is a single MQX API which has the functionality where it implements the combination or equivalent of both fflush (pSerialPort) and  ioctl(pSerialPort, IO_IOCTL_SERIAL_WAIT_FOR_TC, NULL).

The fflush formatted I/O call will do a IO_IOCTL_FLUSH_OUTPUT that waits for the ring buffer to empty using while(!_CHARQ_EMPTY(int_io_dev_ptr->OUT_QUEUE)).  The IOCTL_SERIAL_WAIT_FOR_TC will wait for the UART to drain (as in the code in item 1 above).

In the history of the MQX IO User Guide, this IOCTL command was present from Rev 10 to Rev 22 of the MQX IO Users Guide, but was no longer included in MQX IO User Guide Rev 24.

MQX Version          IO User Guide Rev                  IO_IOCTL_SERIAL_TX_DRAINED included?


3.8                          Rev 10                                     Y

4.0                          Rev 16                                      Y

4.0.2                       Rev 18                                      Y

4.1                          Rev 22                                      Y

4.2                          Rev 24                                      N

I cannot see any implementation of the IO_IOCTL_SERIAL_TX_DRAINED in any serl_pol_kuart.c, serl_int.c, or serl_int_kuart.c low-level drivers for any version of MQX from 3.8 onwards.  Was this IOCTL command ever implemented?  There was no mention of removing this IOCTL from the documentation in the MQXCHLGUG Change log for MQX from V3.0.0 to 4.2.0 (dated 06/2015).

I look forward to feedback on both the issue with the UART FIFO draining (TC flag in S1 never gets set), as well as the question about the history of IO_IOCTL_SERIAL_TX_DRAINED in the IO User Guide and why this was never implemented.



0 Kudos
1 Reply

Contributor I

Even though I am using the interrupt driven serial driver, perhaps it may not be clear from my original message what this has to do with polled serial driver code in serl_polled_kuart.c. 

Based on my understanding of the serial driver code, the interrupt-driven Kinetis serial uart driver code in serl_int.c and serl_int_kuart.c relies upon (i.e. is dependent on) the polled version of the Kinetis serial uart driver in serl_polled_kuart.c for UART device initialization as well as for handling any IOCTL requests which were not explicitly handled by the IOCTL handler in the interrupt-driver serl_int.c handler in the _io_serial_int_ioctl call.  Since there is no handler for IO_IOCTL_SERIAL_WAIT_FOR_TC in _io_serial_int_ioctl, I believe it is falling through to see if by default the polled version of the device can handle the requested ioctl command opcode.

From serl_int.c....

_mqx_int _io_serial_int_ioctl (FILE_DEVICE_STRUCT_PTR fd_ptr, _mqx_uint cmd, void *param_ptr)



switch (cmd) {


    // Gord comment - No matching IOCTL opcode in the interrupt-driven ioctl
    // routine - forward the request to the polled driver?? 

if (int_io_dev_ptr->DEV_IOCTL != NULL)
   result = (*int_io_dev_ptr->DEV_IOCTL)(int_io_dev_ptr->DEV_INFO_PTR, cmd, param_ptr);

return (_mqx_int) result;


Can someone confirm that my understanding of this IOCTL behaviour is indeed part of the serial device driver design? This should be made more clear in the serial driver documentation of so.


0 Kudos