Add Phase 1 UART service foundation
Add versioned NVS-backed configuration, buffered UART1 I/O, modem monitoring, counters, and serial console controls. Coordinate UART1 ownership with Phase 0 diagnostics and document loopback verification.
This commit is contained in:
+96
-23
@@ -17,6 +17,7 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/task.h"
|
||||
#include "rs232_port_owner.h"
|
||||
#include "status_led.h"
|
||||
|
||||
#define STATIC_SETTLE_TIME_MS 20
|
||||
@@ -59,6 +60,7 @@ static int s_rts_level = 1;
|
||||
static bool s_transceiver_enabled = true;
|
||||
static bool s_initialized;
|
||||
static bool s_uart_active;
|
||||
static bool s_cleanup_fault;
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
@@ -253,7 +255,7 @@ static const serial_format_t *find_serial_format(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int command_status(int argc, char **argv)
|
||||
static int execute_status(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
@@ -278,7 +280,7 @@ static int command_status(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int command_transceiver(int argc, char **argv)
|
||||
static int execute_transceiver(int argc, char **argv)
|
||||
{
|
||||
if (argc != 2 || (strcmp(argv[1], "enable") != 0 && strcmp(argv[1], "disable") != 0)) {
|
||||
printf("Usage: transceiver <enable|disable>\n");
|
||||
@@ -300,7 +302,7 @@ static int command_transceiver(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int command_drivers(int argc, char **argv)
|
||||
static int execute_drivers(int argc, char **argv)
|
||||
{
|
||||
int tx;
|
||||
int dtr;
|
||||
@@ -402,21 +404,21 @@ static esp_err_t run_static_loopback(loopback_configuration_t configuration)
|
||||
return all_passed ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
static int command_loopback_a(int argc, char **argv)
|
||||
static int execute_loopback_a(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
return run_static_loopback(LOOPBACK_CONFIGURATION_A) == ESP_OK ? 0 : 1;
|
||||
}
|
||||
|
||||
static int command_loopback_b(int argc, char **argv)
|
||||
static int execute_loopback_b(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
return run_static_loopback(LOOPBACK_CONFIGURATION_B) == ESP_OK ? 0 : 1;
|
||||
}
|
||||
|
||||
static int command_valid_test(int argc, char **argv)
|
||||
static int execute_valid_test(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
@@ -799,24 +801,32 @@ cleanup:;
|
||||
}
|
||||
}
|
||||
|
||||
bool deletion_failed = false;
|
||||
if (driver_installed) {
|
||||
esp_err_t delete_error = uart_driver_delete(RS232_UART_PORT);
|
||||
if (delete_error != ESP_OK) {
|
||||
printf("Could not delete UART1 driver: %s\n", esp_err_to_name(delete_error));
|
||||
deletion_failed = true;
|
||||
s_cleanup_fault = true;
|
||||
if (result == ESP_OK) {
|
||||
result = delete_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* GPIO17/18 return to static idle mode, then the transceiver is re-enabled. */
|
||||
s_transceiver_enabled = true;
|
||||
esp_err_t restore_error = configure_static_gpio(true);
|
||||
if (restore_error != ESP_OK) {
|
||||
printf("Could not restore static GPIO mode: %s\n", esp_err_to_name(restore_error));
|
||||
if (result == ESP_OK) {
|
||||
result = restore_error;
|
||||
if (!deletion_failed) {
|
||||
/* GPIO17/18 return to static idle mode, then the transceiver is re-enabled. */
|
||||
s_transceiver_enabled = true;
|
||||
esp_err_t restore_error = configure_static_gpio(true);
|
||||
if (restore_error != ESP_OK) {
|
||||
printf("Could not restore static GPIO mode: %s\n", esp_err_to_name(restore_error));
|
||||
s_cleanup_fault = true;
|
||||
if (result == ESP_OK) {
|
||||
result = restore_error;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s_transceiver_enabled = false;
|
||||
}
|
||||
|
||||
esp_err_t led_error = status_led_set(result == ESP_OK ? STATUS_LED_PASS : STATUS_LED_FAIL);
|
||||
@@ -829,7 +839,7 @@ cleanup:;
|
||||
return result;
|
||||
}
|
||||
|
||||
static int command_uart_loopback(int argc, char **argv)
|
||||
static int execute_uart_loopback(int argc, char **argv)
|
||||
{
|
||||
long baud_rate;
|
||||
long payload_size = 256;
|
||||
@@ -859,7 +869,7 @@ static int command_uart_loopback(int argc, char **argv)
|
||||
return run_uart_loopback((int)baud_rate, format, (size_t)payload_size) == ESP_OK ? 0 : 1;
|
||||
}
|
||||
|
||||
static int command_uart_suite(int argc, char **argv)
|
||||
static int execute_uart_suite(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
@@ -902,10 +912,13 @@ static esp_err_t finish_flow_test(
|
||||
}
|
||||
|
||||
/* Stop the traffic source before removing the receiver's backpressure. */
|
||||
bool deletion_failed = false;
|
||||
if (generator_uart_installed) {
|
||||
esp_err_t delete_error = uart_driver_delete(RS232_TEST_GENERATOR_UART_PORT);
|
||||
if (delete_error != ESP_OK) {
|
||||
printf("Could not delete UART2 generator: %s\n", esp_err_to_name(delete_error));
|
||||
deletion_failed = true;
|
||||
s_cleanup_fault = true;
|
||||
if (result == ESP_OK) {
|
||||
result = delete_error;
|
||||
}
|
||||
@@ -915,19 +928,26 @@ static esp_err_t finish_flow_test(
|
||||
esp_err_t delete_error = uart_driver_delete(RS232_UART_PORT);
|
||||
if (delete_error != ESP_OK) {
|
||||
printf("Could not delete UART1 driver: %s\n", esp_err_to_name(delete_error));
|
||||
deletion_failed = true;
|
||||
s_cleanup_fault = true;
|
||||
if (result == ESP_OK) {
|
||||
result = delete_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s_transceiver_enabled = true;
|
||||
esp_err_t restore_error = configure_static_gpio(true);
|
||||
if (restore_error != ESP_OK) {
|
||||
printf("Could not restore static GPIO mode: %s\n", esp_err_to_name(restore_error));
|
||||
if (result == ESP_OK) {
|
||||
result = restore_error;
|
||||
if (!deletion_failed) {
|
||||
s_transceiver_enabled = true;
|
||||
esp_err_t restore_error = configure_static_gpio(true);
|
||||
if (restore_error != ESP_OK) {
|
||||
printf("Could not restore static GPIO mode: %s\n", esp_err_to_name(restore_error));
|
||||
s_cleanup_fault = true;
|
||||
if (result == ESP_OK) {
|
||||
result = restore_error;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
s_transceiver_enabled = false;
|
||||
}
|
||||
|
||||
esp_err_t led_error = status_led_set(result == ESP_OK ? STATUS_LED_PASS : STATUS_LED_FAIL);
|
||||
@@ -1164,7 +1184,7 @@ cleanup:;
|
||||
return finish_flow_test(uart1_installed, false, result);
|
||||
}
|
||||
|
||||
static int command_cts_flow_test(int argc, char **argv)
|
||||
static int execute_cts_flow_test(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
@@ -1493,7 +1513,7 @@ cleanup:;
|
||||
return result;
|
||||
}
|
||||
|
||||
static int command_rts_flow_test(int argc, char **argv)
|
||||
static int execute_rts_flow_test(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
@@ -1502,6 +1522,59 @@ static int command_rts_flow_test(int argc, char **argv)
|
||||
return run_rts_flow_test() == ESP_OK ? 0 : 1;
|
||||
}
|
||||
|
||||
typedef int (*hardware_test_command_t)(int argc, char **argv);
|
||||
|
||||
static int run_owned_hardware_test(
|
||||
hardware_test_command_t command,
|
||||
int argc,
|
||||
char **argv)
|
||||
{
|
||||
esp_err_t claim_error = rs232_port_claim(RS232_PORT_OWNER_PHASE0);
|
||||
if (claim_error != ESP_OK) {
|
||||
rs232_port_owner_t owner = rs232_port_get_owner();
|
||||
printf("RS-232 port is owned by %s. Stop the serial service or reboot after a fault.\n",
|
||||
rs232_port_owner_to_string(owner));
|
||||
return 1;
|
||||
}
|
||||
|
||||
s_cleanup_fault = false;
|
||||
int result = command(argc, argv);
|
||||
|
||||
/* Never publish the port as idle after ambiguous cleanup or a surviving driver. */
|
||||
if (s_cleanup_fault ||
|
||||
uart_is_driver_installed(RS232_UART_PORT) ||
|
||||
uart_is_driver_installed(RS232_TEST_GENERATOR_UART_PORT)) {
|
||||
drive_transceiver_enabled(false);
|
||||
rs232_port_mark_fault(RS232_PORT_OWNER_PHASE0);
|
||||
printf("A diagnostic UART driver could not be removed; MAX3243 is disabled. Reboot required.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (rs232_port_release(RS232_PORT_OWNER_PHASE0) != ESP_OK) {
|
||||
rs232_port_mark_fault(RS232_PORT_OWNER_PHASE0);
|
||||
printf("Could not release diagnostic port ownership; reboot required.\n");
|
||||
return 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#define DEFINE_OWNED_COMMAND(name) \
|
||||
static int command_##name(int argc, char **argv) \
|
||||
{ \
|
||||
return run_owned_hardware_test(execute_##name, argc, argv); \
|
||||
}
|
||||
|
||||
DEFINE_OWNED_COMMAND(status)
|
||||
DEFINE_OWNED_COMMAND(transceiver)
|
||||
DEFINE_OWNED_COMMAND(drivers)
|
||||
DEFINE_OWNED_COMMAND(loopback_a)
|
||||
DEFINE_OWNED_COMMAND(loopback_b)
|
||||
DEFINE_OWNED_COMMAND(valid_test)
|
||||
DEFINE_OWNED_COMMAND(uart_loopback)
|
||||
DEFINE_OWNED_COMMAND(uart_suite)
|
||||
DEFINE_OWNED_COMMAND(cts_flow_test)
|
||||
DEFINE_OWNED_COMMAND(rts_flow_test)
|
||||
|
||||
esp_err_t rs232_hw_test_init(void)
|
||||
{
|
||||
s_transceiver_enabled = true;
|
||||
|
||||
Reference in New Issue
Block a user