refactor(RTU): 配置文件独立化 + app_sys_stop() + 代码风格统一

- config/SYSTEM/app_config.json: 配置文件从源码树迁出到独立 config/ 目录
- app_sys.cpp: 配置路径优先级 WORK_PATH 环境变量 > 可执行文件目录
- app_sys.cpp: 新增 app_sys_stop() 完整生命周期(EV_STOP + pthread_join)
- app_sys.cpp: 代码风格统一(空格/花括号/allman)
- main.c: 添加 SIGPIPE 处理 + app_sys_stop() 调用
- mySystem.h: 添加 EV_STOP 宏 + app_sys_stop() 声明
- RTU/makefile: 修复 .PHONY 重复定义 warning
This commit is contained in:
ypc 2026-07-08 17:35:26 +08:00
parent 3f6a3cfe91
commit 16b697f9c4
5 changed files with 137 additions and 24 deletions

View File

@ -25,7 +25,8 @@ S := $(ROOT)/src/system/RTU/src
C_OBJ := $(CURDIR)/RTU/obj/main.o C_OBJ := $(CURDIR)/RTU/obj/main.o
CXX_OBJ := $(CURDIR)/RTU/obj/app_sys.o CXX_OBJ := $(CURDIR)/RTU/obj/app_sys.o
.PHONY: all; all: $(O) .PHONY: all clean rebuild
all: $(O)
$(O): $(C_OBJ) $(CXX_OBJ) $(O): $(C_OBJ) $(CXX_OBJ)
@mkdir -p $(dir $@) @mkdir -p $(dir $@)
@ -40,5 +41,7 @@ $(CXX_OBJ): $(S)/app_sys.cpp
@mkdir -p $(dir $@) @mkdir -p $(dir $@)
$(CXX) $(CXX_FLAGS) $(INC_PATH) -c $< -o $@ $(CXX) $(CXX_FLAGS) $(INC_PATH) -c $< -o $@
.PHONY: clean; clean: clean:
rm -rf $(CURDIR)/RTU/obj $(O) rm -rf $(CURDIR)/RTU/obj $(O)
rebuild: clean all

View File

@ -1,9 +1,16 @@
/** /**
* @file app_sys.cpp * @file app_sys.cpp
* @brief X-Macro + app_config.json * @brief X-Macro + app_config.json
* @details config/SYSTEM/app_config.json * @details <exe目录>/config/SYSTEM/app_config.json
* app_modules.h X-Macro g_vec_app * app_modules.h X-Macro g_vec_app
* + 3 + 线 * + 3 + 线
*
* :
* WORK_PATH/ ()
* RTU
* config/
* SYSTEM/
* app_config.json
*/ */
#include "mySystem.h" #include "mySystem.h"
#include "myLog.h" #include "myLog.h"
@ -19,6 +26,9 @@
/* ---- 启用的应用名集合(从 app_config.json 读取) ---- */ /* ---- 启用的应用名集合(从 app_config.json 读取) ---- */
static std::set<std::string> g_enabled_apps; static std::set<std::string> g_enabled_apps;
/* ---- 线程句柄(用于 stop 时 join ---- */
static std::vector<pthread_t> g_threads;
/* ---- g_vec_app — 由 app_modules.h X-Macro 自动生成 ---- */ /* ---- g_vec_app — 由 app_modules.h X-Macro 自动生成 ---- */
static std::vector<stru_app> g_vec_app = static std::vector<stru_app> g_vec_app =
{ {
@ -32,23 +42,37 @@ static std::vector<stru_app> g_vec_app =
/* ---- 三级定时器事件 ---- */ /* ---- 三级定时器事件 ---- */
static uint32_t g_timer_event[TIMER_NUM] = {EV_TIMER1, EV_TIMER2, EV_TIMER3}; static uint32_t g_timer_event[TIMER_NUM] = {EV_TIMER1, EV_TIMER2, EV_TIMER3};
/* ---- 获取系统配置目录路径 ---- */ /* ---- 获取系统配置目录路径(优先级: WORK_PATH 环境变量 > 可执行文件所在目录) ---- */
static std::string get_system_config_path(void) static std::string get_system_config_path(void)
{ {
char proc_dir[512] = {0}; char buf[512] = {0};
if (0 != func_proc_self_dir(proc_dir, sizeof(proc_dir)))
/* 优先使用 WORK_PATH 环境变量RK3568 装置运行时设置) */
if (0 == func_get_work_path(buf, sizeof(buf)))
{
return std::string(buf) + "/config/SYSTEM/";
}
/* fallback: 从可执行文件路径推导(本地调试用) */
if (0 != func_proc_self_dir(buf, sizeof(buf)))
{ {
LOG_E("func_proc_self_dir failed"); LOG_E("func_proc_self_dir failed");
return ""; return "";
} }
return std::string(proc_dir) + "config/SYSTEM/";
return std::string(buf) + "/config/SYSTEM/";
} }
/* ---- 解析 app_config.json ---- */ /* ---- 解析 app_config.json ---- */
static int app_config_load(void) static int app_config_load(void)
{ {
std::string path = get_system_config_path(); std::string path = get_system_config_path();
if (path.empty()) { return -1; }
if (path.empty())
{
return -1;
}
std::string cfg_path = path + "app_config.json"; std::string cfg_path = path + "app_config.json";
@ -60,9 +84,9 @@ static int app_config_load(void)
/* 配置文件不存在时不视为错误——默认启用所有模块 */ /* 配置文件不存在时不视为错误——默认启用所有模块 */
LOG_I("app_config.json not found, enabling all modules by default"); LOG_I("app_config.json not found, enabling all modules by default");
for (auto &app : g_vec_app) for (size_t i = 0; i < g_vec_app.size(); i++)
{ {
g_enabled_apps.insert(app.name); g_enabled_apps.insert(g_vec_app[i].name);
} }
return 0; return 0;
@ -74,27 +98,38 @@ static int app_config_load(void)
if (!root) if (!root)
{ {
LOG_E("cJSON_Parse failed for app_config.json"); LOG_E("cJSON_Parse failed for app_config.json");
return -1; return -1;
} }
cJSON *apps = cJSON_GetObjectItem(root, "apps"); cJSON *apps = cJSON_GetObjectItem(root, "apps");
if (!apps || !cJSON_IsArray(apps)) if (!apps || !cJSON_IsArray(apps))
{ {
LOG_E("app_config.json missing 'apps' array"); LOG_E("app_config.json missing 'apps' array");
cJSON_Delete(root); cJSON_Delete(root);
return -1; return -1;
} }
int arr_size = cJSON_GetArraySize(apps); int arr_size = cJSON_GetArraySize(apps);
for (int i = 0; i < arr_size; i++) for (int i = 0; i < arr_size; i++)
{ {
cJSON *item = cJSON_GetArrayItem(apps, i); cJSON *item = cJSON_GetArrayItem(apps, i);
if (!item) { continue; }
if (!item)
{
continue;
}
cJSON *name = cJSON_GetObjectItem(item, "name"); cJSON *name = cJSON_GetObjectItem(item, "name");
cJSON *enable = cJSON_GetObjectItem(item, "enable"); cJSON *enable = cJSON_GetObjectItem(item, "enable");
if (!name || !cJSON_IsString(name)) { continue; } if (!name || !cJSON_IsString(name))
{
continue;
}
if (enable && cJSON_IsTrue(enable)) if (enable && cJSON_IsTrue(enable))
{ {
@ -112,6 +147,7 @@ static int app_config_load(void)
if (g_enabled_apps.empty()) if (g_enabled_apps.empty())
{ {
LOG_E("no apps enabled in config"); LOG_E("no apps enabled in config");
return -1; return -1;
} }
@ -127,13 +163,19 @@ static bool is_app_enabled(const char *name)
/* ---- 定时器回调:发送对应的定时器事件给模块 ---- */ /* ---- 定时器回调:发送对应的定时器事件给模块 ---- */
static void app_timer_expire(void *arg) static void app_timer_expire(void *arg)
{ {
if (!arg) { return; } if (!arg)
{
return;
}
uint32_t signal = *(uint32_t *)arg; uint32_t signal = *(uint32_t *)arg;
uint8_t thid = signal >> 8; uint8_t thid = signal >> 8;
uint8_t tm_id = signal & 0xFF; uint8_t tm_id = signal & 0xFF;
if (thid >= g_vec_app.size() || tm_id >= TIMER_NUM) { return; } if (thid >= g_vec_app.size() || tm_id >= TIMER_NUM)
{
return;
}
task_event_send(g_vec_app[thid].p_event, g_timer_event[tm_id]); task_event_send(g_vec_app[thid].p_event, g_timer_event[tm_id]);
} }
@ -141,7 +183,10 @@ static void app_timer_expire(void *arg)
/* ---- 为一个模块创建 3 级定时器 ---- */ /* ---- 为一个模块创建 3 级定时器 ---- */
static int app_timer_create(stru_app *p_app) static int app_timer_create(stru_app *p_app)
{ {
if (!p_app) { return -1; } if (!p_app)
{
return -1;
}
uint32_t delay_ms = 1; uint32_t delay_ms = 1;
@ -162,6 +207,7 @@ static int app_timer_create(stru_app *p_app)
if (!p_app->p_timer[i]) if (!p_app->p_timer[i])
{ {
LOG_E("timer%d create failed for %s", i + 1, p_app->name); LOG_E("timer%d create failed for %s", i + 1, p_app->name);
return -1; return -1;
} }
@ -174,24 +220,29 @@ static int app_timer_create(stru_app *p_app)
/* ---- 主初始化流程 ---- */ /* ---- 主初始化流程 ---- */
static int app_init(void) static int app_init(void)
{ {
uint32_t i; size_t i;
/* init1: 信号注册前 */ /* init1: 信号注册前 */
for (i = 0; i < g_vec_app.size(); i++) for (i = 0; i < g_vec_app.size(); i++)
{ {
stru_app *p = &g_vec_app[i]; stru_app *p = &g_vec_app[i];
if (!p->app_init1) { continue; } if (!p->app_init1)
{
continue;
}
if (!is_app_enabled(p->name)) if (!is_app_enabled(p->name))
{ {
LOG_I("app skipped (disabled): %s", p->name); LOG_I("app skipped (disabled): %s", p->name);
continue; continue;
} }
if (0 != p->app_init1((void *)p)) if (0 != p->app_init1((void *)p))
{ {
LOG_E("app_init1 failed: %s", p->name); LOG_E("app_init1 failed: %s", p->name);
return -1; return -1;
} }
} }
@ -201,17 +252,22 @@ static int app_init(void)
{ {
stru_app *p = &g_vec_app[i]; stru_app *p = &g_vec_app[i];
if (!p->app_init2) { continue; } if (!p->app_init2)
{
continue;
}
if (!is_app_enabled(p->name)) if (!is_app_enabled(p->name))
{ {
LOG_I("app skipped (disabled): %s", p->name); LOG_I("app skipped (disabled): %s", p->name);
continue; continue;
} }
if (0 != p->app_init2((void *)p)) if (0 != p->app_init2((void *)p))
{ {
LOG_E("app_init2 failed: %s", p->name); LOG_E("app_init2 failed: %s", p->name);
return -1; return -1;
} }
} }
@ -224,10 +280,12 @@ static int app_init(void)
p->app_id = i; p->app_id = i;
std::string ev_name = "EV_" + std::string(p->name); std::string ev_name = "EV_" + std::string(p->name);
p->p_event = task_event_create(ev_name.c_str()); p->p_event = task_event_create(ev_name.c_str());
if (!p->p_event) if (!p->p_event)
{ {
LOG_E("task_event_create failed: %s", ev_name.c_str()); LOG_E("task_event_create failed: %s", ev_name.c_str());
return -1; return -1;
} }
@ -236,12 +294,14 @@ static int app_init(void)
if (0 != app_timer_create(p)) if (0 != app_timer_create(p))
{ {
LOG_E("app_timer_create failed: %s", p->name); LOG_E("app_timer_create failed: %s", p->name);
return -1; return -1;
} }
if (!is_app_enabled(p->name)) if (!is_app_enabled(p->name))
{ {
LOG_I("app skipped (disabled): %s", p->name); LOG_I("app skipped (disabled): %s", p->name);
continue; continue;
} }
@ -250,10 +310,11 @@ static int app_init(void)
if (0 != pthread_create(&thread, NULL, p->fun_cb, p->arg)) if (0 != pthread_create(&thread, NULL, p->fun_cb, p->arg))
{ {
LOG_E("pthread_create failed: %s", p->name); LOG_E("pthread_create failed: %s", p->name);
return -1; return -1;
} }
pthread_detach(thread); g_threads.push_back(thread);
LOG_I("thread started: %s", p->name); LOG_I("thread started: %s", p->name);
task_sleep_ms(10); task_sleep_ms(10);
@ -269,30 +330,62 @@ int app_sys_init(void)
if (0 != app_config_load()) if (0 != app_config_load())
{ {
LOG_E("app_config_load failed"); LOG_E("app_config_load failed");
return -1; return -1;
} }
if (g_vec_app.size() != ENUM_APP_MAX) if (g_vec_app.size() != (size_t)ENUM_APP_MAX)
{ {
LOG_E("g_vec_app size mismatch: %zu vs ENUM %d", LOG_E("g_vec_app size mismatch: %zu vs ENUM %d",
g_vec_app.size(), ENUM_APP_MAX); g_vec_app.size(), ENUM_APP_MAX);
return -1; return -1;
} }
if (0 != app_init()) if (0 != app_init())
{ {
LOG_E("app_init failed"); LOG_E("app_init failed");
return -1; return -1;
} }
return 0; return 0;
} }
/**
* @brief
* @details EV_STOP 退 join 线
*/
void app_sys_stop(void)
{
LOG_I("stopping all app modules...");
for (size_t i = 0; i < g_vec_app.size(); i++)
{
stru_app *p = &g_vec_app[i];
if (p->p_event)
{
task_event_send(p->p_event, EV_STOP);
}
}
/* 等待所有线程退出 */
for (size_t i = 0; i < g_threads.size(); i++)
{
pthread_join(g_threads[i], NULL);
LOG_I("module thread [%zu] exited", i);
}
LOG_I("all app modules stopped");
}
stru_app *app_get_ptr(uint32_t app_id) stru_app *app_get_ptr(uint32_t app_id)
{ {
if (app_id >= ENUM_APP_MAX) if (app_id >= ENUM_APP_MAX)
{ {
LOG_E("app_id out of range: %u max %d", app_id, ENUM_APP_MAX); LOG_E("app_id out of range: %u max %d", app_id, ENUM_APP_MAX);
return NULL; return NULL;
} }

View File

@ -3,6 +3,13 @@
* @brief RTU * @brief RTU
* @details app_sys_init() X-Macro * @details app_sys_init() X-Macro
* src/system/inc/app_modules.h * src/system/inc/app_modules.h
*
* :
* WORK_PATH/ ( WORK_PATH )
* RTU
* config/
* SYSTEM/
* app_config.json
*/ */
#include "mySystem.h" #include "mySystem.h"
#include "myLog.h" #include "myLog.h"
@ -22,13 +29,14 @@ static void sig_handler(int sig)
{ {
(void)sig; (void)sig;
g_running = 0; g_running = 0;
LOG_I("signal received, shutting down..."); LOG_I("signal %d received, shutting down...", sig);
} }
static void cmd_version(int argc, char *argv[]) static void cmd_version(int argc, char *argv[])
{ {
(void)argc; (void)argc;
(void)argv; (void)argv;
printf("RTU_ALL_AI v1.0\n"); printf("RTU_ALL_AI v1.0\n");
printf(" libmodbus v%d.%d.%d\n", printf(" libmodbus v%d.%d.%d\n",
libmodbus_version_major, libmodbus_version_minor, libmodbus_version_major, libmodbus_version_minor,
@ -39,6 +47,7 @@ static void cmd_uptime(int argc, char *argv[])
{ {
(void)argc; (void)argc;
(void)argv; (void)argv;
printf("RTU uptime: (running)\n"); printf("RTU uptime: (running)\n");
} }
@ -64,6 +73,7 @@ int main(int argc, char *argv[])
if (app_sys_init() != 0) if (app_sys_init() != 0)
{ {
LOG_E("app_sys_init failed, aborting"); LOG_E("app_sys_init failed, aborting");
return 1; return 1;
} }
@ -73,7 +83,10 @@ int main(int argc, char *argv[])
{ {
char *line = linenoise("RTU> "); char *line = linenoise("RTU> ");
if (!line) { break; } if (!line)
{
break;
}
if (line[0] != '\0') if (line[0] != '\0')
{ {
@ -101,6 +114,8 @@ int main(int argc, char *argv[])
} }
LOG_I("shutting down..."); LOG_I("shutting down...");
app_sys_stop();
dc_cleanup(); dc_cleanup();
log_cleanup(); log_cleanup();

View File

@ -24,6 +24,7 @@ extern "C"
#define EV_TIMER1 (0x01 << 0) #define EV_TIMER1 (0x01 << 0)
#define EV_TIMER2 (0x01 << 1) #define EV_TIMER2 (0x01 << 1)
#define EV_TIMER3 (0x01 << 2) #define EV_TIMER3 (0x01 << 2)
#define EV_STOP (0x80) /**< 模块停止信号 */
#define MSG_SIZE 2048 #define MSG_SIZE 2048
@ -76,8 +77,9 @@ stru_app *app_get_ptr(uint32_t app_id);
#include "app_modules.h" #include "app_modules.h"
#undef APP_MODULE #undef APP_MODULE
/* ---- 初始化 ---- */ /* ---- 初始化与停止 ---- */
int app_sys_init(void); int app_sys_init(void);
void app_sys_stop(void);
#ifdef __cplusplus #ifdef __cplusplus
} }