// uart.c #include #include #include #include LOG_MODULE_REGISTER(uart, LOG_LEVEL_INF); #define RX_RING_BUF_SIZE 1024 #define TX_RING_BUF_SIZE 1024 const struct device *const uart_dev = DEVICE_DT_GET_ONE(zephyr_cdc_acm_uart); RING_BUF_ITEM_DECLARE(rx_ringbuf, RX_RING_BUF_SIZE); RING_BUF_ITEM_DECLARE(tx_ringbuf, TX_RING_BUF_SIZE); K_SEM_DEFINE(tx_done_sem, 0, 1); K_SEM_DEFINE(rx_ready_sem, 0, 1); static void uart_isr(const struct device *dev, void *user_data) { ARG_UNUSED(user_data); if (!uart_irq_update(dev)) { return; } if (uart_irq_rx_ready(dev)) { uint8_t *data_ptr; uint32_t claimed_len; int recv_len; claimed_len = ring_buf_put_claim(&rx_ringbuf, &data_ptr, RX_RING_BUF_SIZE); if (claimed_len > 0) { recv_len = uart_fifo_read(dev, data_ptr, claimed_len); ring_buf_put_finish(&rx_ringbuf, recv_len); if (recv_len > 0) { k_sem_give(&rx_ready_sem); } } else { uart_irq_rx_disable(dev); } } if (uart_irq_tx_ready(dev)) { uint8_t *data_ptr; uint32_t claim_len; int written; claim_len = ring_buf_get_claim(&tx_ringbuf, &data_ptr, ring_buf_size_get(&tx_ringbuf)); if (claim_len > 0) { written = uart_fifo_fill(dev, data_ptr, claim_len); ring_buf_get_finish(&tx_ringbuf, written); } else { uart_irq_tx_disable(dev); } k_sem_give(&tx_done_sem); } } int uart_init(void) { if (!device_is_ready(uart_dev)) { LOG_ERR("UART device not ready"); return -ENODEV; } uart_irq_callback_set(uart_dev, uart_isr); uart_irq_rx_enable(uart_dev); LOG_INF("UART device initialized"); return 0; } int uart_write(const uint8_t *data, size_t len, k_timeout_t timeout) { size_t written_total = 0; k_sem_reset(&tx_done_sem); while (written_total < len) { uint32_t written = ring_buf_put(&tx_ringbuf, &data[written_total], len - written_total); written_total += written; if (written > 0) { uart_irq_tx_enable(uart_dev); } if (written_total < len) { int ret = k_sem_take(&tx_done_sem, timeout); if (ret != 0) { return ret; } } } return written_total; } int uart_write_string(const char *str, k_timeout_t timeout) { return uart_write((const uint8_t *)str, strlen(str), timeout); } int uart_read(uint8_t *data, size_t len, k_timeout_t timeout) { uint32_t read_len = ring_buf_get(&rx_ringbuf, data, len); if (read_len == 0 && !K_TIMEOUT_EQ(timeout, K_NO_WAIT)) { k_sem_reset(&rx_ready_sem); if (ring_buf_is_empty(&rx_ringbuf)) { if (k_sem_take(&rx_ready_sem, timeout) != 0) { return -ETIMEDOUT; } } read_len = ring_buf_get(&rx_ringbuf, data, len); } if (read_len > 0) { uart_irq_rx_enable(uart_dev); } return read_len; }