/** * transmit next character of fifo if any, and call the event function. * This function is executed with intr locked. */ void uart_send_next_char(uint8_t num) { #ifdef CONFIG_MODULE_UART_9BITS if (uart_getconf_nbits(num) == 9) { int elt = 0; /* for 9 bits, it uses 2 places in the fifo */ if (CIRBUF_GET_LEN(&g_tx_fifo[num]) < 2) { cbi(*uart_regs[num].REGISTER_FOR_UART_IE, UDRIE); return; } cirbuf_get_buf_tail(&g_tx_fifo[num], (char *)&elt, 2); cirbuf_del_buf_tail(&g_tx_fifo[num], 2); uart_set_udr_9bits(num, elt); sbi(*uart_regs[num].REGISTER_FOR_UART_IE, UDRIE); } else /* 5, 6, 7 or 8 bits */ #endif /* CONFIG_MODULE_UART_9BITS */ { char elt = 0; if (CIRBUF_IS_EMPTY(&g_tx_fifo[num])) { cbi(*uart_regs[num].REGISTER_FOR_UART_IE, UDRIE); return; } elt = cirbuf_get_tail(&g_tx_fifo[num]); cirbuf_del_tail(&g_tx_fifo[num]); uart_set_udr(num, elt); sbi(*uart_regs[num].REGISTER_FOR_UART_IE, UDRIE); } }
cirbuf_int cirbuf_add_buf_tail(struct cirbuf * cbuf, const char * c, cirbuf_uint n) { cirbuf_uint e; if (!n || n > CIRBUF_GET_FREELEN(cbuf)) return -EINVAL; e = CIRBUF_IS_EMPTY(cbuf) ? 1 : 0; if (n < cbuf->maxlen - cbuf->end - 1 + e) { dprintf("s[%d] -> d[%d] (%d)\n", 0, cbuf->end + !e, n); memcpy(cbuf->buf + cbuf->end + !e, c, n); } else { dprintf("s[%d] -> d[%d] (%d)\n", cbuf->end + !e, 0, cbuf->maxlen - cbuf->end - 1 + e); dprintf("s[%d] -> d[%d] (%d)\n", cbuf->maxlen - cbuf->end - 1 + e, 0, n - cbuf->maxlen + cbuf->end + 1 - e); memcpy(cbuf->buf + cbuf->end + !e, c, cbuf->maxlen - cbuf->end - 1 + e); memcpy(cbuf->buf, c + cbuf->maxlen - cbuf->end - 1 + e, n - cbuf->maxlen + cbuf->end + 1 - e); } cbuf->len += n; cbuf->end += n - e; cbuf->end %= cbuf->maxlen; return n; }
cirbuf_int cirbuf_del_tail_safe(struct cirbuf * cbuf) { if (cbuf && !CIRBUF_IS_EMPTY(cbuf)) { __cirbuf_del_tail(cbuf); return 0; } return -EINVAL; }
static inline void __cirbuf_del_tail(struct cirbuf * cbuf) { cbuf->len --; if (!CIRBUF_IS_EMPTY(cbuf)) { cbuf->end += (cbuf->maxlen - 1); cbuf->end %= cbuf->maxlen; } }
/* get a char from the receive fifo */ int uart_recv_nowait(uint8_t num) { char elt = 0; uint8_t flags; IRQ_LOCK(flags); if( !CIRBUF_IS_EMPTY(&g_rx_fifo[num]) ) { elt = cirbuf_get_tail(&g_rx_fifo[num]); cirbuf_del_tail(&g_rx_fifo[num]); IRQ_UNLOCK(flags); return (int)elt; } IRQ_UNLOCK(flags); return (-1); }
cirbuf_int cirbuf_del_buf_tail(struct cirbuf * cbuf, cirbuf_uint size) { if (!size || size > CIRBUF_GET_LEN(cbuf)) return -EINVAL; cbuf->len -= size; if (CIRBUF_IS_EMPTY(cbuf)) { cbuf->end += (cbuf->maxlen - size + 1); cbuf->end %= cbuf->maxlen; } else { cbuf->end += (cbuf->maxlen - size); cbuf->end %= cbuf->maxlen; } return 0; }