Chromatix wrote:
Quote:
…so if the buffer is full you will have to discard it.
Preferably, before you get to that point you should send a flow-control signal back to the sender so that it doesn't cause overflow.
That's not the purpose of flow-control. Flow-control is used to pace the data link, in which the goal is to prevent an overrun of the receiver. Flow-control doesn't decide what to do with a datum once it has been received.
Once a datum has been received it is up to the local operating system to determine that datum's fate. In a typical TIA-232 implementation, for example, the local OS will read the datum from the UART and then attempt to store it into a receiver circular queue (RxQ) pending subsequent processing. If RxQ has room the newly-arrived datum is stored and the queue pointer is updated. If RxQ is full the datum is discarded and the queue pointer is not disturbed. Either way, the datum is read before its disposition is determined, a sequence that is especially necessary when working with a UART that lacks a receiver FIFO.
Below is a flow chart that illustrates how the interrupt service routine (ISR) in my POC series' firmware handles incoming data flow. In the chart, RHR means "receiver holding register," which is another name for the 8- or 16-deep FIFO that is part of the UART's hardware. RxRDY is a flag bit in the UART's status register that when set, indicates at least one datum is present in the RHR.
Attachment:
File comment: UART Receiver IRQ Processing
rxd_isr_flow_small.gif [ 81.63 KiB | Viewed 1058 times ]
In the NXP 26** and 28** UART series, the hardware can be configured so when the RHR is full the UART will automatically deassert the request-to-send (RTS) signal. When RTS is deasserted, CTS at the remote transmitter is likewise deasserted, and the transmitter is supposed to immediately stop sending. Most TIA-232 hardware will immediately stop, but there's always the odd exception.
An alternative to automatic flow-control is to "manually" control RTS and deassert it when RxQ's fill level exceeds a certain threshold, and assert RTS once RxQ's fill level has dropped below another threshold—these thresholds are referred to as "high water" and "low water" marks, respectively. A possible high water mark would be
queue_size-16 and a corresponding low water mark would be
queue_size-64. Basically, the procedure is to store the most recent datum, update the RxQ "put" index and then subtract the RxQ "get" index from the "put" index, discarding the carry. The result is then compared to the high water mark and if the same or higher RTS is deasserted, (hopefully) stopping the remote transmitter. As the foreground process gets datums from the queue it would also calculate the fill level and once it drops to the low water mark, assert RTS so the remote transmitter can resume sending. This procedure would obviously demand more processing time, but would also protect from a receiver overrun due to the transmitter being slow to respond to its CTS input.