sync
This commit is contained in:
135
firmware/src/uart.c
Normal file
135
firmware/src/uart.c
Normal file
@@ -0,0 +1,135 @@
|
||||
// uart.c
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/drivers/uart.h>
|
||||
#include <zephyr/sys/ring_buffer.h>
|
||||
|
||||
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;
|
||||
}
|
||||
Reference in New Issue
Block a user