refactor(system): 迁移至 X-Macro 框架 + app_config.json 启停控制
- 新增 app_modules.h: X-Macro 模块中心化列表(当前仅 modbus_m)
- 重写 mySystem.h: 移除旧 app_module_register API,新增:
* enum_app: 通过 app_modules.h X-Macro 自动生成
* extern 声明: 通过 app_modules.h 自动生成全部 init1/init2/run
* stru_app: 增加 p_event/timer[3]/rtx/run_cnt(对齐原工程)
- 新增 app_sys.cpp (替换 app_modules.c):
* 读取 app_config.json → 按 enable:true/false 启停模块
* 自动为每个模块创建 3 级定时器 (10ms/100ms/1000ms) + 事件
* X-Macro 展开 g_vec_app 初始化列表
- 新增 app_config.json: {"apps":[{"name":"app_modbus_m","enable":true}]}
- 删除 app_modules.c: 旧的动态注册框架
This commit is contained in:
parent
aed907a977
commit
447443a6e5
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"apps": [
|
||||||
|
{"name": "app_modbus_m", "enable": true}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -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 <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
/* ---- 启用的应用名集合(从 app_config.json 读取) ---- */
|
||||||
|
static std::set<std::string> g_enabled_apps;
|
||||||
|
|
||||||
|
/* ---- g_vec_app — 由 app_modules.h X-Macro 自动生成 ---- */
|
||||||
|
static std::vector<stru_app> 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];
|
||||||
|
}
|
||||||
|
|
@ -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 <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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
/**
|
/**
|
||||||
* @file mySystem.h
|
* @file mySystem.h
|
||||||
* @brief 系统管理模块公共定义
|
* @brief 系统管理模块公共定义 — X-Macro 框架
|
||||||
* @details 定义任务上下文 stru_app 和模块注册框架。
|
* @details 通过 app_modules.h X-Macro 自动生成:
|
||||||
* 供 RTU 主程序及所有 system/ 线程模块共用。
|
* 1) enum_app 枚举(所有模块 ID)
|
||||||
|
* 2) extern 函数声明(init1/init2/thread)
|
||||||
|
* 3) g_vec_app 初始化列表(app_sys.cpp 中使用)
|
||||||
|
* 新增模块只需修改 app_modules.h,无需改框架代码。
|
||||||
*/
|
*/
|
||||||
#ifndef _MY_SYSTEM_H_
|
#ifndef _MY_SYSTEM_H_
|
||||||
#define _MY_SYSTEM_H_
|
#define _MY_SYSTEM_H_
|
||||||
|
|
@ -15,55 +18,66 @@ extern "C"
|
||||||
{
|
{
|
||||||
#endif
|
#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
|
typedef struct
|
||||||
{
|
{
|
||||||
const char *name;
|
uint16_t rx_len;
|
||||||
stru_task_event_t p_event;
|
uint16_t tx_len;
|
||||||
stru_task_msg_queue_t p_queue;
|
uint8_t rx[MSG_SIZE];
|
||||||
uint32_t run_cnt;
|
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;
|
} stru_app;
|
||||||
|
|
||||||
/** @brief 模块初始化阶段 1(datacenter 信号注册前) */
|
/* ---- 获取模块指针 ---- */
|
||||||
typedef int (*app_init1_fn)(void *arg);
|
stru_app *app_get_ptr(uint32_t app_id);
|
||||||
|
|
||||||
/** @brief 模块初始化阶段 2(datacenter 信号注册后) */
|
/* ---- extern 函数声明,由 app_modules.h 生成 ---- */
|
||||||
typedef int (*app_init2_fn)(void *arg);
|
#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 模块主循环(独立线程入口) */
|
#include "app_modules.h"
|
||||||
typedef void *(*app_run_fn)(void *arg);
|
#undef APP_MODULE
|
||||||
|
|
||||||
/** @brief 已注册的模块描述符 */
|
/* ---- 初始化 ---- */
|
||||||
typedef struct
|
int app_sys_init(void);
|
||||||
{
|
|
||||||
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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue