Keep USB line coding diagnostic only. Fix cdc connect reconfiguring UART

1
This commit is contained in:
2026-08-31 03:40:55 +02:00
parent 6ad6c00d68
commit 2aafff25be
8 changed files with 16 additions and 153 deletions
+3 -139
View File
@@ -9,7 +9,6 @@
#include "freertos/queue.h"
#include "freertos/stream_buffer.h"
#include "freertos/task.h"
#include "serial_config.h"
#include "serial_service.h"
#include "tinyusb.h"
#include "tinyusb_cdc_acm.h"
@@ -54,8 +53,8 @@ static atomic_uint s_connection_generation;
static session_broker_client_id_t s_broker_client_id;
static bool s_writer;
/* Host-provided CDC line coding is diagnostic information only. */
static usb_cdc_transport_line_coding_t s_line_coding;
static bool s_line_coding_pending;
static usb_cdc_transport_counters_t s_counters;
static const char s_language_descriptor[] = {0x09, 0x04};
@@ -134,14 +133,11 @@ static void device_event_callback(tinyusb_event_t *event, void *arg)
notify_transport_task();
break;
case TINYUSB_EVENT_DETACHED: {
/* A new attachment must receive fresh control state and line coding. */
/* A new attachment must receive fresh control state. */
unsigned int old_state = atomic_exchange(&s_usb_state, 0U);
if (usb_state_is_open(old_state)) {
atomic_fetch_add(&s_connection_generation, 1U);
}
taskENTER_CRITICAL(&s_state_lock);
s_line_coding_pending = false;
taskEXIT_CRITICAL(&s_state_lock);
notify_transport_task();
break;
}
@@ -226,13 +222,6 @@ static void cdc_line_state_callback(int itf, cdcacm_event_t *event)
}
}
if (!event->line_state_changed_data.dtr) {
/* Do not apply a closed host session's deferred line coding after reopen. */
taskENTER_CRITICAL(&s_state_lock);
s_line_coding_pending = false;
taskEXIT_CRITICAL(&s_state_lock);
}
notify_transport_task();
}
@@ -252,137 +241,15 @@ static void cdc_line_coding_callback(int itf, cdcacm_event_t *event)
sizeof(coding));
taskENTER_CRITICAL(&s_state_lock);
if (s_line_coding_pending) {
/* Preserve the latest complete setting and account for the superseded one. */
++s_counters.callback_drops;
}
s_line_coding = (usb_cdc_transport_line_coding_t) {
.baud_rate = coding.bit_rate,
.stop_bits = coding.stop_bits,
.parity = coding.parity,
.data_bits = coding.data_bits,
};
s_line_coding_pending = true;
taskEXIT_CRITICAL(&s_state_lock);
notify_transport_task();
}
static bool take_pending_line_coding(usb_cdc_transport_line_coding_t *coding)
{
bool pending;
taskENTER_CRITICAL(&s_state_lock);
pending = s_line_coding_pending;
if (pending) {
*coding = s_line_coding;
s_line_coding_pending = false;
}
taskEXIT_CRITICAL(&s_state_lock);
return pending;
}
static bool serial_configs_equal(const serial_config_t *left,
const serial_config_t *right)
{
return left->version == right->version &&
left->baud_rate == right->baud_rate &&
left->data_bits == right->data_bits &&
left->parity == right->parity &&
left->stop_bits == right->stop_bits &&
left->flow_control == right->flow_control &&
left->dtr_behavior == right->dtr_behavior &&
left->rts_threshold == right->rts_threshold;
}
static bool map_line_coding(const usb_cdc_transport_line_coding_t *coding,
serial_config_t *config)
{
if (coding->baud_rate < SERIAL_CONFIG_MIN_BAUD_RATE ||
coding->baud_rate > SERIAL_CONFIG_MAX_BAUD_RATE) {
return false;
}
config->baud_rate = coding->baud_rate;
switch (coding->data_bits) {
case 7U:
config->data_bits = SERIAL_CONFIG_DATA_BITS_7;
break;
case 8U:
config->data_bits = SERIAL_CONFIG_DATA_BITS_8;
break;
default:
return false;
}
switch (coding->parity) {
case CDC_LINE_CODING_PARITY_NONE:
config->parity = SERIAL_CONFIG_PARITY_NONE;
break;
case CDC_LINE_CODING_PARITY_ODD:
config->parity = SERIAL_CONFIG_PARITY_ODD;
break;
case CDC_LINE_CODING_PARITY_EVEN:
config->parity = SERIAL_CONFIG_PARITY_EVEN;
break;
default:
/* Mark and space parity are intentionally not representable by UART policy. */
return false;
}
switch (coding->stop_bits) {
case CDC_LINE_CODING_STOP_BITS_1:
config->stop_bits = SERIAL_CONFIG_STOP_BITS_1;
break;
case CDC_LINE_CODING_STOP_BITS_2:
config->stop_bits = SERIAL_CONFIG_STOP_BITS_2;
break;
default:
/* This also rejects USB's 1.5-stop-bit encoding. */
return false;
}
return true;
}
static void apply_pending_line_coding(bool writer)
{
if (!writer || !serial_service_is_running()) {
return;
}
/* Restarting UART1 discards queued TX, so defer framing changes until idle. */
if (serial_service_tx_pending() > 0U) {
return;
}
usb_cdc_transport_line_coding_t coding;
if (!take_pending_line_coding(&coding)) {
return;
}
serial_config_t current;
if (serial_service_get_config(&current) != ESP_OK) {
add_counter(&s_counters.line_coding_failed, 1U);
return;
}
serial_config_t desired = current;
if (!map_line_coding(&coding, &desired)) {
add_counter(&s_counters.line_coding_rejected, 1U);
return;
}
/* Flow control, DTR policy, and RTS threshold remain from current RAM state. */
if (serial_configs_equal(&current, &desired)) {
return;
}
if (serial_service_apply_config(&desired) == ESP_OK) {
add_counter(&s_counters.line_coding_applied, 1U);
} else {
add_counter(&s_counters.line_coding_failed, 1U);
}
/* CDC line coding must not reconfigure the independently configured UART1. */
}
static bool writer_event_type(session_broker_event_type_t type)
@@ -762,8 +629,6 @@ static void transport_task(void *context)
continue;
}
apply_pending_line_coding(writer);
if (atomic_load(&s_connection_generation) != observed_generation) {
continue;
}
@@ -812,7 +677,6 @@ static void reset_uninitialized_state(void)
.parity = USB_CDC_TRANSPORT_PARITY_NONE,
.data_bits = 8U,
};
s_line_coding_pending = false;
memset(&s_counters, 0, sizeof(s_counters));
taskEXIT_CRITICAL(&s_state_lock);
}
-3
View File
@@ -44,9 +44,6 @@ typedef struct {
uint64_t writer_revocations;
uint64_t writer_events;
uint64_t service_start_failures;
uint64_t line_coding_applied;
uint64_t line_coding_rejected;
uint64_t line_coding_failed;
uint64_t callback_drops;
uint64_t control_drops;
} usb_cdc_transport_counters_t;
+2 -6
View File
@@ -76,7 +76,7 @@ static int show_status(void)
(unsigned int)snapshot.line_coding.data_bits,
parity_name(snapshot.line_coding.parity),
stop_bits_name(snapshot.line_coding.stop_bits));
printf("USB line coding changes RAM only; use 'serial save' to persist it.\n");
printf("Host line coding is reported only; UART1 uses the serial configuration.\n");
return 0;
}
@@ -110,11 +110,7 @@ static int show_counters(void)
counter->writer_denials,
counter->writer_revocations,
counter->writer_events);
printf("Line coding: applied=%" PRIu64 " rejected=%" PRIu64
" failed=%" PRIu64 " service-start-failures=%" PRIu64 "\n",
counter->line_coding_applied,
counter->line_coding_rejected,
counter->line_coding_failed,
printf("Service start failures=%" PRIu64 "\n",
counter->service_start_failures);
printf("Control/callback drops: control=%" PRIu64 " callback=%" PRIu64 "\n",
counter->control_drops,