diff --git a/src/system/RTU/src/app_config.json b/src/system/RTU/src/app_config.json new file mode 100644 index 0000000..ede5e3d --- /dev/null +++ b/src/system/RTU/src/app_config.json @@ -0,0 +1,5 @@ +{ + "apps": [ + {"name": "app_modbus_m", "enable": true} + ] +} diff --git a/src/system/RTU/src/app_sys.cpp b/src/system/RTU/src/app_sys.cpp new file mode 100644 index 0000000..0161f55 --- /dev/null +++ b/src/system/RTU/src/app_sys.cpp @@ -0,0 +1,300 @@ +/** + * @file app_sys.cpp + * @brief 应用系统初始化 — X-Macro 驱动 + app_config.json 启停控制 + * @details 读取 config/SYSTEM/app_config.json 决定哪些模块启用, + * 通过 app_modules.h X-Macro 自动生成模块列表和 g_vec_app, + * 为每个模块创建事件 + 3 级定时器 + 独立线程。 + */ +#include "mySystem.h" +#include "myLog.h" +#include "myFunc.h" +#include "myDatacenter.h" +#include "cJSON.h" + +#include +#include +#include +#include + +/* ---- 启用的应用名集合(从 app_config.json 读取) ---- */ +static std::set g_enabled_apps; + +/* ---- g_vec_app — 由 app_modules.h X-Macro 自动生成 ---- */ +static std::vector g_vec_app = +{ +#define APP_MODULE(name, cfg_name, init1, init2, func) \ + {"app_" #cfg_name, 0, init1, init2, (app_func_fn)func, NULL, 0, {}, {}, {}, 0}, + +#include "app_modules.h" +#undef APP_MODULE +}; + +/* ---- 三级定时器事件 ---- */ +static uint32_t g_timer_event[TIMER_NUM] = {EV_TIMER1, EV_TIMER2, EV_TIMER3}; + +/* ---- 获取系统配置目录路径 ---- */ +static std::string get_system_config_path(void) +{ + char proc_dir[512] = {0}; + if (0 != func_proc_self_dir(proc_dir, sizeof(proc_dir))) + { + LOG_E("func_proc_self_dir failed"); + return ""; + } + return std::string(proc_dir) + "config/SYSTEM/"; +} + +/* ---- 解析 app_config.json ---- */ +static int app_config_load(void) +{ + std::string path = get_system_config_path(); + if (path.empty()) { return -1; } + + std::string cfg_path = path + "app_config.json"; + + uint32_t fsize = 0; + uint8_t *buf = func_read_file_alloc(cfg_path.c_str(), &fsize); + + if (!buf) + { + /* 配置文件不存在时不视为错误——默认启用所有模块 */ + LOG_I("app_config.json not found, enabling all modules by default"); + + for (auto &app : g_vec_app) + { + g_enabled_apps.insert(app.name); + } + + return 0; + } + + cJSON *root = cJSON_Parse((const char *)buf); + free(buf); + + if (!root) + { + LOG_E("cJSON_Parse failed for app_config.json"); + return -1; + } + + cJSON *apps = cJSON_GetObjectItem(root, "apps"); + if (!apps || !cJSON_IsArray(apps)) + { + LOG_E("app_config.json missing 'apps' array"); + cJSON_Delete(root); + return -1; + } + + int arr_size = cJSON_GetArraySize(apps); + for (int i = 0; i < arr_size; i++) + { + cJSON *item = cJSON_GetArrayItem(apps, i); + if (!item) { continue; } + + cJSON *name = cJSON_GetObjectItem(item, "name"); + cJSON *enable = cJSON_GetObjectItem(item, "enable"); + + if (!name || !cJSON_IsString(name)) { continue; } + + if (enable && cJSON_IsTrue(enable)) + { + g_enabled_apps.insert(std::string(name->valuestring)); + LOG_I("app enabled: %s", name->valuestring); + } + else + { + LOG_I("app disabled: %s", name->valuestring); + } + } + + cJSON_Delete(root); + + if (g_enabled_apps.empty()) + { + LOG_E("no apps enabled in config"); + return -1; + } + + return 0; +} + +/* ---- 判断模块是否启用 ---- */ +static bool is_app_enabled(const char *name) +{ + return g_enabled_apps.find(name) != g_enabled_apps.end(); +} + +/* ---- 定时器回调:发送对应的定时器事件给模块 ---- */ +static void app_timer_expire(void *arg) +{ + if (!arg) { return; } + + uint32_t signal = *(uint32_t *)arg; + uint8_t thid = signal >> 8; + uint8_t tm_id = signal & 0xFF; + + 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]); +} + +/* ---- 为一个模块创建 3 级定时器 ---- */ +static int app_timer_create(stru_app *p_app) +{ + if (!p_app) { return -1; } + + uint32_t delay_ms = 1; + + for (int i = 0; i < TIMER_NUM; i++) + { + std::string tm_name = std::string(p_app->name) + "_tm" + std::to_string(i + 1); + + p_app->timer_arg[i] = ((p_app->app_id << 8) | i) & 0xFFFF; + delay_ms *= 10; + + p_app->p_timer[i] = task_timer_create( + tm_name.c_str(), + app_timer_expire, + (void *)&p_app->timer_arg[i], + delay_ms, + TASK_TIMER_FLAG_PERIODIC); + + if (!p_app->p_timer[i]) + { + LOG_E("timer%d create failed for %s", i + 1, p_app->name); + return -1; + } + + task_timer_start(p_app->p_timer[i]); + } + + return 0; +} + +/* ---- 主初始化流程 ---- */ +static int app_init(void) +{ + uint32_t i; + + /* init1: 信号注册前 */ + for (i = 0; i < g_vec_app.size(); i++) + { + stru_app *p = &g_vec_app[i]; + + if (!p->app_init1) { continue; } + + if (!is_app_enabled(p->name)) + { + LOG_I("app skipped (disabled): %s", p->name); + continue; + } + + if (0 != p->app_init1((void *)p)) + { + LOG_E("app_init1 failed: %s", p->name); + return -1; + } + } + + /* init2: 信号注册后 */ + for (i = 0; i < g_vec_app.size(); i++) + { + stru_app *p = &g_vec_app[i]; + + if (!p->app_init2) { continue; } + + if (!is_app_enabled(p->name)) + { + LOG_I("app skipped (disabled): %s", p->name); + continue; + } + + if (0 != p->app_init2((void *)p)) + { + LOG_E("app_init2 failed: %s", p->name); + return -1; + } + } + + /* 创建事件 + 定时器 + 启动线程 */ + for (i = 0; i < g_vec_app.size(); i++) + { + stru_app *p = &g_vec_app[i]; + + p->app_id = i; + + std::string ev_name = "EV_" + std::string(p->name); + p->p_event = task_event_create(ev_name.c_str()); + if (!p->p_event) + { + LOG_E("task_event_create failed: %s", ev_name.c_str()); + return -1; + } + + p->arg = (void *)p; + + if (0 != app_timer_create(p)) + { + LOG_E("app_timer_create failed: %s", p->name); + return -1; + } + + if (!is_app_enabled(p->name)) + { + LOG_I("app skipped (disabled): %s", p->name); + continue; + } + + pthread_t thread; + + if (0 != pthread_create(&thread, NULL, p->fun_cb, p->arg)) + { + LOG_E("pthread_create failed: %s", p->name); + return -1; + } + + pthread_detach(thread); + + LOG_I("thread started: %s", p->name); + task_sleep_ms(10); + } + + return 0; +} + +/* ---- 公共 API ---- */ + +int app_sys_init(void) +{ + if (0 != app_config_load()) + { + LOG_E("app_config_load failed"); + return -1; + } + + if (g_vec_app.size() != ENUM_APP_MAX) + { + LOG_E("g_vec_app size mismatch: %zu vs ENUM %d", + g_vec_app.size(), ENUM_APP_MAX); + return -1; + } + + if (0 != app_init()) + { + LOG_E("app_init failed"); + return -1; + } + + return 0; +} + +stru_app *app_get_ptr(uint32_t app_id) +{ + if (app_id >= ENUM_APP_MAX) + { + LOG_E("app_id out of range: %u max %d", app_id, ENUM_APP_MAX); + return NULL; + } + + return &g_vec_app[app_id]; +} diff --git a/src/system/app_modules.c b/src/system/app_modules.c deleted file mode 100644 index d9ec96b..0000000 --- a/src/system/app_modules.c +++ /dev/null @@ -1,133 +0,0 @@ -/** - * @file app_modules.c - * @brief 模块注册框架实现 - * @details 管理已注册线程模块的生命周期: register → init1 → init2 → start → stop。 - * 此文件编译进 libsystem.a,供 RTU 主程序使用。 - */ -#include "mySystem.h" -#include "myLog.h" - -#include -#include -#include - -/** 最大可注册模块数 */ -#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); - } - } -} diff --git a/src/system/inc/app_modules.h b/src/system/inc/app_modules.h new file mode 100644 index 0000000..c97325e --- /dev/null +++ b/src/system/inc/app_modules.h @@ -0,0 +1,26 @@ +/** + * @file app_modules.h + * @brief 应用模块注册表 — X-Macro 中心化列表 + * @details 此文件故意不设 include guard,因为需要被多次包含 + * (每次在不同的 APP_MODULE 宏定义下展开)。 + * 新增模块只需在此文件中追加一行,无需修改其他代码。 + * + * 格式: APP_MODULE(枚举后缀, 配置名, init1, init2, 线程入口) + * - 枚举后缀: 用于生成 ENUM_APP_<后缀> 枚举值(大写) + * - 配置名: 用于生成 "app_<配置名>" 名称字符串(小写) + * - init1: 阶段1 初始化函数(信号注册前) + * - init2: 阶段2 初始化函数(信号注册后,可为 NULL) + * - 线程入口: 主循环入口函数(独立线程中运行) + */ + +#ifndef APP_MODULE +#error "APP_MODULE macro must be defined before including app_modules.h" +#endif + +/* ============== 线程模块(system/ 子目录) ============== */ +APP_MODULE(MODBUS_M, modbus_m, app_modbus_m_init1, app_modbus_m_init2, app_modbus_m) + +/* ============== 预留模块(阶段 2-3 实现后取消注释) ============== */ +// APP_MODULE(COM_DECODE, com_decode, app_com_decode_init1, app_com_decode_init2, app_com_decode) +// APP_MODULE(IEC, iec, app_iec_init1, app_iec_init2, app_iec) +// APP_MODULE(WEB_SERVER, web_server, app_web_server_init1, app_web_server_init2, app_web_server) diff --git a/src/system/inc/mySystem.h b/src/system/inc/mySystem.h index 08625ed..da22518 100644 --- a/src/system/inc/mySystem.h +++ b/src/system/inc/mySystem.h @@ -1,8 +1,11 @@ /** * @file mySystem.h - * @brief 系统管理模块公共定义 - * @details 定义任务上下文 stru_app 和模块注册框架。 - * 供 RTU 主程序及所有 system/ 线程模块共用。 + * @brief 系统管理模块公共定义 — X-Macro 框架 + * @details 通过 app_modules.h X-Macro 自动生成: + * 1) enum_app 枚举(所有模块 ID) + * 2) extern 函数声明(init1/init2/thread) + * 3) g_vec_app 初始化列表(app_sys.cpp 中使用) + * 新增模块只需修改 app_modules.h,无需改框架代码。 */ #ifndef _MY_SYSTEM_H_ #define _MY_SYSTEM_H_ @@ -15,55 +18,66 @@ extern "C" { #endif -/** @brief 应用任务上下文(每个线程模块一个实例) */ +/** 每个模块的定时器数量(10ms / 100ms / 1000ms 三级) */ +#define TIMER_NUM 3 + +#define EV_TIMER1 (0x01 << 0) +#define EV_TIMER2 (0x01 << 1) +#define EV_TIMER3 (0x01 << 2) + +#define MSG_SIZE 2048 + +/* ---- 应用枚举,由 app_modules.h 生成 ---- */ +#define APP_MODULE(name, cfg_name, init1, init2, func) ENUM_APP_##name, +typedef enum +{ +#include "app_modules.h" + ENUM_APP_MAX +} enum_app; +#undef APP_MODULE + +/* ---- 应用数据收发结构体 ---- */ typedef struct { - const char *name; - stru_task_event_t p_event; - stru_task_msg_queue_t p_queue; - uint32_t run_cnt; + uint16_t rx_len; + uint16_t tx_len; + uint8_t rx[MSG_SIZE]; + uint8_t tx[MSG_SIZE]; +} stru_rtx_data; + +/* ---- 应用上下文(每个线程模块一个实例) ---- */ +typedef int (*app_init_fn)(void *arg); +typedef void *(*app_func_fn)(void *arg); + +typedef struct +{ + const char *name; + uint32_t app_id; + app_init_fn app_init1; + app_init_fn app_init2; + app_func_fn fun_cb; + void *arg; + stru_task_event_t p_event; + stru_rtx_data rtx; + uint32_t timer_arg[TIMER_NUM]; + stru_task_timer_t p_timer[TIMER_NUM]; + uint32_t run_cnt; } stru_app; -/** @brief 模块初始化阶段 1(datacenter 信号注册前) */ -typedef int (*app_init1_fn)(void *arg); +/* ---- 获取模块指针 ---- */ +stru_app *app_get_ptr(uint32_t app_id); -/** @brief 模块初始化阶段 2(datacenter 信号注册后) */ -typedef int (*app_init2_fn)(void *arg); +/* ---- extern 函数声明,由 app_modules.h 生成 ---- */ +#define APP_MODULE(name, cfg_name, init1, init2, func) \ + extern int init1(void *arg); \ + extern int init2(void *arg); \ + extern void *func(void *arg); -/** @brief 模块主循环(独立线程入口) */ -typedef void *(*app_run_fn)(void *arg); +#include "app_modules.h" +#undef APP_MODULE -/** @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); +/* ---- 初始化 ---- */ +int app_sys_init(void); #ifdef __cplusplus }