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