Initializing the repository
This commit is contained in:
31
.clang-format
Normal file
31
.clang-format
Normal file
@@ -0,0 +1,31 @@
|
||||
AccessModifierOffset: -4
|
||||
AlignConsecutiveAssignments: Consecutive
|
||||
AlignConsecutiveDeclarations: Consecutive
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseExpressionOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortCompoundRequirementOnASingleLine: false
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLambdasOnASingleLine: None
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterReturnType: All
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Allman
|
||||
BreakTemplateDeclarations: Yes
|
||||
ColumnLimit: 100
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: true
|
||||
IndentExternBlock: NoIndent
|
||||
IndentPPDirectives: AfterHash
|
||||
IndentWidth: 4
|
||||
NamespaceIndentation: None
|
||||
PackConstructorInitializers: Never
|
||||
PointerAlignment: Right
|
||||
ReflowComments: Always
|
||||
SortIncludes: CaseSensitive
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
.vscode
|
||||
.idea
|
||||
cache
|
||||
build
|
||||
33
CMakeLists.txt
Normal file
33
CMakeLists.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(jlv135_cli C)
|
||||
|
||||
# Настройка кросс-компиляции
|
||||
set(CMAKE_SYSTEM_NAME Linux)
|
||||
set(CMAKE_C_COMPILER arm-uclinuxfdpiceabi-gcc)
|
||||
set(CMAKE_STRIP arm-uclinuxfdpiceabi-strip)
|
||||
|
||||
# Настройки компиляции
|
||||
set(CMAKE_C_FLAGS "-Os -fdata-sections -ffunction-sections -mno-unaligned-access")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "-Wl,--gc-sections")
|
||||
|
||||
# Создание исполняемого файла
|
||||
add_executable(${PROJECT_NAME}
|
||||
src/jl_modbus/jl_modbus_config.c
|
||||
src/jl_modbus/jl_config.c
|
||||
src/jlv135_cli/main.c)
|
||||
|
||||
# Настройка библиотек
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME} pthread)
|
||||
|
||||
# Добавление каталогов для поиска заголовков
|
||||
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE
|
||||
inc)
|
||||
|
||||
# Опция strip
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
add_custom_command(
|
||||
TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
|
||||
COMMAND strip $<TARGET_FILE:${CMAKE_PROJECT_NAME}>
|
||||
COMMENT "Stripping debug symbols (Release only)"
|
||||
)
|
||||
endif()
|
||||
22
inc/jl_modbus/jl_config.h
Normal file
22
inc/jl_modbus/jl_config.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef JLV135_CLI_CONFIG_H
|
||||
#define JLV135_CLI_CONFIG_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define JLV135_BACKUP_BLOCKS_ADDRESS 0x40400
|
||||
#define JLV135_DEV_MTD_BLOCK "/dev/mtdblock0"
|
||||
|
||||
void
|
||||
jl_config_load(const char *name, void *def, size_t size);
|
||||
|
||||
bool
|
||||
jl_config_read(int block_num, void *data, size_t size);
|
||||
|
||||
bool
|
||||
jl_config_write(int block_num, void *data, size_t size);
|
||||
|
||||
void
|
||||
jl_config_save(const char *name, void *def, size_t size);
|
||||
|
||||
#endif // JLV135_CLI_CONFIG_H
|
||||
54
inc/jl_modbus/jl_modbus_config.h
Normal file
54
inc/jl_modbus/jl_modbus_config.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#ifndef JLV135_CLI_MODBUS_CONFIG_H
|
||||
#define JLV135_CLI_MODBUS_CONFIG_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct jl_version
|
||||
{
|
||||
uint16_t major;
|
||||
uint16_t minor;
|
||||
uint16_t path;
|
||||
} jl_version_t;
|
||||
|
||||
typedef struct jl_modbus_tcp_port
|
||||
{
|
||||
uint32_t addr;
|
||||
uint16_t port;
|
||||
uint16_t repeate;
|
||||
uint16_t timeout;
|
||||
} jl_modbus_tcp_port_t;
|
||||
|
||||
static const uint32_t jl_modbus_rs485_baud_rates[] = {9600, 19200, 38400, 57600, 115200};
|
||||
|
||||
typedef struct jl_modbus_rs485_port
|
||||
{
|
||||
uint16_t speed;
|
||||
uint16_t prop_p;
|
||||
uint16_t prop_s;
|
||||
uint16_t repeate;
|
||||
uint16_t timeout;
|
||||
} jl_modbus_rs485_port_t;
|
||||
|
||||
typedef struct jl_modbus_config
|
||||
{
|
||||
uint16_t num_port;
|
||||
uint16_t addr;
|
||||
uint16_t tcycle;
|
||||
jl_modbus_rs485_port_t port_rtu;
|
||||
jl_modbus_tcp_port_t port_tcp;
|
||||
} jl_modbus_config_t;
|
||||
|
||||
// -------------------------- Методы -------------------------- //
|
||||
|
||||
bool
|
||||
jl_modbus_rs485_baud_rate_is_index_valid(size_t index);
|
||||
|
||||
uint32_t
|
||||
jl_modbus_rs485_baud_rate_get_baud_by_index(size_t index);
|
||||
|
||||
int32_t
|
||||
jl_modbus_rs485_baud_rate_get_index_by_baud(uint32_t baud);
|
||||
|
||||
#endif // JLV135_CLI_MODBUS_CONFIG_H
|
||||
6
inc/jlv135_cli/jl_util.h
Normal file
6
inc/jlv135_cli/jl_util.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef JL135_CLI_UTIL
|
||||
#define JL135_CLI_UTIL
|
||||
|
||||
#define jl_array_size(x) (sizeof(x) / sizeof(x[0]))
|
||||
|
||||
#endif // JL135_CLI_UTIL
|
||||
173
src/jl_modbus/jl_config.c
Normal file
173
src/jl_modbus/jl_config.c
Normal file
@@ -0,0 +1,173 @@
|
||||
#include <jl_modbus/jl_config.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#if JL_CONFIG_SAVE_TO_FILE
|
||||
static const char *jl_config_path = JL_CONFIG_SAVE_TO_FILE_PATH;
|
||||
void
|
||||
jl_config_load(const char *name, void *def, size_t size)
|
||||
{
|
||||
char filename[256] = {0};
|
||||
strcat(filename, jl_config_path);
|
||||
strcat(filename, name);
|
||||
strcat(filename, ".bcfg");
|
||||
|
||||
// printf("jl_config_load [%s]\n", filename);
|
||||
FILE *f = fopen(filename, "rb");
|
||||
if (f != NULL)
|
||||
{
|
||||
fread(def, 1, size, f);
|
||||
fclose(f);
|
||||
// printf("Load %s\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
jl_config_save(name, def, size);
|
||||
}
|
||||
|
||||
void
|
||||
jl_config_save(const char *name, void *def, size_t size)
|
||||
{
|
||||
char filename[256] = {0};
|
||||
strcat(filename, jl_config_path);
|
||||
strcat(filename, name);
|
||||
strcat(filename, ".bcfg");
|
||||
|
||||
// printf("jl_config_save [%s]\n", filename);
|
||||
FILE *f = fopen(filename, "wb");
|
||||
if (f != NULL)
|
||||
{
|
||||
// printf("Save %s\n", name);
|
||||
fwrite(def, 1, size, f);
|
||||
fclose(f);
|
||||
sync();
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const int backup_block_size = 0x80;
|
||||
struct backup_block_t
|
||||
{
|
||||
char name[32];
|
||||
int num;
|
||||
} backup_blocks[] = {{.name = "wifi", .num = 0},
|
||||
{.name = "modbus", .num = 1},
|
||||
{.name = "display", .num = 2},
|
||||
{.name = "feature", .num = 3},
|
||||
{.name = "datatime", .num = 4},
|
||||
{.name = "sensor", .num = 5},
|
||||
{.name = "secure", .num = 6},
|
||||
{.name = "service", .num = 7},
|
||||
{{0}}};
|
||||
|
||||
bool
|
||||
jl_config_read(int block_num, void *data, size_t size)
|
||||
{
|
||||
FILE *mtd0 = fopen(JLV135_DEV_MTD_BLOCK, "rb");
|
||||
size_t read_size = 0;
|
||||
if (mtd0)
|
||||
{
|
||||
bool isSeek =
|
||||
fseek(mtd0, JLV135_BACKUP_BLOCKS_ADDRESS + backup_block_size * block_num, SEEK_SET) ==
|
||||
0;
|
||||
if (isSeek)
|
||||
{
|
||||
read_size = fread(data, 1, size, mtd0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
fclose(mtd0);
|
||||
return read_size == size;
|
||||
}
|
||||
|
||||
bool
|
||||
jl_config_write(int block_num, void *data, size_t size)
|
||||
{
|
||||
FILE *mtd0 = fopen(JLV135_DEV_MTD_BLOCK, "r+b");
|
||||
size_t write_size = 0;
|
||||
if (mtd0)
|
||||
{
|
||||
bool isSeek =
|
||||
fseek(mtd0, JLV135_BACKUP_BLOCKS_ADDRESS + backup_block_size * block_num, SEEK_SET) ==
|
||||
0;
|
||||
if (isSeek)
|
||||
{
|
||||
write_size = fwrite(data, 1, size, mtd0);
|
||||
rewind(mtd0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
fclose(mtd0);
|
||||
return write_size == size;
|
||||
}
|
||||
|
||||
void
|
||||
jl_config_load(const char *name, void *def, size_t size)
|
||||
{
|
||||
struct backup_block_t *block = backup_blocks;
|
||||
|
||||
while (*block->name)
|
||||
{
|
||||
if (strcmp(block->name, name) == 0)
|
||||
{
|
||||
unsigned char mem[size];
|
||||
bool empty = true;
|
||||
if (!jl_config_read(block->num, mem, size))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
if (mem[i] != 0xFF)
|
||||
{
|
||||
empty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (empty)
|
||||
{
|
||||
jl_config_save(name, def, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(def, mem, size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
block++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
jl_config_save(const char *name, void *def, size_t size)
|
||||
{
|
||||
struct backup_block_t *block = backup_blocks;
|
||||
|
||||
while (*block->name)
|
||||
{
|
||||
if (strcmp(block->name, name) == 0)
|
||||
{
|
||||
unsigned char temp[size];
|
||||
if (jl_config_read(block->num, temp, size) && memcmp(temp, def, size) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
jl_config_write(block->num, def, size);
|
||||
return;
|
||||
}
|
||||
block++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
29
src/jl_modbus/jl_modbus_config.c
Normal file
29
src/jl_modbus/jl_modbus_config.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <jl_modbus/jl_modbus_config.h>
|
||||
#include <jlv135_cli/jl_util.h>
|
||||
|
||||
bool
|
||||
jl_modbus_rs485_baud_rate_is_index_valid(size_t index)
|
||||
{
|
||||
size_t sz = jl_array_size(jl_modbus_rs485_baud_rates);
|
||||
return index < sz;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
jl_modbus_rs485_baud_rate_get_baud_by_index(size_t index)
|
||||
{
|
||||
return jl_modbus_rs485_baud_rate_is_index_valid(index) ? jl_modbus_rs485_baud_rates[index] : 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
jl_modbus_rs485_baud_rate_get_index_by_baud(uint32_t baud)
|
||||
{
|
||||
size_t sz = jl_array_size(jl_modbus_rs485_baud_rates);
|
||||
for (size_t i = 0; i < sz; i++)
|
||||
{
|
||||
if (jl_modbus_rs485_baud_rates[i] == baud)
|
||||
{
|
||||
return (int32_t)i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
139
src/jlv135_cli/main.c
Normal file
139
src/jlv135_cli/main.c
Normal file
@@ -0,0 +1,139 @@
|
||||
#include <jl_modbus/jl_config.h>
|
||||
#include <jl_modbus/jl_modbus_config.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define JLV135_CLI_OK 0
|
||||
#define JLV135_CLI_ERROR 1
|
||||
|
||||
void
|
||||
print_version(jl_version_t *ver)
|
||||
{
|
||||
printf("Version:\n");
|
||||
printf(" major: %u\n", ver->major);
|
||||
printf(" minor: %u\n", ver->minor);
|
||||
printf(" path: %u\n\n", ver->path);
|
||||
}
|
||||
|
||||
// Функция для печати TCP порта
|
||||
void
|
||||
print_tcp_port(jl_modbus_tcp_port_t *tcp)
|
||||
{
|
||||
printf("Modbus TCP Port:\n");
|
||||
printf(" addr: %u\n", tcp->addr);
|
||||
printf(" port: %u\n", tcp->port);
|
||||
printf(" repeate: %u\n", tcp->repeate);
|
||||
printf(" timeout: %u\n\n", tcp->timeout);
|
||||
}
|
||||
|
||||
void
|
||||
print_rs485_baud_rates(uint16_t speed_index)
|
||||
{
|
||||
if (jl_modbus_rs485_baud_rate_is_index_valid(speed_index))
|
||||
{
|
||||
printf(" speed: %u\n", jl_modbus_rs485_baud_rates[speed_index]);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" speed: %s\n", "unknown");
|
||||
}
|
||||
}
|
||||
|
||||
// Функция для печати RS485 порта
|
||||
void
|
||||
print_rs485_port(jl_modbus_rs485_port_t *rs485)
|
||||
{
|
||||
printf("Modbus RS485 Port:\n");
|
||||
print_rs485_baud_rates(rs485->speed);
|
||||
|
||||
printf(" prop_p: %u\n", rs485->prop_p);
|
||||
printf(" prop_s: %u\n", rs485->prop_s);
|
||||
printf(" repeate: %u\n", rs485->repeate);
|
||||
printf(" timeout: %u\n\n", rs485->timeout);
|
||||
}
|
||||
|
||||
// Функция для печати конфигурации Modbus
|
||||
void
|
||||
print_modbus_config(jl_modbus_config_t *config)
|
||||
{
|
||||
printf("Modbus Config:\n");
|
||||
printf(" num_port: %u\n", config->num_port);
|
||||
printf(" addr: %u\n", config->addr);
|
||||
printf(" tcycle: %u\n", config->tcycle);
|
||||
printf("\n");
|
||||
|
||||
// Печатаем вложенные структуры
|
||||
print_rs485_port(&config->port_rtu);
|
||||
print_tcp_port(&config->port_tcp);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, const char *argv[])
|
||||
{
|
||||
jl_modbus_config_t conf = {};
|
||||
jl_config_load("modbus", &conf, sizeof(jl_modbus_config_t));
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
print_modbus_config(&conf);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool modbus_mode = false; // Флаг, что был передан --modbus
|
||||
bool modbus_rs485_mode = true; // Флаг, что был передан --rs485
|
||||
|
||||
for (int i = 1; i < argc; i++)
|
||||
{
|
||||
if (strcmp(argv[i], "--modbus") == 0)
|
||||
{
|
||||
modbus_mode = true;
|
||||
continue;
|
||||
}
|
||||
else if (modbus_mode)
|
||||
{
|
||||
// Эти параметры обрабатываются только если был --modbus
|
||||
if (modbus_mode && strcmp(argv[i], "--rs485") == 0)
|
||||
{
|
||||
modbus_rs485_mode = true;
|
||||
continue;
|
||||
}
|
||||
else if (modbus_rs485_mode && strcmp(argv[i], "--speed") == 0)
|
||||
{
|
||||
if (i + 1 < argc)
|
||||
{
|
||||
long val = strtol(argv[i + 1], NULL, 10);
|
||||
int idx = jl_modbus_rs485_baud_rate_get_index_by_baud(val);
|
||||
if (idx == -1)
|
||||
{
|
||||
fprintf(stderr, "Error: invalid speed value\n");
|
||||
return JLV135_CLI_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
conf.port_rtu.speed = idx;
|
||||
jl_config_save("modbus", &conf, sizeof(jl_modbus_config_t));
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Error: --speed requires a value\n");
|
||||
return JLV135_CLI_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Unknown parameter for --modbus: %s\n", argv[i]);
|
||||
return JLV135_CLI_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Unknown parameter: %s (did you forget --modbus?)\n", argv[i]);
|
||||
return JLV135_CLI_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
return JLV135_CLI_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user