feat: automate FT1 factory test status reporting

This commit is contained in:
chenjintao
2026-09-24 11:21:40 +08:00
parent 8b499948dd
commit 06b0eaaf70
11 changed files with 461 additions and 38 deletions
@@ -9,6 +9,7 @@
#include "factory_protocol.h"
#define FT_PROTOCOL_LINE_MAX 1024
#define FT_PROTOCOL_UART_PORT QL_DEBUG_UART_PORT
typedef struct {
char session[32];
@@ -20,9 +21,17 @@ typedef struct {
u32 seq;
ft_state_t nodes[FT_NODE_COUNT];
int cdc_open;
ql_mutex_t tx_mutex;
ql_task_t status_task;
volatile int status_broadcast;
int active_node;
} ft_protocol_context_t;
static ft_protocol_context_t g_protocol;
static void ft_emit(const char *fmt, ...);
u32 ft_now_ms(void);
static void ft_status_task(void *arg);
u32 ft_now_ms(void)
{
@@ -64,10 +73,16 @@ static void ft_emit(const char *fmt, ...)
if (len < 0) return;
if (len >= (int)sizeof(line)) len = sizeof(line) - 1;
printf("%s", line);
if (g_protocol.cdc_open) {
ql_uart_write(QL_USB_CDC_PORT, (unsigned char *)line, len);
if (g_protocol.tx_mutex) ql_rtos_mutex_lock(g_protocol.tx_mutex, QL_WAIT_FOREVER);
if (FT_PROTOCOL_UART_PORT == QL_DEBUG_UART_PORT) {
/* DBG UART is the printf console on this board. Use the same
transport as the visible boot/application logs so FT1 frames are
actually received by the host terminal. */
printf("%s", line);
} else if (g_protocol.cdc_open) {
ql_uart_write(FT_PROTOCOL_UART_PORT, (unsigned char *)line, len);
}
if (g_protocol.tx_mutex) ql_rtos_mutex_unlock(g_protocol.tx_mutex);
}
static void ft_make_session(void)
@@ -94,10 +109,50 @@ static void ft_make_session(void)
void ft_protocol_init(void)
{
int uart_ret;
memset(&g_protocol, 0, sizeof(g_protocol));
g_protocol.cdc_open =
(ql_uart_open(QL_USB_CDC_PORT, QL_UART_BAUD_115200, QL_FC_NONE) == 0);
g_protocol.active_node = -1;
ql_rtos_mutex_create(&g_protocol.tx_mutex);
uart_ret = ql_uart_open(FT_PROTOCOL_UART_PORT, QL_UART_BAUD_115200, QL_FC_NONE);
g_protocol.cdc_open = (uart_ret == 0 || uart_ret == QL_UART_ALREAD_OPEN);
ft_make_session();
printf("[FT1] control UART port=%d open_ret=%d ready=%d\r\n",
FT_PROTOCOL_UART_PORT, uart_ret, g_protocol.cdc_open);
}
static void ft_status_task(void *arg)
{
(void)arg;
while (g_protocol.status_broadcast) {
int i;
char payload[FT_PROTOCOL_LINE_MAX - 16];
int offset = snprintf(payload, sizeof(payload),
"{\"v\":%d,\"type\":\"status_snapshot\",\"seq\":%lu,\"session\":\"%s\",\"uptime_ms\":%lu,\"active_node\":%d,\"nodes\":{",
FT_PROTOCOL_VERSION, (unsigned long)++g_protocol.seq,
g_protocol.session, (unsigned long)ft_now_ms(),
g_protocol.active_node);
for (i = 0; i < FT_NODE_COUNT && offset > 0 && offset < (int)sizeof(payload); ++i) {
offset += snprintf(payload + offset, sizeof(payload) - offset,
"%s\"%s\":\"%s\"",
i ? "," : "", ft_node_name((ft_node_t)i),
ft_state_name(g_protocol.nodes[i]));
}
if (offset > 0 && offset < (int)sizeof(payload)) {
snprintf(payload + offset, sizeof(payload) - offset, "}}");
ft_emit("%s", payload);
}
ql_rtos_task_sleep_ms(500);
}
}
void ft_protocol_start_status_broadcast(void)
{
if (g_protocol.status_broadcast) return;
g_protocol.status_broadcast = 1;
/* The snapshot formatter keeps a near-1 KiB JSON buffer on the task
stack; leave headroom for libc formatting and UART calls. */
ql_rtos_task_create(&g_protocol.status_task, 8192, 15,
"ft_status", ft_status_task, NULL);
}
static void ft_copy(char *dst, unsigned int dst_size, const char *src)
@@ -141,6 +196,7 @@ void ft_protocol_session_start(void)
void ft_protocol_node_start(ft_node_t node)
{
if (node >= 0 && node < FT_NODE_COUNT) g_protocol.active_node = node;
ft_emit("{\"v\":%d,\"type\":\"node_start\",\"seq\":%lu,"
"\"session\":\"%s\",\"uptime_ms\":%lu,\"imei\":\"%s\","
"\"iccid\":\"%s\",\"nfc_uid\":\"%s\",\"node\":%d,"
@@ -169,6 +225,7 @@ void ft_protocol_node_result(ft_node_t node, int passed, ft_error_t code,
const char *result = passed ? "PASS" : "FAIL";
if (node >= 0 && node < FT_NODE_COUNT) {
g_protocol.nodes[node] = passed ? FT_STATE_PASS : FT_STATE_FAIL;
g_protocol.active_node = -1;
}
if (!data_json || !data_json[0]) data_json = "{}";