#include "uart_component.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" #include #include // T07: UART TX 全局互斥锁 // 保护所有 uart_write_bytes 调用,防止 face_tracker 任务与 application 任务并发 // 写入造成帧交织(RESEARCH A3) static SemaphoreHandle_t s_uart_tx_mutex = nullptr; // 初始化 ESP32 → RP2040 的 UART 通信 // 波特率 115200,8 数据位,无校验,1 停止位,无流控 void uart_init_component() { uart_config_t uart_config = { .baud_rate = 115200, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, }; uart_param_config(UART_PORT_NUM, &uart_config); // GPIO17=TX(发送到 RP2040 的 GP5/RX),GPIO18=RX(接收 RP2040 的 GP4/TX) uart_set_pin(UART_PORT_NUM, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); uart_driver_install(UART_PORT_NUM, BUF_SIZE, 0, 0, NULL, 0); // T07: 创建 TX 全局互斥锁 if (s_uart_tx_mutex == nullptr) { s_uart_tx_mutex = xSemaphoreCreateMutex(); } } // 发送状态字符串给 RP2040,末尾自动添加 \r\n // RP2040 的 main.py 通过 coms.esp_read() 按 \n 分割解析 // 支持的状态字符串:idle / listening / speaking / thinking / neutral / happy 等 // T07: 加锁,防与 uart_send_face 并发撕包 void uart_send_string(const char* str) { if (s_uart_tx_mutex != nullptr) { xSemaphoreTake(s_uart_tx_mutex, portMAX_DELAY); } uart_write_bytes(UART_PORT_NUM, str, strlen(str)); uart_write_bytes(UART_PORT_NUM, "\r\n", 2); if (s_uart_tx_mutex != nullptr) { xSemaphoreGive(s_uart_tx_mutex); } } // 发送说话开始信号(预留接口,RP2040 当前未使用) // 注意:经由 uart_send_string 间接加锁 void uart_signal_start() { uart_send_string("[SPEAK_START]\n"); } // 发送说话停止信号(预留接口,RP2040 当前未使用) // 注意:经由 uart_send_string 间接加锁 void uart_signal_stop() { uart_send_string("[SPEAK_STOP]\n"); } // T07: 发送人脸检测坐标到 RP2040 // 格式:"face:,\r\n",x/y ∈ [-112, +112](RP2040 pixel_centre=112) // 由 face_tracker 任务以 Kconfig FPS 频率调用(默认 10 FPS) // 必须是 C 链接(extern "C")——face_tracker.cc 用 weak 符号前置声明, // 链接时本 strong 实现自动覆盖 weak。 extern "C" void uart_send_face(int x_offset, int y_offset) { if (s_uart_tx_mutex == nullptr) return; // UART 未初始化,直接丢弃 char buf[24]; int n = snprintf(buf, sizeof(buf), "face:%d,%d", x_offset, y_offset); if (n <= 0 || n >= (int)sizeof(buf)) return; // 格式化失败/截断 xSemaphoreTake(s_uart_tx_mutex, portMAX_DELAY); uart_write_bytes(UART_PORT_NUM, buf, n); uart_write_bytes(UART_PORT_NUM, "\r\n", 2); xSemaphoreGive(s_uart_tx_mutex); }