Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 27 additions & 11 deletions drivers/serial/serial_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,24 +57,32 @@
void uart_xmitchars(FAR uart_dev_t *dev)
{
uint16_t nbytes = 0;
sbuf_size_t head;

#ifdef CONFIG_SMP
irqstate_t flags = enter_critical_section();
#endif

/* Send while we still have data in the TX buffer & room in the fifo */
/* Send while we still have data in the TX buffer & room in the fifo.
*
* uart_putxmitchar() advances xmit.head from thread context without
* holding the critical section, so on SMP it can move (and wrap) while
* we are in here. Sample it once per iteration: a stale value only
* makes us send less now, whereas reading it twice can turn the batch
* length negative and send from far beyond the buffer.
*/

while (dev->xmit.head != dev->xmit.tail && uart_txready(dev))
while ((head = dev->xmit.head) != dev->xmit.tail && uart_txready(dev))
{
/* Send the next byte */

if (dev->ops->sendbuf)
{
ssize_t sent;

if (dev->xmit.tail < dev->xmit.head)
if (dev->xmit.tail < head)
{
sent = dev->xmit.head - dev->xmit.tail;
sent = head - dev->xmit.tail;
}
else
{
Expand Down Expand Up @@ -164,8 +172,16 @@ void uart_recvchars(FAR uart_dev_t *dev)

while (uart_rxavailable(dev))
{
/* uart_read() advances recv.tail from thread context without holding
* the critical section, so on SMP it can move (and wrap) while we are
* in here. Sample it once per iteration and derive the free space
* from that snapshot: a stale value only makes us store less now,
* whereas reading it twice can turn the batch length negative.
*/

int nexthead = rxbuf->head + 1 < rxbuf->size ? rxbuf->head + 1 : 0;
bool is_full = (nexthead == rxbuf->tail);
Comment thread
xiaoxiang781216 marked this conversation as resolved.
sbuf_size_t tail = rxbuf->tail;
bool is_full = (nexthead == tail);
FAR char *pbuf = NULL;
char ch;

Expand All @@ -174,13 +190,13 @@ void uart_recvchars(FAR uart_dev_t *dev)

/* How many bytes are buffered */

if (rxbuf->head >= rxbuf->tail)
if (rxbuf->head >= tail)
{
nbuffered = rxbuf->head - rxbuf->tail;
nbuffered = rxbuf->head - tail;
}
else
{
nbuffered = rxbuf->size - rxbuf->tail + rxbuf->head;
nbuffered = rxbuf->size - tail + rxbuf->head;
}

/* Is the level now above the watermark level that we need to report? */
Expand Down Expand Up @@ -223,11 +239,11 @@ void uart_recvchars(FAR uart_dev_t *dev)

if (!is_full)
{
if (rxbuf->tail > rxbuf->head)
if (tail > rxbuf->head)
{
nbytes = rxbuf->tail - rxbuf->head - 1;
nbytes = tail - rxbuf->head - 1;
}
else if (rxbuf->tail)
else if (tail)
{
nbytes = rxbuf->size - rxbuf->head;
}
Expand Down
Loading