diff --git a/prj.conf b/prj.conf index 0211a80..52234ed 100644 --- a/prj.conf +++ b/prj.conf @@ -3,5 +3,6 @@ CONFIG_GPIO=y CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y -CONFIG_PRINTK=y -CONFIG_UART_INTERRUPT_DRIVEN=y \ No newline at end of file +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_RING_BUFFER=y +CONFIG_PRINTK=y \ No newline at end of file diff --git a/src/main.c b/src/main.c index ae94e3b..ecdf420 100644 --- a/src/main.c +++ b/src/main.c @@ -1,37 +1,130 @@ -#include -#include #include +#include +#include #include +#include +#include -#define SLEEP_MS 2000 +#include #define LED_NODE DT_ALIAS(led0) -#if !DT_NODE_HAS_STATUS(LED_NODE, okay) -#error "led0 not enabled in devicetree" -#endif + +#define UART_DEVICE_NODE DT_CHOSEN(zephyr_shell_uart) + +#define RX_BUF_SIZE 256 +#define LINE_BUF_SIZE 128 +#define THREAD_STACK 1024 +#define THREAD_PRIO 5 + +// Ring buffer: callback writes, thread reads (could probably be a msg_queue too) +RING_BUF_DECLARE(rx_buf, RX_BUF_SIZE); + +// Semaphore to wake the thread (name, initial count, max count) +K_SEM_DEFINE(rx_sem, 0, 1); + +K_THREAD_STACK_DEFINE(rx_stack, THREAD_STACK); +static struct k_thread rx_thread_data; static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED_NODE, gpios); +static const struct device *uart = DEVICE_DT_GET(DT_NODELABEL(lpuart1)); + +void uart_print(const char buffer[]); +void uart_println(const char buffer[]); +void uart_cb(const struct device *dev, void *user_data); +static void rx_thread(void *p1, void *p2, void *p3); int main(void) { - printk("app started\n"); - - if (!gpio_is_ready_dt(&led)) + if (!device_is_ready(uart)) { - printk("LED GPIO not ready\n"); - return 0; + printk("UART not ready\n"); + return -1; } - int ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE); - if (ret < 0) + // Set up interrupt-driven RX + uart_irq_callback_set(uart, uart_cb); + uart_irq_rx_enable(uart); + + // Spawn the processing thread + k_thread_create(&rx_thread_data, rx_stack, + THREAD_STACK, + rx_thread, NULL, NULL, NULL, + THREAD_PRIO, 0, K_NO_WAIT); + + printk("UART ready — type something!\r\n"); + + return 0; +} + +// ============= Helpers ============= + +void uart_print(const char buffer[]) +{ + size_t len = strlen(buffer); + for (size_t i = 0; i < len; i++) + uart_poll_out(uart, buffer[i]); +} + +void uart_println(const char buffer[]) +{ + uart_print(buffer); + uart_poll_out(uart, '\r'); + uart_poll_out(uart, '\n'); +} + +// ============= Callbacks ============= +void uart_cb(const struct device *dev, void *user_data) +{ + uint8_t byte; + while (uart_irq_update(dev) && uart_irq_rx_ready(dev)) { - printk("LED GPIO configure failed: %d\n", ret); - return 0; + if (uart_fifo_read(dev, &byte, 1) == 1) + { + ring_buf_put(&rx_buf, &byte, 1); + } } - char incoming; - int i = 0; + // wake up thread + k_sem_give(&rx_sem); +} + +// ============= Threads ============= +static void rx_thread(void *p1, void *p2, void *p3) +{ + char line[LINE_BUF_SIZE]; + size_t pos = 0; + while (1) { + k_sem_take(&rx_sem, K_FOREVER); + + uint8_t byte; + while (ring_buf_get(&rx_buf, &byte, 1) == 1) + { + + // Echo the character back + uart_poll_out(uart, byte); + + if (byte == '\r' || byte == '\n') + { + if (pos > 0) + { + line[pos] = '\0'; + + printk("\r\n"); + printk("─────────────────────────────\r\n"); + printk("│ RX: %-24s \r\n", line); + printk("│ Len: %-3d, Time: %-10u \r\n", + pos, k_uptime_get_32()); + printk("─────────────────────────────\r\n"); + + pos = 0; + } + } + else if (pos < LINE_BUF_SIZE - 1) + { + line[pos++] = byte; + } + } } -} \ No newline at end of file +}