feat(RTU): 主程序入口 + 模块注册框架
- src/system/inc/mySystem.h: app_init1/init2/run_fn 回调类型 + stru_app_module + 注册API - src/system/app_modules.c: 模块注册框架实现(register/init1/init2/start/stop/join) - src/system/RTU/src/main.c: 主程序入口(信号处理/模块生命周期/命令交互) - release/src/system/makefile: 构建 libsystem.a(app_modules.c) - release/src/system/RTU/makefile: 编译 RTU 可执行文件(链接全部 lib) - 构建验证: x86 + ARM RTU 可执行文件全通过
This commit is contained in:
parent
854319a500
commit
e1736315e4
|
|
@ -0,0 +1,45 @@
|
||||||
|
include ./../../../linux.mk
|
||||||
|
|
||||||
|
ROOT := $(realpath $(CURDIR)/../../../..)
|
||||||
|
|
||||||
|
INC_PATH := -I$(ROOT)/release/inc \
|
||||||
|
-I$(ROOT)/src/system/inc \
|
||||||
|
-I$(ROOT)/src/public/libdatacenter/inc \
|
||||||
|
-I$(ROOT)/src/public/liblog/inc \
|
||||||
|
-I$(ROOT)/src/public/libfunc/inc \
|
||||||
|
-I$(ROOT)/src/public/libcmd/inc \
|
||||||
|
-I$(ROOT)/src/public/libtask/inc \
|
||||||
|
-I$(ROOT)/src/public/libmy_xxhash/inc \
|
||||||
|
-I$(ROOT)/src/protocol/libmodbus/inc
|
||||||
|
|
||||||
|
LIBS := -L$(ROOT)/release/$(BUILD_TYPE)/lib \
|
||||||
|
-lsystem -lmodbus_m -lmodbus -l60870 \
|
||||||
|
-ldatacenter -lxml -lcmd -ltask \
|
||||||
|
-llog -lfunc -lmy_xxhash -lcJSON -lmd5 -lcomm \
|
||||||
|
-lpthread -lstdc++
|
||||||
|
|
||||||
|
O := $(ROOT)/release/$(BUILD_TYPE)/exe/RTU
|
||||||
|
S := $(ROOT)/src/system/RTU/src
|
||||||
|
B := $(CURDIR)/RTU/obj
|
||||||
|
SRCS := $(wildcard $(S)/*.c)
|
||||||
|
OBJS := $(patsubst $(S)/%.c, $(B)/%.o, $(SRCS))
|
||||||
|
F := $(C_FLAGS) $(INC_PATH)
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: $(O)
|
||||||
|
@echo "[RTU] built -> $(O)"
|
||||||
|
|
||||||
|
$(O): $(OBJS)
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(CXX) $^ $(LIBS) -o $@
|
||||||
|
|
||||||
|
$(B)/%.o: $(S)/%.c
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(CC) $(F) -c $< -o $@
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
rm -rf $(B) $(O)
|
||||||
|
|
||||||
|
.PHONY: rebuild
|
||||||
|
rebuild: clean all
|
||||||
|
|
@ -1,8 +1,36 @@
|
||||||
SUBDIRS := ./libmodbus_m
|
include ./../../linux.mk
|
||||||
define make_subdir
|
|
||||||
for d in $(SUBDIRS); do [ -f "$$d/makefile" ] && (cd "$$d" && make -f makefile $1) || true; done
|
# 纠正 ROOT_DIR:release/src/system 只有三级深度,linux.mk 假设四级
|
||||||
endef
|
ORIG_ROOT := $(ROOT_DIR)
|
||||||
|
ROOT := $(realpath $(CURDIR)/../../..)
|
||||||
|
SYS_SRC := $(ROOT)/src/system
|
||||||
|
PUB_SRC := $(ROOT)/src/public
|
||||||
|
|
||||||
|
LIB := $(ROOT)/release/$(BUILD_TYPE)/lib/libsystem.a
|
||||||
|
LIB_OBJ := $(CURDIR)/libsystem/obj/app_modules.o
|
||||||
|
LIB_FLAGS := $(C_FLAGS) -I$(SYS_SRC)/inc -I$(PUB_SRC)/liblog/inc -I$(PUB_SRC)/libtask/inc -I$(ROOT)/release/inc
|
||||||
|
|
||||||
|
$(LIB): $(LIB_OBJ)
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(AR) rcs $@ $^
|
||||||
|
@echo "[libsystem] built"
|
||||||
|
|
||||||
|
$(LIB_OBJ): $(SYS_SRC)/app_modules.c
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(CC) $(LIB_FLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
.PHONY: clean-sys
|
||||||
|
clean-sys:
|
||||||
|
rm -rf $(CURDIR)/libsystem/obj $(LIB)
|
||||||
|
|
||||||
|
SUBDIRS := ./libmodbus_m ./RTU
|
||||||
|
|
||||||
.PHONY: all clean rebuild
|
.PHONY: all clean rebuild
|
||||||
all:; @$(call make_subdir,all)
|
|
||||||
clean:; @$(call make_subdir,clean)
|
all: $(LIB)
|
||||||
|
@for d in $(SUBDIRS); do [ -f "$$d/makefile" ] && (cd "$$d" && $(MAKE) -f makefile all) || true; done
|
||||||
|
|
||||||
|
clean: clean-sys
|
||||||
|
@for d in $(SUBDIRS); do [ -f "$$d/makefile" ] && (cd "$$d" && $(MAKE) -f makefile clean) || true; done
|
||||||
|
|
||||||
rebuild: clean all
|
rebuild: clean all
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,163 @@
|
||||||
|
/**
|
||||||
|
* @file main.c
|
||||||
|
* @brief RTU 主程序入口
|
||||||
|
* @details 注册所有线程模块 → init1 → init2 → start → wait。
|
||||||
|
* 每个模块在自己的独立线程中运行主循环。
|
||||||
|
*/
|
||||||
|
#include "mySystem.h"
|
||||||
|
#include "myLog.h"
|
||||||
|
#include "myDatacenter.h"
|
||||||
|
#include "myModbus.h"
|
||||||
|
#include "myFunc.h"
|
||||||
|
#include "myCmd.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* ================================================================
|
||||||
|
* 外部模块声明(各模块在 system/ 子目录中实现,链接时解析)
|
||||||
|
* ================================================================ */
|
||||||
|
|
||||||
|
/* libmodbus_m — Modbus 主站管理 */
|
||||||
|
extern int app_modbus_m_init1(void *arg);
|
||||||
|
extern int app_modbus_m_init2(void *arg);
|
||||||
|
extern void *app_modbus_m(void *arg);
|
||||||
|
extern void app_modbus_m_register(void);
|
||||||
|
|
||||||
|
/* ================================================================
|
||||||
|
* 信号处理
|
||||||
|
* ================================================================ */
|
||||||
|
|
||||||
|
static volatile int g_running = 1;
|
||||||
|
|
||||||
|
static void sig_handler(int sig)
|
||||||
|
{
|
||||||
|
(void)sig;
|
||||||
|
g_running = 0;
|
||||||
|
LOG_I("signal received, shutting down...");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ================================================================
|
||||||
|
* 内置命令
|
||||||
|
* ================================================================ */
|
||||||
|
|
||||||
|
static void cmd_version(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
|
||||||
|
printf("RTU_ALL_AI v1.0\n");
|
||||||
|
printf(" libmodbus v%d.%d.%d\n",
|
||||||
|
libmodbus_version_major, libmodbus_version_minor,
|
||||||
|
libmodbus_version_micro);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cmd_uptime(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
|
||||||
|
printf("RTU uptime: (running)\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
CMD_REGISTER("version", cmd_version, "show firmware version");
|
||||||
|
CMD_REGISTER("uptime", cmd_uptime, "show uptime");
|
||||||
|
|
||||||
|
/* ================================================================
|
||||||
|
* main
|
||||||
|
* ================================================================ */
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
|
||||||
|
printf("\n=== RTU_ALL_AI Starting ===\n\n");
|
||||||
|
|
||||||
|
/* 信号处理 */
|
||||||
|
signal(SIGINT, sig_handler);
|
||||||
|
signal(SIGTERM, sig_handler);
|
||||||
|
|
||||||
|
/* 初始化日志 */
|
||||||
|
log_init(NULL);
|
||||||
|
|
||||||
|
LOG_I("RTU booting...");
|
||||||
|
|
||||||
|
/* 注册所有线程模块 */
|
||||||
|
app_modbus_m_register();
|
||||||
|
|
||||||
|
/* 阶段 1: 模块初始化(信号注册前) */
|
||||||
|
if (app_modules_init1() != 0)
|
||||||
|
{
|
||||||
|
LOG_E("app_modules_init1 failed, aborting");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 数据中心初始化 */
|
||||||
|
dc_init(NULL);
|
||||||
|
|
||||||
|
/* 阶段 2: 模块初始化(信号注册后) */
|
||||||
|
if (app_modules_init2() != 0)
|
||||||
|
{
|
||||||
|
LOG_E("app_modules_init2 failed, aborting");
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 启动所有模块线程 */
|
||||||
|
app_modules_start();
|
||||||
|
|
||||||
|
LOG_I("RTU running, %d worker threads", 1);
|
||||||
|
|
||||||
|
/* 主循环: 处理命令输入 */
|
||||||
|
while (g_running)
|
||||||
|
{
|
||||||
|
char *line = linenoise("RTU> ");
|
||||||
|
|
||||||
|
if (!line)
|
||||||
|
{
|
||||||
|
break; /* Ctrl+D */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line[0] != '\0')
|
||||||
|
{
|
||||||
|
linenoiseHistoryAdd(line);
|
||||||
|
|
||||||
|
/* 解析为 argc/argv */
|
||||||
|
char *argv_buf[16];
|
||||||
|
uint8_t argc = 0;
|
||||||
|
|
||||||
|
if (func_str2argv(line, &argc, argv_buf, 16) == 0 && argc > 0)
|
||||||
|
{
|
||||||
|
stru_cmd *cmd = cmd_find(argv_buf[0]);
|
||||||
|
|
||||||
|
if (cmd)
|
||||||
|
{
|
||||||
|
cmd->func((int)argc, argv_buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("unknown command: %s (type 'help')\n", argv_buf[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
linenoiseFree(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 停止所有模块 */
|
||||||
|
LOG_I("stopping all modules...");
|
||||||
|
app_modules_stop();
|
||||||
|
app_modules_join();
|
||||||
|
|
||||||
|
/* 清理 */
|
||||||
|
dc_cleanup();
|
||||||
|
log_cleanup();
|
||||||
|
|
||||||
|
printf("=== RTU_ALL_AI Stopped ===\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
/**
|
||||||
|
* @file app_modules.c
|
||||||
|
* @brief 模块注册框架实现
|
||||||
|
* @details 管理已注册线程模块的生命周期: register → init1 → init2 → start → stop。
|
||||||
|
* 此文件编译进 libsystem.a,供 RTU 主程序使用。
|
||||||
|
*/
|
||||||
|
#include "mySystem.h"
|
||||||
|
#include "myLog.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
/** 最大可注册模块数 */
|
||||||
|
#define APP_MODULES_MAX 16
|
||||||
|
|
||||||
|
/** 已注册模块表 */
|
||||||
|
static stru_app_module g_modules[APP_MODULES_MAX];
|
||||||
|
static int g_module_count = 0;
|
||||||
|
|
||||||
|
/** 线程句柄表 */
|
||||||
|
static pthread_t g_threads[APP_MODULES_MAX];
|
||||||
|
|
||||||
|
void app_module_register(const char *name,
|
||||||
|
app_init1_fn init1,
|
||||||
|
app_init2_fn init2,
|
||||||
|
app_run_fn run,
|
||||||
|
stru_app *p_app)
|
||||||
|
{
|
||||||
|
if (g_module_count >= APP_MODULES_MAX)
|
||||||
|
{
|
||||||
|
LOG_E("app_module_register: max modules reached");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!name || !run)
|
||||||
|
{
|
||||||
|
LOG_E("app_module_register: invalid args");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
stru_app_module *m = &g_modules[g_module_count];
|
||||||
|
|
||||||
|
m->name = name;
|
||||||
|
m->init1 = init1;
|
||||||
|
m->init2 = init2;
|
||||||
|
m->run = run;
|
||||||
|
m->p_app = p_app;
|
||||||
|
|
||||||
|
g_module_count++;
|
||||||
|
|
||||||
|
LOG_I("app_module_register: [%s] registered", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
int app_modules_init1(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < g_module_count; i++)
|
||||||
|
{
|
||||||
|
if (g_modules[i].init1)
|
||||||
|
{
|
||||||
|
LOG_I("app_modules_init1: [%s]...", g_modules[i].name);
|
||||||
|
|
||||||
|
if (g_modules[i].init1(g_modules[i].p_app) != 0)
|
||||||
|
{
|
||||||
|
LOG_E("app_modules_init1: [%s] failed", g_modules[i].name);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int app_modules_init2(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < g_module_count; i++)
|
||||||
|
{
|
||||||
|
if (g_modules[i].init2)
|
||||||
|
{
|
||||||
|
LOG_I("app_modules_init2: [%s]...", g_modules[i].name);
|
||||||
|
|
||||||
|
if (g_modules[i].init2(g_modules[i].p_app) != 0)
|
||||||
|
{
|
||||||
|
LOG_E("app_modules_init2: [%s] failed", g_modules[i].name);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_modules_start(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < g_module_count; i++)
|
||||||
|
{
|
||||||
|
LOG_I("app_modules_start: [%s]...", g_modules[i].name);
|
||||||
|
|
||||||
|
if (pthread_create(&g_threads[i], NULL, g_modules[i].run,
|
||||||
|
g_modules[i].p_app) != 0)
|
||||||
|
{
|
||||||
|
LOG_E("app_modules_start: [%s] thread create failed",
|
||||||
|
g_modules[i].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_modules_stop(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < g_module_count; i++)
|
||||||
|
{
|
||||||
|
if (g_modules[i].p_app && g_modules[i].p_app->p_event)
|
||||||
|
{
|
||||||
|
task_event_send(g_modules[i].p_app->p_event, 0x80); /* 停止信号 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_modules_join(void)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < g_module_count; i++)
|
||||||
|
{
|
||||||
|
if (g_threads[i])
|
||||||
|
{
|
||||||
|
pthread_join(g_threads[i], NULL);
|
||||||
|
LOG_I("app_modules_join: [%s] exited", g_modules[i].name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
/**
|
/**
|
||||||
* @file mySystem.h
|
* @file mySystem.h
|
||||||
* @brief 系统管理模块公共定义
|
* @brief 系统管理模块公共定义
|
||||||
* @details 供 libmodbus_m/libiec/libcom_decode/RTU 等系统模块共用。
|
* @details 定义任务上下文 stru_app 和模块注册框架。
|
||||||
|
* 供 RTU 主程序及所有 system/ 线程模块共用。
|
||||||
*/
|
*/
|
||||||
#ifndef _MY_SYSTEM_H_
|
#ifndef _MY_SYSTEM_H_
|
||||||
#define _MY_SYSTEM_H_
|
#define _MY_SYSTEM_H_
|
||||||
|
|
@ -14,15 +15,56 @@ extern "C"
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** @brief 应用任务上下文(RTU 多任务运行时使用) */
|
/** @brief 应用任务上下文(每个线程模块一个实例) */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
const char *name; /**< 任务名称 */
|
const char *name;
|
||||||
stru_task_event_t p_event; /**< 事件句柄 */
|
stru_task_event_t p_event;
|
||||||
stru_task_msg_queue_t p_queue; /**< 消息队列句柄 */
|
stru_task_msg_queue_t p_queue;
|
||||||
uint32_t run_cnt; /**< 运行计数 */
|
uint32_t run_cnt;
|
||||||
} stru_app;
|
} stru_app;
|
||||||
|
|
||||||
|
/** @brief 模块初始化阶段 1(datacenter 信号注册前) */
|
||||||
|
typedef int (*app_init1_fn)(void *arg);
|
||||||
|
|
||||||
|
/** @brief 模块初始化阶段 2(datacenter 信号注册后) */
|
||||||
|
typedef int (*app_init2_fn)(void *arg);
|
||||||
|
|
||||||
|
/** @brief 模块主循环(独立线程入口) */
|
||||||
|
typedef void *(*app_run_fn)(void *arg);
|
||||||
|
|
||||||
|
/** @brief 已注册的模块描述符 */
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
app_init1_fn init1;
|
||||||
|
app_init2_fn init2;
|
||||||
|
app_run_fn run;
|
||||||
|
stru_app *p_app;
|
||||||
|
} stru_app_module;
|
||||||
|
|
||||||
|
/** @brief 注册一个线程模块 */
|
||||||
|
void app_module_register(const char *name,
|
||||||
|
app_init1_fn init1,
|
||||||
|
app_init2_fn init2,
|
||||||
|
app_run_fn run,
|
||||||
|
stru_app *p_app);
|
||||||
|
|
||||||
|
/** @brief 执行所有模块 init1 */
|
||||||
|
int app_modules_init1(void);
|
||||||
|
|
||||||
|
/** @brief 执行所有模块 init2 */
|
||||||
|
int app_modules_init2(void);
|
||||||
|
|
||||||
|
/** @brief 启动所有模块主循环(每模块一个独立线程) */
|
||||||
|
void app_modules_start(void);
|
||||||
|
|
||||||
|
/** @brief 停止所有模块 */
|
||||||
|
void app_modules_stop(void);
|
||||||
|
|
||||||
|
/** @brief 等待所有模块线程退出 */
|
||||||
|
void app_modules_join(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue