версия протокола мк 1.4.0 (убран пароль, таймаут подключения, команда help,...

версия протокола мк 1.4.0 (убран пароль, таймаут подключения, команда help, cli_prepare_tx_data, исправлен cli_protocol_process, добавлены конверторы строки в буфер и буфера в строку, передача строки по uart, обработчик проверки соединения (надо реализовать), информация о модуле берется из памяти)
parent c500d6a7
//***********************************************************************************************************
//! @file cli_protocol.c
//! @brief Реализация протокола CLI с адресацией (board_id)
//! @version v1.2.1
//! @date 20.04.2026
//! @brief Реализация протокола CLI
//! @version v1.4.0
//! @date 25.05.2026
//!
//! @details Протокол предназначен для тестирования и диагностики встроенного ПО устройств,
//! подключенных к ПК через UART (COM-порт). ПК выступает мастером, устройство — подчинённым.
......@@ -106,9 +106,8 @@ static void send_response(u8 cmd, const u8* data, u8 len)
byte_to_hex(cmd, (char*)&buf[idx]); idx += 2; // код команды
for (u8 i = 0; i < len; i++) {
buf[idx++] = data[i];
// byte_to_hex(data[i], (char*)&buf[idx]); // данные в HEX
// idx += 2;
byte_to_hex(data[i], (char*)&buf[idx]); // данные в HEX
idx += 2;
}
buf[idx++] = CLI_MSG_TERMINATOR; // '\r'
......@@ -169,16 +168,25 @@ static i8 handle_cmd_close(const u8* data, u8 len)
// Обработчик команды проверки соединения (CLI_CMD_ECHO = 0x02)
// Возвращает эхо переданных данных.
// data в hex
static i8 handle_cmd_echo(const u8* data, u8 len)
{
i8 err = CLI_HND_OK_TX;
u8 tmp[CLI_DATA_MAX_SIZE];
memcpy(tmp, data, len);
//! Пример работы с функциями
// u8 tmp[CLI_DATA_MAX_SIZE];
// u8 tmp_size = CLI_DATA_MAX_SIZE;
// u8 tmp2[CLI_DATA_MAX_SIZE];
// u8 tmp2_size = CLI_DATA_MAX_SIZE;
// cli_conv_str_to_hex(data, len, tmp, &tmp_size);
// cli_conv_hex_to_str(tmp, tmp_size, tmp2, &tmp2_size);
// cli_send_string(tmp2, tmp2_size);
cli_prepare_tx_data(tmp, len);
return err;
}
......@@ -233,29 +241,13 @@ static i8 handle_cmd_get_info(const u8* data, u8 len)
memcpy(&raw[raw_idx], cli_device_info.version, str_len);
raw_idx += str_len;
// Преобразование в HEX-строку ===
u8 hex_idx = 0;
for (u8 i = 0; i < raw_idx; i++) {
byte_to_hex(raw[i], &buf_tmp[hex_idx]);
hex_idx += 2;
}
data_size = hex_idx;
// send_response(CLI_CMD_GET_INFO, buf, idx);
// Копируем бинарные данные в buf_tmp
memcpy(buf_tmp, raw, raw_idx);
data_size = raw_idx;
return CLI_HND_OK_TX;
}
// Колбек прерывания по приёму байта из UART.
// static void uart_rx_cb(void)
// {
// u16 rx = lmcal_uart_read(CLI_UART_CHANNEL);
// rb_add_item(&fifo_rx, (u8*)&rx);
// }
static void uart_rx_cb(void)
{
u16 rx = lmcal_uart_read(CLI_UART_CHANNEL);
......@@ -264,8 +256,6 @@ static void uart_rx_cb(void)
}
// Обработка буфера, 4 первых символа должны содержать код и длину данных
static i8 parse_cmd(char* buf, u8* cmd, u8* data)
{
......@@ -294,16 +284,17 @@ static i8 parse_cmd(char* buf, u8* cmd, u8* data)
// Возвращает: буфер с байтами и кол-во байт
static void parse_data(char* buf, u8* size)
{
u8 tmp;
u8 tmp_size = *size / 2;
u8 hex_size = *size; // Исходное количество HEX-символов
u8 byte_count = 0; // Количество полученных байт
for (u8 i=0, j=0; i < *size; i+=2, j++)
for (u8 i = 0, j = 0; i < hex_size; i += 2, j++)
{
tmp = hex_to_byte(&buf[i]);
u8 tmp = hex_to_byte(&buf[i]);
buf[j] = tmp;
byte_count++;
}
*size = tmp_size;
*size = byte_count; // Обновляем size на количество байт
}
......@@ -436,17 +427,16 @@ void cli_protocol_process(void)
{
if (parse_cmd(buf_tmp, &cur_cmd, &data_size) == 0)
{
if ((data_size > 0) &&
(CLI_DATA_MAX_SIZE >= data_size) &&
(data_size % 2 == 0))
// ИСПРАВЛЕНИЕ: убираем data_size % 2 == 0
if ((data_size > 0) && (CLI_DATA_MAX_SIZE >= data_size))
state = WAIT_DATA;
else state = WAIT_CR;
else
state = WAIT_CR;
buf_index = 0;
}
else
{
// Ошибка в формате команды
state = RESET;
}
}
......@@ -490,6 +480,7 @@ void cli_protocol_process(void)
}
else
{
printf(" -> RESET (not CR)\n");
state = RESET;
}
}
......@@ -497,6 +488,8 @@ void cli_protocol_process(void)
case EXECUTE:
printf("EXECUTE: cmd=%02X, data_size=%d\n", cur_cmd, data_size);
#if 0
if (cli_connected == 0)
{
......@@ -538,6 +531,7 @@ void cli_protocol_process(void)
break;
default:
printf(" -> send_error (unknown)\n");
// хэндл вернул недопустимый ответ
send_error(cur_cmd, CLI_ERR_INTERNAL);
state = WAIT_START;
......@@ -552,24 +546,83 @@ void cli_protocol_process(void)
}
}
void cli_conv_str_to_hex(u8* str, u8 str_size, u8* hex, u8* hex_size)
{
if ((str == NULL) || (hex == NULL) || (hex_size == NULL))
{
return;
}
if (str_size % 2 != 0)
{
// количество символов должно быть четным
return;
}
u8 tmp;
u16 tmp_size = 0;
for (u8 i=0, j=0; i < str_size; i+=2, j++)
{
tmp = hex_to_byte(&str[i]);
if (*hex_size > tmp_size)
{
hex[j] = tmp;
tmp_size++;
}
}
*hex_size = tmp_size;
}
void cli_prepare_tx_data(u8* hex_data, u8 size)
void cli_conv_hex_to_str(u8* hex, u8 hex_size, u8* str, u8* str_size)
{
if (hex_data == NULL) return;
if ((str == NULL) || (hex == NULL) || (str_size == NULL))
{
return;
}
u16 tmp_size = hex_size * 2;
if (tmp_size > *str_size)
{
// Вых. буфер слишком мал
return;
}
u8 tmp[3];
tmp_size = 0;
for (u8 i=0, j=0; i < size; i++, j+=2) {
for (u8 i=0, j=0; i < hex_size; i++, j+=2) {
// Преобразуем каждый байт в два hex‑символа (с ведущими нулями)
sprintf(tmp, "%02X", hex_data[i]);
buf_tmp[j] = tmp[0];
buf_tmp[j+1] = tmp[1];
if (*str_size > tmp_size)
{
sprintf(tmp, "%02X", hex[i]);
str[j] = tmp[0];
str[j+1] = tmp[1];
tmp_size += 2;
}
}
data_size = size * 2;
*str_size = tmp_size;
}
void cli_send_string(u8* str, u8 size)
{
if (str == NULL)
{
return;
}
if (size > CLI_DATA_MAX_SIZE)
{
size = CLI_DATA_MAX_SIZE;
}
memcpy(buf_tmp, str, size);
data_size = size;
}
fun_res_t cli_protocol_set_device_info(const char* name, const char* serial, const char* ver)
......
......@@ -10,7 +10,6 @@ typedef enum {
CLI_CMD_CLOSE = 0x01U, // T01 - закрыть соединение
CLI_CMD_ECHO = 0x02U, // T02 - проверка соединения (ping)
CLI_CMD_GET_INFO = 0x03U, // T03 - получить информацию об устройстве (имя, серийный, версия)
} cli_cmd_t;
......@@ -61,11 +60,21 @@ fun_res_t cli_protocol_deinit(void);
//! @brief Основной цикл обработки (вызывать в главном цикле программы)
void cli_protocol_process(void);
//! Преобразование строки в буфер
//! Принимает: указатель на строку, кол-во символов и размер буфера hex
//! Возвращает: буфер с байтами и кол-во байт
//! Примечание: количество символов должно быть четным!
void cli_conv_str_to_hex(u8* str, u8 str_size, u8* hex, u8* hex_size);
//! @brief Отправка строки через UART (с ожиданием завершения передачи)
//! @param str Указатель на нуль-терминированную строку
void cli_prepare_tx_data(u8* hex_data, u8 size);
//! Преобразование буфера в строку
//! Принимает: указатель на массив байт, кол-во байт и размер строки
//! Возвращает: строку и кол-во символов
//! Примечание: возвращается четное количество символов
void cli_conv_hex_to_str(u8* hex, u8 hex_size, u8* str, u8* str_size);
//! Передача строки по протоколу. Выполнять только в обработчике!
//! Примечание: строка будет передана в интерфейс после выполнения обработчика
void cli_send_string(u8* str, u8 size);
//! @brief Установка информации об устройстве
//! @param name Имя устройства (до 15 символа)
......@@ -74,7 +83,6 @@ void cli_prepare_tx_data(u8* hex_data, u8 size);
//! @return ERR_OK при успехе
fun_res_t cli_protocol_set_device_info(const char* name, const char* serial, const char* ver);
//! @brief Регистрация новой команды
//! @param cmd Указатель на структуру с кодом и обработчиком
//! @return ERR_OK при успехе, ERR_INVALID_ARGUMENT – неверные параметры,
......
......@@ -16,16 +16,4 @@
#define CLI_INT_CMD_NUM (10) // Количество встроенных команд
//************************************ Таймауты ************************************************************
#define CLI_CONNECTION_TIMEOUT_MS (20000U) // Таймаут соединения 20 секунд
//************************************ Пароль по умолчанию **************************************************
// Пароль по умолчанию "1357"
#define CLI_DEFAULT_PASSWORD_BYTES {0x31, 0x33, 0x35, 0x37}
#define CLI_DEFAULT_PASSWORD_LEN 4
#define CLI_PASSWORD_MAX_LEN 15 // Максимальная длина пароля в байтах
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment