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

версия протокола мк 1.4.0 (убран пароль, таймаут подключения, команда help, cli_prepare_tx_data, исправлен cli_protocol_process, добавлены конверторы строки в буфер и буфера в строку, передача строки по uart, обработчик проверки соединения (надо реализовать), информация о модуле берется из памяти)
parent c500d6a7
//*********************************************************************************************************** //***********************************************************************************************************
//! @file cli_protocol.c //! @file cli_protocol.c
//! @brief Реализация протокола CLI с адресацией (board_id) //! @brief Реализация протокола CLI
//! @version v1.2.1 //! @version v1.4.0
//! @date 20.04.2026 //! @date 25.05.2026
//! //!
//! @details Протокол предназначен для тестирования и диагностики встроенного ПО устройств, //! @details Протокол предназначен для тестирования и диагностики встроенного ПО устройств,
//! подключенных к ПК через UART (COM-порт). ПК выступает мастером, устройство — подчинённым. //! подключенных к ПК через UART (COM-порт). ПК выступает мастером, устройство — подчинённым.
...@@ -106,9 +106,8 @@ static void send_response(u8 cmd, const u8* data, u8 len) ...@@ -106,9 +106,8 @@ static void send_response(u8 cmd, const u8* data, u8 len)
byte_to_hex(cmd, (char*)&buf[idx]); idx += 2; // код команды byte_to_hex(cmd, (char*)&buf[idx]); idx += 2; // код команды
for (u8 i = 0; i < len; i++) { for (u8 i = 0; i < len; i++) {
buf[idx++] = data[i]; byte_to_hex(data[i], (char*)&buf[idx]); // данные в HEX
// byte_to_hex(data[i], (char*)&buf[idx]); // данные в HEX idx += 2;
// idx += 2;
} }
buf[idx++] = CLI_MSG_TERMINATOR; // '\r' buf[idx++] = CLI_MSG_TERMINATOR; // '\r'
...@@ -169,16 +168,25 @@ static i8 handle_cmd_close(const u8* data, u8 len) ...@@ -169,16 +168,25 @@ static i8 handle_cmd_close(const u8* data, u8 len)
// Обработчик команды проверки соединения (CLI_CMD_ECHO = 0x02) // Обработчик команды проверки соединения (CLI_CMD_ECHO = 0x02)
// Возвращает эхо переданных данных. // Возвращает эхо переданных данных.
// data в hex
static i8 handle_cmd_echo(const u8* data, u8 len) static i8 handle_cmd_echo(const u8* data, u8 len)
{ {
i8 err = CLI_HND_OK_TX; i8 err = CLI_HND_OK_TX;
u8 tmp[CLI_DATA_MAX_SIZE];
memcpy(tmp, data, len);
cli_prepare_tx_data(tmp, 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);
return err; return err;
} }
...@@ -233,29 +241,13 @@ static i8 handle_cmd_get_info(const u8* data, u8 len) ...@@ -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); memcpy(&raw[raw_idx], cli_device_info.version, str_len);
raw_idx += str_len; raw_idx += str_len;
// Преобразование в HEX-строку === // Копируем бинарные данные в buf_tmp
u8 hex_idx = 0; memcpy(buf_tmp, raw, raw_idx);
for (u8 i = 0; i < raw_idx; i++) { data_size = raw_idx;
byte_to_hex(raw[i], &buf_tmp[hex_idx]);
hex_idx += 2;
}
data_size = hex_idx;
// send_response(CLI_CMD_GET_INFO, buf, idx);
return CLI_HND_OK_TX; 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) static void uart_rx_cb(void)
{ {
u16 rx = lmcal_uart_read(CLI_UART_CHANNEL); u16 rx = lmcal_uart_read(CLI_UART_CHANNEL);
...@@ -264,8 +256,6 @@ static void uart_rx_cb(void) ...@@ -264,8 +256,6 @@ static void uart_rx_cb(void)
} }
// Обработка буфера, 4 первых символа должны содержать код и длину данных // Обработка буфера, 4 первых символа должны содержать код и длину данных
static i8 parse_cmd(char* buf, u8* cmd, u8* data) static i8 parse_cmd(char* buf, u8* cmd, u8* data)
{ {
...@@ -294,16 +284,17 @@ 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) static void parse_data(char* buf, u8* size)
{ {
u8 tmp; u8 hex_size = *size; // Исходное количество HEX-символов
u8 tmp_size = *size / 2; 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; buf[j] = tmp;
byte_count++;
} }
*size = tmp_size; *size = byte_count; // Обновляем size на количество байт
} }
...@@ -431,22 +422,21 @@ void cli_protocol_process(void) ...@@ -431,22 +422,21 @@ void cli_protocol_process(void)
if (read_fifo(&tmp) == 0) if (read_fifo(&tmp) == 0)
{ {
buf_tmp[buf_index++] = tmp; buf_tmp[buf_index++] = tmp;
if (buf_index == 4) if (buf_index == 4)
{ {
if (parse_cmd(buf_tmp, &cur_cmd, &data_size) == 0) if (parse_cmd(buf_tmp, &cur_cmd, &data_size) == 0)
{ {
if ((data_size > 0) && // ИСПРАВЛЕНИЕ: убираем data_size % 2 == 0
(CLI_DATA_MAX_SIZE >= data_size) && if ((data_size > 0) && (CLI_DATA_MAX_SIZE >= data_size))
(data_size % 2 == 0))
state = WAIT_DATA; state = WAIT_DATA;
else state = WAIT_CR; else
state = WAIT_CR;
buf_index = 0; buf_index = 0;
} }
else else
{ {
// Ошибка в формате команды
state = RESET; state = RESET;
} }
} }
...@@ -490,6 +480,7 @@ void cli_protocol_process(void) ...@@ -490,6 +480,7 @@ void cli_protocol_process(void)
} }
else else
{ {
printf(" -> RESET (not CR)\n");
state = RESET; state = RESET;
} }
} }
...@@ -497,6 +488,8 @@ void cli_protocol_process(void) ...@@ -497,6 +488,8 @@ void cli_protocol_process(void)
case EXECUTE: case EXECUTE:
printf("EXECUTE: cmd=%02X, data_size=%d\n", cur_cmd, data_size);
#if 0 #if 0
if (cli_connected == 0) if (cli_connected == 0)
{ {
...@@ -538,6 +531,7 @@ void cli_protocol_process(void) ...@@ -538,6 +531,7 @@ void cli_protocol_process(void)
break; break;
default: default:
printf(" -> send_error (unknown)\n");
// хэндл вернул недопустимый ответ // хэндл вернул недопустимый ответ
send_error(cur_cmd, CLI_ERR_INTERNAL); send_error(cur_cmd, CLI_ERR_INTERNAL);
state = WAIT_START; state = WAIT_START;
...@@ -552,24 +546,83 @@ void cli_protocol_process(void) ...@@ -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++;
}
}
void cli_prepare_tx_data(u8* hex_data, u8 size) *hex_size = tmp_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]; 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‑символа (с ведущими нулями) // Преобразуем каждый байт в два hex‑символа (с ведущими нулями)
sprintf(tmp, "%02X", hex_data[i]);
buf_tmp[j] = tmp[0]; if (*str_size > tmp_size)
buf_tmp[j+1] = tmp[1]; {
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) fun_res_t cli_protocol_set_device_info(const char* name, const char* serial, const char* ver)
......
...@@ -10,7 +10,6 @@ typedef enum { ...@@ -10,7 +10,6 @@ typedef enum {
CLI_CMD_CLOSE = 0x01U, // T01 - закрыть соединение CLI_CMD_CLOSE = 0x01U, // T01 - закрыть соединение
CLI_CMD_ECHO = 0x02U, // T02 - проверка соединения (ping) CLI_CMD_ECHO = 0x02U, // T02 - проверка соединения (ping)
CLI_CMD_GET_INFO = 0x03U, // T03 - получить информацию об устройстве (имя, серийный, версия) CLI_CMD_GET_INFO = 0x03U, // T03 - получить информацию об устройстве (имя, серийный, версия)
} cli_cmd_t; } cli_cmd_t;
...@@ -61,11 +60,21 @@ fun_res_t cli_protocol_deinit(void); ...@@ -61,11 +60,21 @@ fun_res_t cli_protocol_deinit(void);
//! @brief Основной цикл обработки (вызывать в главном цикле программы) //! @brief Основной цикл обработки (вызывать в главном цикле программы)
void cli_protocol_process(void); 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 Установка информации об устройстве //! @brief Установка информации об устройстве
//! @param name Имя устройства (до 15 символа) //! @param name Имя устройства (до 15 символа)
...@@ -74,7 +83,6 @@ void cli_prepare_tx_data(u8* hex_data, u8 size); ...@@ -74,7 +83,6 @@ void cli_prepare_tx_data(u8* hex_data, u8 size);
//! @return ERR_OK при успехе //! @return ERR_OK при успехе
fun_res_t cli_protocol_set_device_info(const char* name, const char* serial, const char* ver); fun_res_t cli_protocol_set_device_info(const char* name, const char* serial, const char* ver);
//! @brief Регистрация новой команды //! @brief Регистрация новой команды
//! @param cmd Указатель на структуру с кодом и обработчиком //! @param cmd Указатель на структуру с кодом и обработчиком
//! @return ERR_OK при успехе, ERR_INVALID_ARGUMENT – неверные параметры, //! @return ERR_OK при успехе, ERR_INVALID_ARGUMENT – неверные параметры,
......
...@@ -16,16 +16,4 @@ ...@@ -16,16 +16,4 @@
#define CLI_INT_CMD_NUM (10) // Количество встроенных команд #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 #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