Hi,
I have another UART question:
I need to turn off RS485 TX drivers when TX buffer emptied out. It has to be done quickly, 10mS delay after last char left UART is already too long.
So far I found only one way of doing it:
IO_IOCTL_SERIAL_TRANSMIT_DONE check through ioctl.
So far I had very bad lack with this ioctl feature, probably because my task priority issues.
Is MQX offer any callback functions or IRQ vectors for TX Over condition? Can I use any hardware flow control signals? I saw one topic which suggested that hardware flow control is not a working feature. Any suggestions?
已解决! 转到解答。
Answers to your questions:
Is there anyway to check how many bytes sitting in RX or TX buffers?
- not via current driver API - you would have to change internal implementation.
Is interrupts UART blocks other tasks until he is done sending bytes?
- Uart interrupts runs on background. It does not block task, it interrupts all tasks, reacting on IRQ TIE(Transmit Data Register Empty). In isr it sends next byte from OS buffer. After last byte it disables transmit interrupt.
Is flush() essentially blocks everything else until UART completed the send?
- flush() internal implementation is while(){} waiting till all OS device buffer is emptied.
Other task with higher priority can run.
Is IO_IOCTL_SERIAL_TRANSMIT_DONE sets when last byte of the OS buffer been send out to UART buffer or when hardware UART buffer been emptied?
- Current implementation of both - IO_IOCTL_SERIAL_TRANSMIT_DONE and flush() function are dependent only on OS buffer sending. Neither of them check UART HW buffer.
-------------------------
I think you would need to wait for Transmission Complete FLAG of the last send byte. In current driver implementation there is no way how to do it.
We will investigate this problem and change it in next MQX version.(probably modify IO_IOCTL_SERIAL_TRANSMIT_DONE ioctl to check TC flag.
Currently I would suggest you to modify driver to check TC flag. And in your application you should call flush() - waits till last byte is send, then check Transmit Complete flag.
Hi,
there was bug in flush(fflush did not wait for buffer empty) implementation if version 3.1.0 and older. Correction is in attached file - src\mqx\sourc\io\serial\int\serl_int.c .
In attached version fflush suspends current task till all data are send.
case IO_IOCTL_FLUSH_OUTPUT: while(!_CHARQ_EMPTY(int_io_dev_ptr->OUT_QUEUE)) { /* wait untill all chars are sent from output queue*/ _taskq_suspend(int_io_dev_ptr->OUT_WAITING_TASKS); }; break;
PetrL
Hi,
I am still trying to come up with clean solution for Half duplex RS485 coms. MSF52259 chip seams to have required hardware option. It looks like tx driver control will be properly operated by RTS hardware handshake line if bit TXRTS set in UMR2n register.
I noticed MQX serial driver has an option for hardware flow control.
Could you tell me if opening serial port in IO_SERIAL_HW_FLOW_CONTROL mode sets proper bit for flow control? If not, would it be possible to alter UMR1n and UMR2n register values for custom flow control in MQX serial driver code?
What register values and where in MQX library currently past to the chip under IO_SERIAL_HW_FLOW_CONTROL flow control mode? Unfortunately not much description is available in MQX manual on this particular option.
Hi,
Functionality of driver depends on type you are using:
In the polled driver write() blocks untill all data are written to SCI HW output buffer(SCID register).
In interrupt driven serial driver, are data after calling write() data is stored in internal driver ring buffer of BSPCFG_SCI1_QUEUE_SIZE size. Driver is then sending data on the background.
I guess you are using interrupt driver.
There is no callback function from driver to signalize empty internal send-buffer. You can either use fflush()(fixed in MQX 3.2.1) or check IO_IOCTL_SERIAL_TRANSMIT_DONE ictl result.
PetrL
Thanks for the advice. For clarification, I use interrupt driven UART.
Looks like I need to know more about this UART driver implementation.
Is there anyway to check how many bytes sitting in RX or TX buffers?
Is interrupts UART blocks other tasks until he is done sending bytes?
Is flush() essentially blocks everything else until UART completed the send?
Is IO_IOCTL_SERIAL_TRANSMIT_DONE sets when last byte of the OS buffer been send out to UART buffer or when hardware UART buffer been emptied?
Sorry to be so annoying, but documentation on MQX is so scares.
Answers to your questions:
Is there anyway to check how many bytes sitting in RX or TX buffers?
- not via current driver API - you would have to change internal implementation.
Is interrupts UART blocks other tasks until he is done sending bytes?
- Uart interrupts runs on background. It does not block task, it interrupts all tasks, reacting on IRQ TIE(Transmit Data Register Empty). In isr it sends next byte from OS buffer. After last byte it disables transmit interrupt.
Is flush() essentially blocks everything else until UART completed the send?
- flush() internal implementation is while(){} waiting till all OS device buffer is emptied.
Other task with higher priority can run.
Is IO_IOCTL_SERIAL_TRANSMIT_DONE sets when last byte of the OS buffer been send out to UART buffer or when hardware UART buffer been emptied?
- Current implementation of both - IO_IOCTL_SERIAL_TRANSMIT_DONE and flush() function are dependent only on OS buffer sending. Neither of them check UART HW buffer.
-------------------------
I think you would need to wait for Transmission Complete FLAG of the last send byte. In current driver implementation there is no way how to do it.
We will investigate this problem and change it in next MQX version.(probably modify IO_IOCTL_SERIAL_TRANSMIT_DONE ioctl to check TC flag.
Currently I would suggest you to modify driver to check TC flag. And in your application you should call flush() - waits till last byte is send, then check Transmit Complete flag.
I would modify the interrupt driven driver to support 485 mode.
In _mcf51xx_sci_int_putc, enable the driver. In _mcf51xx_sci_int_tx_isr, disable the driver if _io_serial_int_nextc returns -1. You can add a new flag bit to FLAGS in IO_SERIAL_INT_DEVICE_STRUCT to specify if it is a 485 channel.