From 5f3e7678cdb2b0c625a4b9f91d1f5166601ae806 Mon Sep 17 00:00:00 2001 From: hangpersonal Date: Tue, 8 Sep 2026 17:26:25 -0700 Subject: [PATCH] 02_uart --- apps/02_uart/CMakeLists.txt | 10 +++ apps/02_uart/boards/nucleo_f767zi.overlay | 18 +++++ apps/02_uart/boards/stm32f4_disco.overlay | 9 +++ apps/02_uart/prj.conf | 5 ++ apps/02_uart/src/main.c | 94 +++++++++++++++++++++++ 5 files changed, 136 insertions(+) create mode 100644 apps/02_uart/CMakeLists.txt create mode 100644 apps/02_uart/boards/nucleo_f767zi.overlay create mode 100644 apps/02_uart/boards/stm32f4_disco.overlay create mode 100644 apps/02_uart/prj.conf create mode 100644 apps/02_uart/src/main.c diff --git a/apps/02_uart/CMakeLists.txt b/apps/02_uart/CMakeLists.txt new file mode 100644 index 0000000..a684b14 --- /dev/null +++ b/apps/02_uart/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.20.0) + +# Locate the Zephyr build system as a CMake package +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +# Project name +project(uart) + +# Add source files belong to this application +target_sources(app PRIVATE src/main.c) \ No newline at end of file diff --git a/apps/02_uart/boards/nucleo_f767zi.overlay b/apps/02_uart/boards/nucleo_f767zi.overlay new file mode 100644 index 0000000..8c9f503 --- /dev/null +++ b/apps/02_uart/boards/nucleo_f767zi.overlay @@ -0,0 +1,18 @@ +/ { + aliases { + led0 = &red_led; + led1 = &blue_led; + led2 = &green_led; + sw0 = &user_button0; + }; + + gpio_keys { + compatible = "gpio-keys"; + + user_button0: button { + label = "Button"; + gpios = <&gpioc 13 GPIO_ACTIVE_HIGH>; + zephyr,code = ; + }; + }; +}; \ No newline at end of file diff --git a/apps/02_uart/boards/stm32f4_disco.overlay b/apps/02_uart/boards/stm32f4_disco.overlay new file mode 100644 index 0000000..e5b1739 --- /dev/null +++ b/apps/02_uart/boards/stm32f4_disco.overlay @@ -0,0 +1,9 @@ +/ { + aliases { + led0 = &red_led_5; + led1 = &blue_led_6; + led2 = &green_led_4; + led3 = &orange_led_3; + sw0 = &user_button; + }; +}; \ No newline at end of file diff --git a/apps/02_uart/prj.conf b/apps/02_uart/prj.conf new file mode 100644 index 0000000..829fc22 --- /dev/null +++ b/apps/02_uart/prj.conf @@ -0,0 +1,5 @@ +CONFIG_GPIO=y +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_CONSOLE=y +CONFIG_PRINTK=y diff --git a/apps/02_uart/src/main.c b/apps/02_uart/src/main.c new file mode 100644 index 0000000..43e9017 --- /dev/null +++ b/apps/02_uart/src/main.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include + +// Use the board's chosen console UART +#define UART_NODE DT_CHOSEN(zephyr_console) +#define UART_RX_QUEUE_SIZE 16 + +#if !DT_NODE_HAS_STATUS(DT_ALIAS(led0), okay) +#error "Board does not define alias led0. Add a board overlay" +#endif + +static const struct gpio_dt_spec led_red = + GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios); + +#if !DT_NODE_HAS_STATUS(UART_NODE, okay) +#error "UART console not available. Add a board overlay" +#endif + +static const struct device *const uart_dev = + DEVICE_DT_GET(UART_NODE); + +/* Do not poll the STM32F4 UART only once per application loop. Its receive + * data register can hold just one byte, so a second byte causes an overrun. + * Store received bytes from the UART interrupt until the main thread handles + * them. + */ +K_MSGQ_DEFINE(uart_rx_queue, sizeof(uint8_t), UART_RX_QUEUE_SIZE, 1); + +static void uart_rx_isr(const struct device *dev, void *user_data) { + uint8_t ch; + + ARG_UNUSED(user_data); + + if (!uart_irq_update(dev) || !uart_irq_rx_ready(dev)) { + return; + } + + while (uart_fifo_read(dev, &ch, 1) == 1) { + // Drop the newest byte if the application queue is full + (void)k_msgq_put(&uart_rx_queue, &ch, K_NO_WAIT); + } +} + +int main(void) +{ + uint32_t cnt = 0; + uint8_t ch; + int rc; + + if (!gpio_is_ready_dt(&led_red)) { + printk("LED GPIO is not ready\r\n"); + return 0; + } + + rc = gpio_pin_configure_dt(&led_red, GPIO_OUTPUT_INACTIVE); + if (rc != 0) { + printk("Failed to configure LED GPIO: %d\r\n", rc); + return 0; + } + + if (!device_is_ready(uart_dev)) { + return 0; + } + + rc = uart_irq_callback_user_data_set(uart_dev, uart_rx_isr, NULL); + if (rc != 0) { + printk("Failed to configure UART RX interrupt: %d\r\n", rc); + return 0; + } + uart_irq_rx_enable(uart_dev); + + printk("\r\n[UART]: Send O to turn LED on, F to turn it off\r\n"); + + while (1) { + while (k_msgq_get(&uart_rx_queue, &ch, K_NO_WAIT) == 0) { + if (ch == 'O' || ch == 'o') { + (void)gpio_pin_set_dt(&led_red, 1); + printk("LED on\r\n"); + } else if (ch == 'F' || ch == 'f') { + (void)gpio_pin_set_dt(&led_red, 0); + printk("LED off\r\n"); + } + } + + printk("Tick: %u\r\n", cnt++); + k_msleep(200); + } + + return 0; +}