Add Serial Terminal App & WebUi Theme
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
#include "sys_uart.h"
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
static const char *TAG = "SYS_UART";
|
||||
|
||||
static uint8_t s_rx_ring[SYS_UART_BUFFER_SIZE];
|
||||
static uint32_t s_rx_head = 0; /* Total lifetime received bytes (monotonic) */
|
||||
static uint32_t s_tx_total = 0;
|
||||
static uint32_t s_baud_rate = SYS_UART_DEFAULT_BAUD;
|
||||
static SemaphoreHandle_t s_uart_mutex = NULL;
|
||||
static bool s_initialized = false;
|
||||
|
||||
static void uart_rx_task(void *pvParameters)
|
||||
{
|
||||
uint8_t tmp_buf[256];
|
||||
while (1) {
|
||||
int len = uart_read_bytes(SYS_UART_NUM, tmp_buf, sizeof(tmp_buf), pdMS_TO_TICKS(20));
|
||||
if (len > 0) {
|
||||
if (xSemaphoreTake(s_uart_mutex, pdMS_TO_TICKS(50)) == pdTRUE) {
|
||||
for (int i = 0; i < len; i++) {
|
||||
s_rx_ring[s_rx_head % SYS_UART_BUFFER_SIZE] = tmp_buf[i];
|
||||
s_rx_head++;
|
||||
}
|
||||
xSemaphoreGive(s_uart_mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t sys_uart_init(uint32_t baud_rate)
|
||||
{
|
||||
if (s_initialized) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (baud_rate == 0) {
|
||||
baud_rate = SYS_UART_DEFAULT_BAUD;
|
||||
}
|
||||
s_baud_rate = baud_rate;
|
||||
|
||||
s_uart_mutex = xSemaphoreCreateMutex();
|
||||
if (!s_uart_mutex) {
|
||||
ESP_LOGE(TAG, "Failed to create UART mutex");
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = (int)s_baud_rate,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.source_clk = UART_SCLK_DEFAULT,
|
||||
};
|
||||
|
||||
esp_err_t err = uart_driver_install(SYS_UART_NUM, 1024, 1024, 0, NULL, 0);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "uart_driver_install failed: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
err = uart_param_config(SYS_UART_NUM, &uart_config);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "uart_param_config failed: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
err = uart_set_pin(SYS_UART_NUM, SYS_UART_PIN_TX, SYS_UART_PIN_RX, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "uart_set_pin failed: %s", esp_err_to_name(err));
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Enable internal pull-up on RX to prevent floating line noise / framing errors */
|
||||
gpio_set_pull_mode(SYS_UART_PIN_RX, GPIO_PULLUP_ONLY);
|
||||
gpio_pullup_en(SYS_UART_PIN_RX);
|
||||
|
||||
memset(s_rx_ring, 0, sizeof(s_rx_ring));
|
||||
s_rx_head = 0;
|
||||
s_tx_total = 0;
|
||||
s_initialized = true;
|
||||
|
||||
xTaskCreate(uart_rx_task, "uart_rx_task", 3072, NULL, 5, NULL);
|
||||
ESP_LOGI(TAG, "Hardware UART initialized on TX:GPIO%d, RX:GPIO%d @ %lu baud",
|
||||
SYS_UART_PIN_TX, SYS_UART_PIN_RX, (unsigned long)s_baud_rate);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t sys_uart_set_baud_rate(uint32_t baud_rate)
|
||||
{
|
||||
if (!s_initialized || baud_rate == 0) return ESP_ERR_INVALID_STATE;
|
||||
esp_err_t err = uart_set_baudrate(SYS_UART_NUM, baud_rate);
|
||||
if (err == ESP_OK) {
|
||||
s_baud_rate = baud_rate;
|
||||
uart_flush_input(SYS_UART_NUM);
|
||||
ESP_LOGI(TAG, "Baud rate changed to %lu", (unsigned long)baud_rate);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
uint32_t sys_uart_get_baud_rate(void)
|
||||
{
|
||||
return s_baud_rate;
|
||||
}
|
||||
|
||||
esp_err_t sys_uart_write(const uint8_t *data, size_t len)
|
||||
{
|
||||
if (!s_initialized || !data || len == 0) return ESP_ERR_INVALID_ARG;
|
||||
int sent = uart_write_bytes(SYS_UART_NUM, data, len);
|
||||
if (sent > 0) {
|
||||
if (xSemaphoreTake(s_uart_mutex, pdMS_TO_TICKS(50)) == pdTRUE) {
|
||||
s_tx_total += (uint32_t)sent;
|
||||
xSemaphoreGive(s_uart_mutex);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t sys_uart_write_str(const char *str)
|
||||
{
|
||||
if (!str) return ESP_ERR_INVALID_ARG;
|
||||
return sys_uart_write((const uint8_t *)str, strlen(str));
|
||||
}
|
||||
|
||||
size_t sys_uart_read_delta(uint32_t from_seq, uint8_t *out_buf, size_t max_len, uint32_t *new_seq)
|
||||
{
|
||||
if (!s_initialized || !out_buf || max_len == 0) {
|
||||
if (new_seq) *new_seq = from_seq;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t bytes_copied = 0;
|
||||
if (xSemaphoreTake(s_uart_mutex, pdMS_TO_TICKS(50)) == pdTRUE) {
|
||||
uint32_t current_head = s_rx_head;
|
||||
|
||||
if (from_seq > current_head) {
|
||||
from_seq = current_head;
|
||||
}
|
||||
|
||||
uint32_t available = current_head - from_seq;
|
||||
if (available > SYS_UART_BUFFER_SIZE) {
|
||||
/* Client is too far behind, catch up to buffer start */
|
||||
from_seq = current_head - SYS_UART_BUFFER_SIZE;
|
||||
available = SYS_UART_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
if (available > max_len) {
|
||||
available = max_len;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < available; i++) {
|
||||
out_buf[i] = s_rx_ring[(from_seq + i) % SYS_UART_BUFFER_SIZE];
|
||||
}
|
||||
|
||||
bytes_copied = available;
|
||||
if (new_seq) {
|
||||
*new_seq = from_seq + available;
|
||||
}
|
||||
xSemaphoreGive(s_uart_mutex);
|
||||
} else {
|
||||
if (new_seq) *new_seq = from_seq;
|
||||
}
|
||||
|
||||
return bytes_copied;
|
||||
}
|
||||
|
||||
void sys_uart_get_stats(uint32_t *rx_count, uint32_t *tx_count)
|
||||
{
|
||||
if (xSemaphoreTake(s_uart_mutex, pdMS_TO_TICKS(50)) == pdTRUE) {
|
||||
if (rx_count) *rx_count = s_rx_head;
|
||||
if (tx_count) *tx_count = s_tx_total;
|
||||
xSemaphoreGive(s_uart_mutex);
|
||||
} else {
|
||||
if (rx_count) *rx_count = s_rx_head;
|
||||
if (tx_count) *tx_count = s_tx_total;
|
||||
}
|
||||
}
|
||||
|
||||
void sys_uart_clear_rx_buffer(void)
|
||||
{
|
||||
if (xSemaphoreTake(s_uart_mutex, pdMS_TO_TICKS(50)) == pdTRUE) {
|
||||
memset(s_rx_ring, 0, sizeof(s_rx_ring));
|
||||
xSemaphoreGive(s_uart_mutex);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user