убрана блокировка из за пароля, убрана команда Т00 без пароля,

игнорированеи проблелов в конце команд, исправлена проверка границ
памяти, обновлен приветственный вывод, нет избыточной проверке в
cli_register_command.
parent 8df5e7e1
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
//! //!
//! Расширение протокола: новые команды регистрируются через cli_register_command(). //! Расширение протокола: новые команды регистрируются через cli_register_command().
//! //!
//! Таймаут соединения: 20 секунд бездействия.
//! Максимальный размер поля данных: 64 байта. //! Максимальный размер поля данных: 64 байта.
//! //!
//! @note Для работы необходимо наличие LMCAL, ring_buffer, а также tsp_dev_info из модуля tcp.h. //! @note Для работы необходимо наличие LMCAL, ring_buffer, а также tsp_dev_info из модуля tcp.h.
...@@ -37,8 +36,8 @@ ...@@ -37,8 +36,8 @@
// Макрос для преобразования ASCII HEX-символа в 4-битное значение (0-15), 0xFF при ошибке // Макрос для преобразования ASCII HEX-символа в 4-битное значение (0-15), 0xFF при ошибке
#define HEX_CHAR_TO_NIBBLE(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \ #define HEX_CHAR_TO_NIBBLE(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \
((c) >= 'A' && (c) <= 'F') ? ((c) - 'A' + 10) : \ ((c) >= 'A' && (c) <= 'F') ? ((c) - 'A' + 10) : \
((c) >= 'a' && (c) <= 'f') ? ((c) - 'a' + 10) : 0xFF) ((c) >= 'a' && (c) <= 'f') ? ((c) - 'a' + 10) : 0xFF)
//************************************ Локальные переменные ************************************************* //************************************ Локальные переменные *************************************************
static ringbuf_t fifo_rx; // Кольцевой буфер приёма байт из UART static ringbuf_t fifo_rx; // Кольцевой буфер приёма байт из UART
...@@ -127,22 +126,16 @@ void cli_send_string(const char* str) ...@@ -127,22 +126,16 @@ void cli_send_string(const char* str)
//----------------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------------
static void uart_wait_tx_done(void) static void uart_wait_tx_done(void)
{ {
// Попытка использовать функцию LMCAL, если она доступна #if CLI_UART_CHANNEL == LMCAL_UART_CHANNEL0
#ifdef LMCAL_UART_TX_COMPLETE #define CLI_USART USART5
uint32_t timeout = 100000; // ~100 мс при типичной скорости #elif CLI_UART_CHANNEL == LMCAL_UART_CHANNEL1
while (!lmcal_uart_tx_complete(CLI_UART_CHANNEL) && --timeout); #define CLI_USART USART0
#else #else
// Резервный вариант с прямым доступом к регистрам (для GD32) #define CLI_USART USART0
#if CLI_UART_CHANNEL == LMCAL_UART_CHANNEL0
#define CLI_USART USART5
#elif CLI_UART_CHANNEL == LMCAL_UART_CHANNEL1
#define CLI_USART USART0
#else
#define CLI_USART USART0
#endif
volatile uint32_t timeout = 100000;
while (usart_flag_get(CLI_USART, USART_FLAG_TC) == RESET && --timeout);
#endif #endif
volatile u32 timeout = 100000;
while (usart_flag_get(CLI_USART, USART_FLAG_TC) == RESET && --timeout);
} }
//----------------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------------
...@@ -193,27 +186,19 @@ static void send_error(u8 cmd, u8 err) ...@@ -193,27 +186,19 @@ static void send_error(u8 cmd, u8 err)
static void handle_cmd_open(const u8* data, u8 len) static void handle_cmd_open(const u8* data, u8 len)
{ {
(void)len; (void)len;
// Проверяем, не открыто ли уже соединение
if (cli_connected) { if (cli_connected) {
send_error(CLI_CMD_OPEN, CLI_ERR_INTERNAL); send_error(CLI_CMD_OPEN, CLI_ERR_INTERNAL);
return; return;
} }
// Проверка пароля, если он задан if (len != cli_password_len || memcmp(data, cli_password, len) != 0) {
if (cli_password_len > 0) { send_error(CLI_CMD_OPEN, CLI_ERR_INTERNAL);
if (len != cli_password_len || memcmp(data, cli_password, len) != 0) { return;
// Неверный пароль - возвращаем ошибку "неизвестная команда"
send_error(CLI_CMD_OPEN, CLI_ERR_UNKNOWN_CMD);
return;
}
} }
// Пароль верен или не требуется
cli_connected = true; cli_connected = true;
if (cli_get_tick) { if (cli_get_tick) cli_last_activity = cli_get_tick();
cli_last_activity = cli_get_tick();
}
send_response(CLI_CMD_OPEN, NULL, 0); send_response(CLI_CMD_OPEN, NULL, 0);
} }
...@@ -298,21 +283,30 @@ static void handle_cmd_read_mem(const u8* data, u8 len) ...@@ -298,21 +283,30 @@ static void handle_cmd_read_mem(const u8* data, u8 len)
send_error(CLI_CMD_READ_MEM, CLI_ERR_INVALID_ARG); send_error(CLI_CMD_READ_MEM, CLI_ERR_INVALID_ARG);
return; return;
} }
u32 addr = 0; u32 addr = 0;
for (u8 i = 0; i < 4; i++) addr = (addr << 8) | data[i]; for (u8 i = 0; i < 4; i++) addr = (addr << 8) | data[i];
u8 size = data[4]; u8 size = data[4];
if (size == 0 || size > CLI_DATA_MAX_SIZE) { if (size == 0 || size > CLI_DATA_MAX_SIZE) {
send_error(CLI_CMD_READ_MEM, CLI_ERR_INVALID_ARG); send_error(CLI_CMD_READ_MEM, CLI_ERR_INVALID_ARG);
return; return;
} }
// Проверка допустимых диапазонов с учётом размера // Проверка на переполнение адреса
u32 end_addr = addr + size;
if (end_addr < addr) {
send_error(CLI_CMD_READ_MEM, CLI_ERR_INTERNAL);
return;
}
// Проверка допустимых диапазонов (GD32F450: Flash 2MB, SRAM 192KB)
bool valid = false; bool valid = false;
// Flash: 1 МБ (0x08000000 - 0x080FFFFF) – типично для GD32F450VG
if ((addr >= 0x08000000) && ((addr + size) <= 0x080FFFFF)) { if ((addr >= 0x08000000) && (end_addr <= 0x081FFFFF)) {
valid = true; valid = true; // Flash (банк 0 + банк 1 = 2 МБ)
} else if ((addr >= 0x20000000) && ((addr + size) <= 0x2001FFFF)) { } else if ((addr >= 0x20000000) && (end_addr <= 0x2002FFFF)) {
valid = true; // SRAM (128 КБ) valid = true; // SRAM (192 КБ)
} }
if (valid) { if (valid) {
...@@ -322,6 +316,7 @@ static void handle_cmd_read_mem(const u8* data, u8 len) ...@@ -322,6 +316,7 @@ static void handle_cmd_read_mem(const u8* data, u8 len)
} }
send_response(CLI_CMD_READ_MEM, buf, size); send_response(CLI_CMD_READ_MEM, buf, size);
} else { } else {
printf("READ_MEM error: addr=0x%08X, size=%d, end=0x%08X\n", addr, size, end_addr);
send_error(CLI_CMD_READ_MEM, CLI_ERR_INTERNAL); send_error(CLI_CMD_READ_MEM, CLI_ERR_INTERNAL);
} }
} }
...@@ -341,21 +336,31 @@ static void handle_cmd_write_mem(const u8* data, u8 len) ...@@ -341,21 +336,31 @@ static void handle_cmd_write_mem(const u8* data, u8 len)
send_error(CLI_CMD_WRITE_MEM, CLI_ERR_INVALID_ARG); send_error(CLI_CMD_WRITE_MEM, CLI_ERR_INVALID_ARG);
return; return;
} }
u32 addr = 0; u32 addr = 0;
for (u8 i = 0; i < 4; i++) addr = (addr << 8) | data[i]; for (u8 i = 0; i < 4; i++) addr = (addr << 8) | data[i];
u8 size = len - 4; u8 size = len - 4;
if (size > CLI_DATA_MAX_SIZE) { if (size > CLI_DATA_MAX_SIZE) {
send_error(CLI_CMD_WRITE_MEM, CLI_ERR_INVALID_ARG); send_error(CLI_CMD_WRITE_MEM, CLI_ERR_INVALID_ARG);
return; return;
} }
// Проверка: только SRAM с учётом размера // Проверка на переполнение
if ((addr >= 0x20000000) && ((addr + size) <= 0x2001FFFF)) { u32 end_addr = addr + size;
if (end_addr < addr) {
send_error(CLI_CMD_WRITE_MEM, CLI_ERR_INTERNAL);
return;
}
// Запись разрешена только в SRAM
if ((addr >= 0x20000000) && (end_addr <= 0x2002FFFF)) {
for (u8 i = 0; i < size; i++) { for (u8 i = 0; i < size; i++) {
*(volatile u8*)(addr + i) = data[4 + i]; *(volatile u8*)(addr + i) = data[4 + i];
} }
send_response(CLI_CMD_WRITE_MEM, NULL, 0); send_response(CLI_CMD_WRITE_MEM, NULL, 0);
} else { } else {
printf("WRITE_MEM error: addr=0x%08X, size=%d, end=0x%08X\n", addr, size, end_addr);
send_error(CLI_CMD_WRITE_MEM, CLI_ERR_INTERNAL); send_error(CLI_CMD_WRITE_MEM, CLI_ERR_INTERNAL);
} }
} }
...@@ -457,16 +462,16 @@ fun_res_t cli_protocol_init(void) ...@@ -457,16 +462,16 @@ fun_res_t cli_protocol_init(void)
const u8 default_pass[] = CLI_DEFAULT_PASSWORD_BYTES; const u8 default_pass[] = CLI_DEFAULT_PASSWORD_BYTES;
cli_protocol_set_password(default_pass, sizeof(default_pass)); cli_protocol_set_password(default_pass, sizeof(default_pass));
cli_send_string("\r\n------ LTA PROTOCOL ENABLED -----\r\n"); cli_send_string("\r\n********** LTA PROTOCOL ENABLED **********\r\n");
cli_send_string("- T0001 - open without password\r\n"); cli_send_string("|> T000131333537 - open with password '1357' (hex bytes 0x31,0x33,0x35,0x37)\r\n");
cli_send_string("- T000131333537 - open with password '1357' (hex bytes 0x31,0x33,0x35,0x37)\r\n"); cli_send_string("|> T0101 - close connection\r\n");
cli_send_string("- T0101 - close connection\r\n"); cli_send_string("|> T0201AABB - ping with data 0xAA,0xBB\r\n");
cli_send_string("- T0201AABB - ping with data 0xAA,0xBB\r\n"); cli_send_string("|> T0A01 - get device info\r\n");
cli_send_string("- T0A01 - get device info\r\n"); cli_send_string("|> T14010800000004 - read 4 bytes from 0x08000000\r\n");
cli_send_string("- T14010800000004 - read 4 bytes from 0x08000000\r\n"); cli_send_string("|> T14012000000004 - read 4 bytes from 0x20000000\r\n");
cli_send_string("- T150120000000AABB - write 0xAA,0xBB to SRAM 0x20000000\r\n"); cli_send_string("|> T150120000000AABB - write 0xAA,0xBB to SRAM 0x20000000\r\n");
cli_send_string("--------------------------------------------------\r\n"); cli_send_string("******************************************************\r\n");
cli_send_string("> "); cli_send_string("|> ");
return ERR_OK; return ERR_OK;
} }
...@@ -498,14 +503,20 @@ void cli_protocol_process(void) ...@@ -498,14 +503,20 @@ void cli_protocol_process(void)
cli_cmd_buffer[cli_cmd_index++] = ch; cli_cmd_buffer[cli_cmd_index++] = ch;
state = RECEIVING; state = RECEIVING;
break; break;
case RECEIVING: case RECEIVING:
if (ch == '\r' || ch == '\n') { if (ch == '\r' || ch == '\n') {
while (cli_cmd_index > 0 && (cli_cmd_buffer[cli_cmd_index - 1] == ' '
|| cli_cmd_buffer[cli_cmd_index - 1] == '\t'))
{
cli_cmd_index--;
}
if (cli_cmd_index > 0) { if (cli_cmd_index > 0) {
cli_cmd_buffer[cli_cmd_index] = CLI_MSG_TERMINATOR; cli_cmd_buffer[cli_cmd_index] = CLI_MSG_TERMINATOR;
cli_cmd_index++; cli_cmd_index++;
parse_and_execute(); parse_and_execute();
cli_send_string("> "); cli_send_string("|> ");
} }
state = EXPECT_NL; state = EXPECT_NL;
} else { } else {
...@@ -517,7 +528,6 @@ void cli_protocol_process(void) ...@@ -517,7 +528,6 @@ void cli_protocol_process(void)
} }
} }
break; break;
case EXPECT_NL: case EXPECT_NL:
if (ch == '\n') { if (ch == '\n') {
state = WAIT_CMD; state = WAIT_CMD;
...@@ -530,7 +540,7 @@ void cli_protocol_process(void) ...@@ -530,7 +540,7 @@ void cli_protocol_process(void)
} }
} }
// Таймаут соединения // Таймаут соединения (работает только если cli_get_tick != NULL)
if (cli_connected && cli_get_tick) { if (cli_connected && cli_get_tick) {
if ((cli_get_tick() - cli_last_activity) > CLI_CONNECTION_TIMEOUT_MS) { if ((cli_get_tick() - cli_last_activity) > CLI_CONNECTION_TIMEOUT_MS) {
cli_connected = false; cli_connected = false;
......
...@@ -10,9 +10,9 @@ ...@@ -10,9 +10,9 @@
//************************************ Коды команд (по протоколу 1.1) ************************************* //************************************ Коды команд (по протоколу 1.1) *************************************
typedef enum { typedef enum {
CLI_CMD_OPEN = 0x00U, // T00 - открыть соединение (опционально с паролем) CLI_CMD_OPEN = 0x00U, // T00 - открыть соединение (с паролем)
CLI_CMD_CLOSE = 0x01U, // T01 - закрыть соединение CLI_CMD_CLOSE = 0x01U, // T01 - закрыть соединение
CLI_CMD_PING = 0x02U, // T02 - проверка соединения (ping) – эхо переданных данных CLI_CMD_PING = 0x02U, // T02 - проверка соединения (ping)
CLI_CMD_GET_INFO = 0x0AU, // T0A - получить информацию об устройстве (имя, серийный, версия) CLI_CMD_GET_INFO = 0x0AU, // T0A - получить информацию об устройстве (имя, серийный, версия)
CLI_CMD_READ_MEM = 0x14U, // T14 - чтение памяти (адрес 4 байта + размер 1 байт) CLI_CMD_READ_MEM = 0x14U, // T14 - чтение памяти (адрес 4 байта + размер 1 байт)
CLI_CMD_WRITE_MEM = 0x15U, // T15 - запись памяти (адрес 4 байта + данные, только SRAM) CLI_CMD_WRITE_MEM = 0x15U, // T15 - запись памяти (адрес 4 байта + данные, только SRAM)
...@@ -102,10 +102,6 @@ void cli_protocol_set_password(const u8* pass, u8 len); ...@@ -102,10 +102,6 @@ void cli_protocol_set_password(const u8* pass, u8 len);
//! @return true – пароль верен, false – неверен //! @return true – пароль верен, false – неверен
bool cli_protocol_verify_password(const u8* pass, u8 len); bool cli_protocol_verify_password(const u8* pass, u8 len);
//---------------------------------------------------------------------
//! @brief Сброс блокировки после превышения попыток ввода пароля
void cli_protocol_reset_block(void);
//--------------------------------------------------------------------- //---------------------------------------------------------------------
//! @brief Регистрация новой команды //! @brief Регистрация новой команды
//! @param cmd Указатель на структуру с кодом и обработчиком //! @param cmd Указатель на структуру с кодом и обработчиком
...@@ -114,4 +110,4 @@ void cli_protocol_reset_block(void); ...@@ -114,4 +110,4 @@ void cli_protocol_reset_block(void);
fun_res_t cli_register_command(const cli_command_t* cmd); fun_res_t cli_register_command(const cli_command_t* cmd);
#endif #endif
\ No newline at end of file \ No newline at end of file
...@@ -16,13 +16,8 @@ ...@@ -16,13 +16,8 @@
//************************************ Пароль по умолчанию ************************************************** //************************************ Пароль по умолчанию **************************************************
// Пароль по умолчанию "1357" // Пароль по умолчанию "1357"
#define CLI_DEFAULT_PASSWORD_BYTES {0x31, 0x33, 0x35, 0x37} #define CLI_DEFAULT_PASSWORD_BYTES {0x31, 0x33, 0x35, 0x37}
#define CLI_DEFAULT_PASSWORD_LEN 4 #define CLI_DEFAULT_PASSWORD_LEN 4
#define CLI_MAX_COMMANDS 256 // Максимальное количество регистрируемых команд (0x00..0xFF)
#define CLI_MAX_COMMANDS 256 // Максимальное количество регистрируемых команд (0x00..0xFF) #define CLI_PASSWORD_MAX_LEN 15 // Максимальная длина пароля в байтах
#define CLI_PASSWORD_MAX_LEN 15 // Максимальная длина пароля в байтах
#define CLI_ACTIVITY_TIMEOUT_TICKS 20000U // ~20 сек при вызове каждые 1 мс
#endif #endif
\ No newline at end of file
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