Обновление

parent 1c1e2bb5
...@@ -65,17 +65,118 @@ ...@@ -65,17 +65,118 @@
Коды команд от 0 до 31 выделены под базовые для любого устройства команды. Коды от 32 до 255 под специфичные команды, они не будут описаны в данном документе. Коды команд от 0 до 31 выделены под базовые для любого устройства команды. Коды от 32 до 255 под специфичные команды, они не будут описаны в данном документе.
todo - сделать описание базовых команд (сделать таблицу с кодами, описанием и ответами) | ID | Команда | Формат | Ответ | Описание |
|-----|-----|-----|-----|-----|
Список базовых команд: | 0x00 | T00 | T00[PWD]\r | t00\r | Открыть соединение (пароль опционально) |
- открытие соединения; | 0x01 | T01 | T01\r | t01\r | Закрыть соединение |
- закрытие соединения; | 0x02 | T02 | T02\r | t02\r | Проверка соединения (ping) |
- Получение информации об устройстве (имя, серийный номер, версия ПО); | 0x0A | T0A | T0A\r | t0A[данные]\r | Информация об устройстве |
- Чтение памяти | 0x14 | T14 | T14[ADDR][SIZE]\r | t14[ДАННЫЕ]\r | Чтение памяти (T142000000004\r, T140800000010\r) |
- Запись памяти | 0x15 | T15 | T15[ADDR][ДАННЫЕ]\r | t15\r | Запись памяти (T1520000000AABBCCDD\r, T1520000000AA\r) |
- ... | 0xXX | - | - | - | - |
#### 3.2 Формат ответа T0A
Ответ на команду T0A содержит информацию об устройстве в следующем формате:
`
t0A[board_id][name_len][name][sn_len][sn][ver_len][ver]\r
`
| Поле | Размер | Описание |
|-----|-----|-----|
| board_id | 1 байт | Идентификатор платы (0-255) |
| name_len | 1 байт | Длина имени устройства |
| name | name_len байт | Имя устройства (ASCII) |
| sn_len | 1 байт | Длина серийного номера |
| sn | sn_len байт | Серийный номер (ASCII) |
| ver_len | 1 байт | Длина версии ПО |
| ver | ver_len байт | Версия ПО (ASCII) |
#### 3.3 Формат команд чтения/записи памяти
T14 – чтение памяти
- ADDR – 4 байта (8 HEX символов) – адрес в памяти
- SIZE – 1 байт (2 HEX символа) – количество байт для чтения (1-64)
- Допустимые адреса: Flash (0x08000000-0x08200000), SRAM (0x20000000-0x20020000)
T15 – запись памяти
- ADDR – 4 байта (8 HEX символов) – адрес в памяти
- ДАННЫЕ – 1-64 байта (2-128 HEX символов) – данные для записи
- Запись возможна только в SRAM (0x20000000-0x20020000)
#### 3.3 Рекомендуемые команды для диагностики
Для тестирования и поиска неисправностей рекомендуется добавить следующие команды:
| Код | Команда | Формат | Ответ | Назначение | Что проверяет |
|-----|-----|-----|-----|-----|-----|
| 0x03 | T03 | T03\r | t03\r | Сброс устройства | Перезагрузка МК, корректность инициализации после сброса |
| 0x04 | T04 | T04\r | t04[STATUS]\r | Статус устройства | Флаги ошибок (1 байт: бит0-аппаратная, бит1-программная, бит2-конфигурация) |
| 0x05 | T05 | T05\r | t05[RESULT]\r | Self-test | RAM (чтение/запись), Flash (CRC), периферия (регистры) |
| 0x06 | T06 | T06[PIN]\r | t06[VALUE]\r | Чтение GPIO | Состояние указанного пина (0/1) или всех пинов порта |
| 0x07 | T07 | T07[PIN][VALUE]\r | t07\r | Запись GPIO | Управление выходом (установка 0 или 1), проверка цепи |
| 0x08 | T08 | T08[ADDR]\r | t08[VALUE]\r | Чтение регистра ПЛИС | fpga_read_reg() – связь с ПЛИС, целостность регистров |
| 0x09 | T09 | T09[ADDR][VALUE]\r | t09\r | Запись регистра ПЛИС | fpga_write_reg() – конфигурация ПЛИС, проверка записи |
| 0x10 | T10 | T10\r | t10[TEMP]\r | Чтение температуры | Встроенный датчик МК, корректность АЦП |
| 0x11 | T11 | T11\r | t11[VDD][VBAT]\r | Чтение напряжения | VDD (питание), VBAT (батарея), корректность АЦП |
| 0x12 | T12 | T12[DATA]\r | t12\r | Логирование в файл | Запись данных в Flash (циклический буфер для отладки) |
| 0x13 | T13 | T13\r | t13[VERSION]\r | Версия загрузчика | Bootloader version (отдельно от прошивки МК) |
### 4. API библиотеки для ПК ### 4. API библиотеки для ПК
todo `
\ No newline at end of file class CLIProtocol:
def __init__(self, port: str, baudrate: int = 115200):
"""Инициализация"""
self.port = port
self.baudrate = baudrate
def open(self) -> bool:
"""Открыть COM-порт"""
pass
def close(self) -> None:
"""Закрыть COM-порт"""
pass
def send_cmd(self, cmd: int, data: bytes = b'') -> bytes:
"""Отправить команду и получить ответ"""
pass
def get_error_string(self, err_code: int) -> str:
"""Получить текстовое описание ошибки"""
errors = {
0x00: "Нет ошибки",
0x01: "Неизвестная команда",
0x02: "Неверный формат или значение аргумента",
0x03: "Внутренняя ошибка устройства"
}
return errors.get(err_code, "Неизвестная ошибка")
def open_connection(self, password: str = "") -> bool:
"""Открыть соединение (T00)"""
pass
def close_connection(self) -> bool:
"""Закрыть соединение (T01)"""
pass
def ping(self) -> bool:
"""Проверить соединение (T02)"""
pass
def get_device_info(self) -> dict:
"""Получить информацию об устройстве (T0A)"""
pass
def read_memory(self, addr: int, size: int) -> bytes:
"""Чтение памяти (T14)"""
pass
def write_memory(self, addr: int, data: bytes) -> bool:
"""Запись памяти (T15)"""
pass
`
\ No newline at end of file
//*********************************************************************************************************** //***********************************************************************************************************
//! @file cli_protocol.c //! @file cli_protocol.c
//! @brief Реализация протокола CLI (Protocol 1.1) //! @brief Реализация протокола CLI с адресацией (board_id)
//! @version v1.0.0 //! @version v1.1.0
//! @date 06.04.2026 //! @date 07.04.2026
//*********************************************************************************************************** //***********************************************************************************************************
//******************************************** Включаемые файлы *********************************************
#include "cli_protocol.h" #include "cli_protocol.h"
#include "ring_buffer.h" #include "ring_buffer.h"
#include "lmcal.h" #include "lmcal.h"
...@@ -16,7 +15,6 @@ ...@@ -16,7 +15,6 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
//******************************************** Локальные константы *******************************************
#define CLI_CMD_PREFIX 'T' #define CLI_CMD_PREFIX 'T'
#define CLI_RESPONSE_PREFIX 't' #define CLI_RESPONSE_PREFIX 't'
#define CLI_ERROR_PREFIX 'e' #define CLI_ERROR_PREFIX 'e'
...@@ -26,7 +24,6 @@ ...@@ -26,7 +24,6 @@
((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; static ringbuf_t fifo_rx;
static u8 fifo_rx_buf[CLI_CMD_BUFFER_SIZE]; static u8 fifo_rx_buf[CLI_CMD_BUFFER_SIZE];
...@@ -40,10 +37,6 @@ static u32 (*cli_get_tick)(void) = NULL; ...@@ -40,10 +37,6 @@ static u32 (*cli_get_tick)(void) = NULL;
static cli_device_info_t cli_device_info; static cli_device_info_t cli_device_info;
static char cli_password[16] = CLI_DEFAULT_PASSWORD; static char cli_password[16] = CLI_DEFAULT_PASSWORD;
//*********************************** Локальные (статические) функции ****************************************
//-----------------------------------------------------------------------------------------------------------
// Преобразование байта в 2 HEX символа
//----------------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------------
static inline void byte_to_hex(u8 byte, char* hex) static inline void byte_to_hex(u8 byte, char* hex)
{ {
...@@ -52,9 +45,6 @@ static inline void byte_to_hex(u8 byte, char* hex) ...@@ -52,9 +45,6 @@ static inline void byte_to_hex(u8 byte, char* hex)
hex[1] = d[byte & 0x0F]; hex[1] = d[byte & 0x0F];
} }
//-----------------------------------------------------------------------------------------------------------
// Преобразование 2 HEX символов в байт
//-----------------------------------------------------------------------------------------------------------
static u8 hex_to_byte(const char* hex) static u8 hex_to_byte(const char* hex)
{ {
u8 h = HEX_CHAR_TO_NIBBLE(hex[0]); u8 h = HEX_CHAR_TO_NIBBLE(hex[0]);
...@@ -62,76 +52,64 @@ static u8 hex_to_byte(const char* hex) ...@@ -62,76 +52,64 @@ static u8 hex_to_byte(const char* hex)
return (h == 0xFF || l == 0xFF) ? 0xFF : (h << 4) | l; return (h == 0xFF || l == 0xFF) ? 0xFF : (h << 4) | l;
} }
//-----------------------------------------------------------------------------------------------------------
// Отправка строки через UART
//-----------------------------------------------------------------------------------------------------------
void cli_send_string(const char* str) void cli_send_string(const char* str)
{ {
if (!str) return; if (!str) return;
while (*str) { while (*str) lmcal_uart_write(CLI_UART_CHANNEL, (u16)*str++);
lmcal_uart_write(CLI_UART_CHANNEL, (u16)*str);
str++;
}
} }
//-----------------------------------------------------------------------------------------------------------
// Отправка ответа на команду
//-----------------------------------------------------------------------------------------------------------
static void send_response(u8 cmd, const u8* data, u8 len) static void send_response(u8 cmd, const u8* data, u8 len)
{ {
u8 buf[CLI_CMD_BUFFER_SIZE]; u8 buf[CLI_CMD_BUFFER_SIZE];
u16 idx = 0; u16 idx = 0;
buf[idx++] = CLI_RESPONSE_PREFIX; buf[idx++] = CLI_RESPONSE_PREFIX;
byte_to_hex(cmd, (char*)&buf[idx]); byte_to_hex(cmd, (char*)&buf[idx]); idx += 2;
idx += 2; byte_to_hex(cli_device_info.board_id, (char*)&buf[idx]); idx += 2;
for (u8 i = 0; i < len; i++) { for (u8 i = 0; i < len; i++) {
byte_to_hex(data[i], (char*)&buf[idx]); byte_to_hex(data[i], (char*)&buf[idx]);
idx += 2; idx += 2;
} }
buf[idx++] = CLI_MSG_TERMINATOR; buf[idx++] = CLI_MSG_TERMINATOR;
for (u16 i = 0; i < idx; i++)
for (u16 i = 0; i < idx; i++) {
lmcal_uart_write(CLI_UART_CHANNEL, buf[i]); lmcal_uart_write(CLI_UART_CHANNEL, buf[i]);
}
} }
//-----------------------------------------------------------------------------------------------------------
// Отправка ошибки
//-----------------------------------------------------------------------------------------------------------
static void send_error(u8 cmd, u8 err) static void send_error(u8 cmd, u8 err)
{ {
u8 buf[6]; u8 buf[8];
buf[0] = CLI_ERROR_PREFIX; u16 idx = 0;
byte_to_hex(cmd, (char*)&buf[1]); buf[idx++] = CLI_ERROR_PREFIX;
byte_to_hex(err, (char*)&buf[3]); byte_to_hex(cmd, (char*)&buf[idx]); idx += 2;
buf[5] = CLI_MSG_TERMINATOR; byte_to_hex(cli_device_info.board_id, (char*)&buf[idx]); idx += 2;
byte_to_hex(err, (char*)&buf[idx]); idx += 2;
for (u16 i = 0; i < 6; i++) { buf[idx++] = CLI_MSG_TERMINATOR;
for (u16 i = 0; i < idx; i++)
lmcal_uart_write(CLI_UART_CHANNEL, buf[i]); lmcal_uart_write(CLI_UART_CHANNEL, buf[i]);
}
} }
//----------------------------------------------------------------------------------------------------------- static void handle_cmd_open(const u8* data, u8 len)
// T00 - открыть соединение
//-----------------------------------------------------------------------------------------------------------
static void handle_cmd_open(void)
{ {
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 > 0) {
if (len != strlen(cli_password)) {
send_error(CLI_CMD_OPEN, CLI_ERR_INTERNAL);
return;
}
for (u8 i = 0; i < len; i++) {
if (data[i] != cli_password[i]) {
send_error(CLI_CMD_OPEN, CLI_ERR_INTERNAL);
return;
}
}
}
cli_connected = true; cli_connected = true;
if (cli_get_tick) cli_last_activity = cli_get_tick(); if (cli_get_tick) cli_last_activity = cli_get_tick();
send_response(CLI_CMD_OPEN, NULL, 0); send_response(CLI_CMD_OPEN, NULL, 0);
} }
//-----------------------------------------------------------------------------------------------------------
// T01 - закрыть соединение
//-----------------------------------------------------------------------------------------------------------
static void handle_cmd_close(void) static void handle_cmd_close(void)
{ {
cli_connected = false; cli_connected = false;
...@@ -140,55 +118,35 @@ static void handle_cmd_close(void) ...@@ -140,55 +118,35 @@ static void handle_cmd_close(void)
memset(cli_cmd_buffer, 0, sizeof(cli_cmd_buffer)); memset(cli_cmd_buffer, 0, sizeof(cli_cmd_buffer));
} }
//-----------------------------------------------------------------------------------------------------------
// T02 - проверка соединения (ping)
//-----------------------------------------------------------------------------------------------------------
static void handle_cmd_ping(const u8* data, u8 len) static void handle_cmd_ping(const u8* data, u8 len)
{ {
if (!cli_connected) { if (!cli_connected) {
send_error(CLI_CMD_PING, CLI_ERR_NOT_CONNECTED); send_error(CLI_CMD_PING, CLI_ERR_INTERNAL);
return; return;
} }
if (len > 0) {
send_response(CLI_CMD_PING, data, len); send_response(CLI_CMD_PING, data, len);
} else {
send_response(CLI_CMD_PING, NULL, 0);
}
} }
//-----------------------------------------------------------------------------------------------------------
// T0A - информация об устройстве
//-----------------------------------------------------------------------------------------------------------
static void handle_cmd_get_info(void) static void handle_cmd_get_info(void)
{ {
if (!cli_connected) { if (!cli_connected) {
send_error(CLI_CMD_GET_INFO, CLI_ERR_NOT_CONNECTED); send_error(CLI_CMD_GET_INFO, CLI_ERR_INTERNAL);
return; return;
} }
u8 buf[CLI_DATA_MAX_SIZE]; u8 buf[CLI_DATA_MAX_SIZE];
u16 idx = 0; u16 idx = 0;
u8 len; u8 len;
// Board ID
buf[idx++] = cli_device_info.board_id; buf[idx++] = cli_device_info.board_id;
// Имя
len = strlen(cli_device_info.name); len = strlen(cli_device_info.name);
if (len > 31) len = 31; if (len > 31) len = 31;
buf[idx++] = len; buf[idx++] = len;
memcpy(&buf[idx], cli_device_info.name, len); memcpy(&buf[idx], cli_device_info.name, len);
idx += len; idx += len;
// Серийный номер
len = strlen(cli_device_info.serial); len = strlen(cli_device_info.serial);
if (len > 15) len = 15; if (len > 15) len = 15;
buf[idx++] = len; buf[idx++] = len;
memcpy(&buf[idx], cli_device_info.serial, len); memcpy(&buf[idx], cli_device_info.serial, len);
idx += len; idx += len;
// Версия ПО
char ver[16]; char ver[16];
snprintf(ver, sizeof(ver), "%lu", tsp_dev_info.mcu_ver); snprintf(ver, sizeof(ver), "%lu", tsp_dev_info.mcu_ver);
len = strlen(ver); len = strlen(ver);
...@@ -196,167 +154,104 @@ static void handle_cmd_get_info(void) ...@@ -196,167 +154,104 @@ static void handle_cmd_get_info(void)
buf[idx++] = len; buf[idx++] = len;
memcpy(&buf[idx], ver, len); memcpy(&buf[idx], ver, len);
idx += len; idx += len;
send_response(CLI_CMD_GET_INFO, buf, idx); send_response(CLI_CMD_GET_INFO, buf, idx);
} }
//-----------------------------------------------------------------------------------------------------------
// T14 - чтение памяти
//-----------------------------------------------------------------------------------------------------------
static void handle_cmd_read_mem(const u8* data, u8 len) static void handle_cmd_read_mem(const u8* data, u8 len)
{ {
if (!cli_connected) { if (!cli_connected) {
send_error(CLI_CMD_READ_MEM, CLI_ERR_NOT_CONNECTED); send_error(CLI_CMD_READ_MEM, CLI_ERR_INTERNAL);
return; return;
} }
if (len != 5) { if (len != 5) {
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++) { for (u8 i = 0; i < 4; i++) addr = (addr << 8) | data[i];
addr = (addr << 8) | data[i];
}
u8 size = data[4]; u8 size = data[4];
if (size == 0 || size > CLI_DATA_MAX_SIZE) {
if (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;
} }
if ((addr >= 0x08000000 && addr < 0x08200000) || if ((addr >= 0x08000000 && addr < 0x08200000) ||
(addr >= 0x20000000 && addr < 0x20020000)) { (addr >= 0x20000000 && addr < 0x20020000)) {
u8 buf[CLI_DATA_MAX_SIZE]; u8 buf[CLI_DATA_MAX_SIZE];
for (u8 i = 0; i < size; i++) { for (u8 i = 0; i < size; i++) buf[i] = *(volatile u8*)(addr + i);
buf[i] = *(volatile u8*)(addr + i);
}
send_response(CLI_CMD_READ_MEM, buf, size); send_response(CLI_CMD_READ_MEM, buf, size);
} else { } else {
send_error(CLI_CMD_READ_MEM, CLI_ERR_INVALID_ADDR); send_error(CLI_CMD_READ_MEM, CLI_ERR_INTERNAL);
} }
} }
//-----------------------------------------------------------------------------------------------------------
// T15 - запись памяти
//-----------------------------------------------------------------------------------------------------------
static void handle_cmd_write_mem(const u8* data, u8 len) static void handle_cmd_write_mem(const u8* data, u8 len)
{ {
if (!cli_connected) { if (!cli_connected) {
send_error(CLI_CMD_WRITE_MEM, CLI_ERR_NOT_CONNECTED); send_error(CLI_CMD_WRITE_MEM, CLI_ERR_INTERNAL);
return; return;
} }
if (len < 5) { if (len < 5) {
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++) { for (u8 i = 0; i < 4; i++) addr = (addr << 8) | data[i];
addr = (addr << 8) | data[i];
}
u8 size = len - 4; u8 size = len - 4;
if (size > CLI_DATA_MAX_SIZE) {
if ((addr >= 0x20000000 && addr < 0x20020000)) { send_error(CLI_CMD_WRITE_MEM, CLI_ERR_INVALID_ARG);
for (u8 i = 0; i < size; i++) { return;
*(volatile u8*)(addr + i) = data[4 + i];
} }
if ((addr >= 0x20000000 && addr < 0x20020000)) {
for (u8 i = 0; i < size; 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 {
send_error(CLI_CMD_WRITE_MEM, CLI_ERR_INVALID_ADDR); send_error(CLI_CMD_WRITE_MEM, CLI_ERR_INTERNAL);
} }
} }
//-----------------------------------------------------------------------------------------------------------
// Парсинг и выполнение команды
//-----------------------------------------------------------------------------------------------------------
static void parse_and_execute(void) static void parse_and_execute(void)
{ {
char* buf = cli_cmd_buffer; char* buf = cli_cmd_buffer;
u16 len = cli_cmd_index; u16 len = cli_cmd_index;
if (len < 6) { cli_cmd_index = 0; return; }
if (len < 3) { if (buf[0] != CLI_CMD_PREFIX) { cli_cmd_index = 0; return; }
cli_cmd_index = 0; if (buf[len - 1] != CLI_MSG_TERMINATOR) return;
return;
}
if (buf[0] != CLI_CMD_PREFIX) {
cli_cmd_index = 0;
return;
}
if (buf[len - 1] != CLI_MSG_TERMINATOR) {
return;
}
u8 cmd = hex_to_byte(&buf[1]); u8 cmd = hex_to_byte(&buf[1]);
if (cmd == 0xFF) { if (cmd == 0xFF) { cli_cmd_index = 0; return; }
cli_cmd_index = 0;
return; u8 board_id = hex_to_byte(&buf[3]);
} if (board_id == 0xFF) { cli_cmd_index = 0; return; } // broadcast ignored
if (board_id != cli_device_info.board_id) { cli_cmd_index = 0; return; }
u16 data_start = 5;
u16 chars = len - 1 - data_start;
u8 data[CLI_DATA_MAX_SIZE + 4]; u8 data[CLI_DATA_MAX_SIZE + 4];
u8 data_len = 0; u8 data_len = 0;
if (chars > 0) {
if (len > 4) { if (chars % 2 != 0) { send_error(cmd, CLI_ERR_INVALID_ARG); cli_cmd_index = 0; return; }
u16 chars = len - 4;
if ((chars % 2) != 0) {
send_error(cmd, CLI_ERR_INVALID_ARG);
cli_cmd_index = 0;
return;
}
data_len = chars / 2; data_len = chars / 2;
if (data_len > (CLI_DATA_MAX_SIZE + 4)) { if (data_len > CLI_DATA_MAX_SIZE + 4) { send_error(cmd, CLI_ERR_INVALID_ARG); cli_cmd_index = 0; return; }
send_error(cmd, CLI_ERR_INVALID_ARG);
cli_cmd_index = 0;
return;
}
for (u8 i = 0; i < data_len; i++) { for (u8 i = 0; i < data_len; i++) {
data[i] = hex_to_byte(&buf[3 + i * 2]); data[i] = hex_to_byte(&buf[data_start + i * 2]);
if (data[i] == 0xFF) { if (data[i] == 0xFF) { send_error(cmd, CLI_ERR_INVALID_ARG); cli_cmd_index = 0; return; }
send_error(cmd, CLI_ERR_INVALID_ARG);
cli_cmd_index = 0;
return;
}
} }
} }
if (cli_get_tick) cli_last_activity = cli_get_tick(); if (cli_get_tick) cli_last_activity = cli_get_tick();
switch (cmd) { switch (cmd) {
case CLI_CMD_OPEN: case CLI_CMD_OPEN: handle_cmd_open(data, data_len); break;
handle_cmd_open(); case CLI_CMD_CLOSE: handle_cmd_close(); break;
break; case CLI_CMD_PING: handle_cmd_ping(data, data_len); break;
case CLI_CMD_CLOSE: case CLI_CMD_GET_INFO: handle_cmd_get_info(); break;
handle_cmd_close(); case CLI_CMD_READ_MEM: handle_cmd_read_mem(data, data_len); break;
break; case CLI_CMD_WRITE_MEM: handle_cmd_write_mem(data, data_len); break;
case CLI_CMD_PING: default: send_error(cmd, CLI_ERR_UNKNOWN_CMD); break;
handle_cmd_ping(data, data_len);
break;
case CLI_CMD_GET_INFO:
handle_cmd_get_info();
break;
case CLI_CMD_READ_MEM:
handle_cmd_read_mem(data, data_len);
break;
case CLI_CMD_WRITE_MEM:
handle_cmd_write_mem(data, data_len);
break;
default:
send_error(cmd, CLI_ERR_UNKNOWN_CMD);
break;
} }
cli_cmd_index = 0; cli_cmd_index = 0;
} }
//-----------------------------------------------------------------------------------------------------------
// Колбек прерывания по приему байта
//-----------------------------------------------------------------------------------------------------------
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);
...@@ -364,19 +259,12 @@ static void uart_rx_cb(void) ...@@ -364,19 +259,12 @@ static void uart_rx_cb(void)
rb_add_item(&fifo_rx, &ch); rb_add_item(&fifo_rx, &ch);
} }
//***********************************************************************************************************
//******************************* Определения глобальных (публичных) функций ********************************
//***********************************************************************************************************
//-----------------------------------------------------------------------------------------------------------
// Инициализация протокола
//----------------------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------------------
fun_res_t cli_protocol_init(void) fun_res_t cli_protocol_init(void)
{ {
fifo_rx.item_size = sizeof(u8); fifo_rx.item_size = sizeof(u8);
rb_init(&fifo_rx, fifo_rx_buf, sizeof(fifo_rx_buf)); rb_init(&fifo_rx, fifo_rx_buf, sizeof(fifo_rx_buf));
rb_clear(&fifo_rx); rb_clear(&fifo_rx);
lmcal_uart_set_callback(CLI_UART_CHANNEL, CB_INT_RX_CALLBACK, uart_rx_cb); lmcal_uart_set_callback(CLI_UART_CHANNEL, CB_INT_RX_CALLBACK, uart_rx_cb);
cli_cmd_index = 0; cli_cmd_index = 0;
...@@ -390,26 +278,17 @@ fun_res_t cli_protocol_init(void) ...@@ -390,26 +278,17 @@ fun_res_t cli_protocol_init(void)
strcpy(cli_device_info.version, "1.0.0"); strcpy(cli_device_info.version, "1.0.0");
cli_device_info.board_id = 0; cli_device_info.board_id = 0;
// Приветствие
cli_send_string("\r\n>----- LTA PROTOCOL ENABLE -----<\r\n"); cli_send_string("\r\n>----- LTA PROTOCOL ENABLE -----<\r\n");
cli_send_string("> T00 - Open connection (T0001, T00011357)\r\n");
// Список доступных команд cli_send_string("> T01 - Close connection (T0101)\r\n");
cli_send_string("> T00 - Open connection\r\n"); cli_send_string("> T02 - Ping (T0201)\r\n");
cli_send_string("> T01 - Close connection\r\n"); cli_send_string("> T0A - Get device info (T0A01)\r\n");
cli_send_string("> T02 - Ping\r\n"); cli_send_string("> T14 - Read memory (T14012000000004)\r\n");
cli_send_string("> T0A - Get device info\r\n"); cli_send_string("> T15 - Write memory (T150120000000AABBCCDD)\r\n");
cli_send_string("> T14 - Read memory (addr:4B HEX, size:1B HEX)\r\n");
cli_send_string("> T15 - Write memory (addr:4B HEX, data:HEX)\r\n");
// Приглашение для ввода
cli_send_string("> "); cli_send_string("> ");
return ERR_OK; return ERR_OK;
} }
//-----------------------------------------------------------------------------------------------------------
// Деинициализация протокола
//-----------------------------------------------------------------------------------------------------------
fun_res_t cli_protocol_deinit(void) fun_res_t cli_protocol_deinit(void)
{ {
lmcal_uart_set_callback(CLI_UART_CHANNEL, CB_INT_RX_CALLBACK, NULL); lmcal_uart_set_callback(CLI_UART_CHANNEL, CB_INT_RX_CALLBACK, NULL);
...@@ -417,19 +296,12 @@ fun_res_t cli_protocol_deinit(void) ...@@ -417,19 +296,12 @@ fun_res_t cli_protocol_deinit(void)
return ERR_OK; return ERR_OK;
} }
//-----------------------------------------------------------------------------------------------------------
// Основной цикл обработки
//-----------------------------------------------------------------------------------------------------------
void cli_protocol_process(void) void cli_protocol_process(void)
{ {
while (rb_get_items_qty(&fifo_rx) > 0) { while (rb_get_items_qty(&fifo_rx) > 0) {
u8 ch; u8 ch;
if (rb_get_item(&fifo_rx, &ch) != RB_RES_OK) continue; if (rb_get_item(&fifo_rx, &ch) != RB_RES_OK) continue;
if (cli_cmd_index == 0 && (ch == '\r' || ch == '\n')) continue;
if (cli_cmd_index == 0 && (ch == '\r' || ch == '\n')) {
continue;
}
if (ch == '\r' || ch == '\n') { if (ch == '\r' || ch == '\n') {
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;
...@@ -445,57 +317,34 @@ void cli_protocol_process(void) ...@@ -445,57 +317,34 @@ void cli_protocol_process(void)
memset(cli_cmd_buffer, 0, sizeof(cli_cmd_buffer)); memset(cli_cmd_buffer, 0, sizeof(cli_cmd_buffer));
} }
} }
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;
} }
}
} }
//-----------------------------------------------------------------------------------------------------------
// Установка информации об устройстве
//-----------------------------------------------------------------------------------------------------------
fun_res_t cli_protocol_set_device_info(const char* name, const char* serial, const char* ver, u8 board_id) fun_res_t cli_protocol_set_device_info(const char* name, const char* serial, const char* ver, u8 board_id)
{ {
if (name) strncpy(cli_device_info.name, name, sizeof(cli_device_info.name) - 1); if (name) strncpy(cli_device_info.name, name, sizeof(cli_device_info.name)-1);
if (serial) strncpy(cli_device_info.serial, serial, sizeof(cli_device_info.serial) - 1); if (serial) strncpy(cli_device_info.serial, serial, sizeof(cli_device_info.serial)-1);
if (ver) strncpy(cli_device_info.version, ver, sizeof(cli_device_info.version) - 1); if (ver) strncpy(cli_device_info.version, ver, sizeof(cli_device_info.version)-1);
cli_device_info.board_id = board_id; cli_device_info.board_id = board_id;
return ERR_OK; return ERR_OK;
} }
//-----------------------------------------------------------------------------------------------------------
// Установка board_id
//-----------------------------------------------------------------------------------------------------------
fun_res_t cli_protocol_set_board_id(u8 board_id) fun_res_t cli_protocol_set_board_id(u8 board_id)
{ {
cli_device_info.board_id = board_id; cli_device_info.board_id = board_id;
return ERR_OK; return ERR_OK;
} }
//----------------------------------------------------------------------------------------------------------- u8 cli_protocol_get_board_id(void) { return cli_device_info.board_id; }
// Получение board_id
//-----------------------------------------------------------------------------------------------------------
u8 cli_protocol_get_board_id(void)
{
return cli_device_info.board_id;
}
//-----------------------------------------------------------------------------------------------------------
// Установка пароля
//-----------------------------------------------------------------------------------------------------------
void cli_protocol_set_password(const char* pass) void cli_protocol_set_password(const char* pass)
{ {
if (pass) { if (pass) strncpy(cli_password, pass, sizeof(cli_password)-1);
strncpy(cli_password, pass, sizeof(cli_password) - 1);
cli_password[sizeof(cli_password) - 1] = '\0';
}
} }
//-----------------------------------------------------------------------------------------------------------
// Проверка пароля
//-----------------------------------------------------------------------------------------------------------
bool cli_protocol_verify_password(const char* pass) bool cli_protocol_verify_password(const char* pass)
{ {
if (!pass) return false; if (!pass) return false;
......
...@@ -5,26 +5,25 @@ ...@@ -5,26 +5,25 @@
#include "l_macro_types.h" #include "l_macro_types.h"
#include <stdbool.h> #include <stdbool.h>
//************************************ Константы протокола *************************************************
#define CLI_BROADCAST_ID 0xFFU // Широковещательный адрес (команды для всех плат без ответа)
//************************************ Коды команд (по протоколу 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 - проверка соединения CLI_CMD_PING = 0x02U, // T02 - проверка соединения (ping)
CLI_CMD_GET_INFO = 0x0AU, // T0A - информация об устройстве CLI_CMD_GET_INFO = 0x0AU, // T0A - информация об устройстве
CLI_CMD_READ_MEM = 0x14U, // T14 - чтение памяти CLI_CMD_READ_MEM = 0x14U, // T14 - чтение памяти
CLI_CMD_WRITE_MEM = 0x15U, // T15 - запись памяти CLI_CMD_WRITE_MEM = 0x15U, // T15 - запись памяти
} cli_cmd_t; } cli_cmd_t;
//************************************ Коды ошибок ********************************************************** //************************************ Коды ошибок (только 00-03 по протоколу) ****************************
typedef enum { typedef enum {
CLI_ERR_NONE = 0x00U, CLI_ERR_NONE = 0x00U,
CLI_ERR_UNKNOWN_CMD = 0x01U, CLI_ERR_UNKNOWN_CMD = 0x01U,
CLI_ERR_INVALID_ARG = 0x02U, CLI_ERR_INVALID_ARG = 0x02U,
CLI_ERR_INTERNAL = 0x03U, CLI_ERR_INTERNAL = 0x03U,
CLI_ERR_NOT_CONNECTED = 0x04U,
CLI_ERR_MEMORY = 0x05U,
CLI_ERR_INVALID_ADDR = 0x06U,
CLI_ERR_INVALID_PASS = 0x07U,
} cli_error_t; } cli_error_t;
//************************************ Информация об устройстве ********************************************** //************************************ Информация об устройстве **********************************************
...@@ -32,7 +31,7 @@ typedef struct { ...@@ -32,7 +31,7 @@ typedef struct {
char name[32]; char name[32];
char serial[16]; char serial[16];
char version[16]; char version[16];
u8 board_id; u8 board_id; // Уникальный идентификатор платы (0-254)
} cli_device_info_t; } cli_device_info_t;
//************************************ Публичные функции **************************************************** //************************************ Публичные функции ****************************************************
...@@ -43,10 +42,10 @@ fun_res_t cli_protocol_init(void); ...@@ -43,10 +42,10 @@ fun_res_t cli_protocol_init(void);
// Деинициализация протокола // Деинициализация протокола
fun_res_t cli_protocol_deinit(void); fun_res_t cli_protocol_deinit(void);
// Основной цикл обработки // Основной цикл обработки (вызывать в while(1))
void cli_protocol_process(void); void cli_protocol_process(void);
// Отправка строки // Отправка строки через UART
void cli_send_string(const char* str); void cli_send_string(const char* str);
// Установка информации об устройстве // Установка информации об устройстве
......
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