feat: 添加模块生命周期管理框架并重构现有模块
添加了模块生命周期管理头文件 module_lifecycle.h,定义了完整的生命周期状态机, 包括初始化、运行、停止、挂起和错误状态。同时将电池模块、BLE BAS模块、BLE HID 模块和BLE NUS模块重构为使用新的生命周期框架进行状态管理。 提升日志缓冲区大小以支持更详细的调试信息记录。
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#include "bat_state_event.h"
|
||||
#include "datetime_event.h"
|
||||
#include "hid_led_event.h"
|
||||
#include "module_lifecycle.h"
|
||||
#include "mode_switch_event.h"
|
||||
#include "theme_rgb_update_event.h"
|
||||
#include "theme_color.h"
|
||||
@@ -27,46 +28,74 @@ BUILD_ASSERT(DT_HAS_CHOSEN(zephyr_display), "Missing zephyr,display chosen node"
|
||||
BUILD_ASSERT(DT_NODE_HAS_STATUS(DT_ALIAS(backlight), okay),
|
||||
"Missing backlight alias");
|
||||
|
||||
static const struct device *const display_dev =
|
||||
DEVICE_DT_GET(DT_CHOSEN(zephyr_display));
|
||||
static const struct device *const backlight_dev =
|
||||
DEVICE_DT_GET(DT_PARENT(DT_ALIAS(backlight)));
|
||||
static const uint32_t backlight_idx = DT_NODE_CHILD_IDX(DT_ALIAS(backlight));
|
||||
static struct ui_main_model ui_model = {
|
||||
.theme_color = LV_COLOR_MAKE(BLINKY_THEME_DEFAULT_R,
|
||||
BLINKY_THEME_DEFAULT_G,
|
||||
BLINKY_THEME_DEFAULT_B),
|
||||
.inactive_border_color = LV_COLOR_MAKE(0x3A, 0x44, 0x52),
|
||||
.mode = MODE_SWITCH_BLE,
|
||||
struct display_module_ctx {
|
||||
struct module_lifecycle_ctx lc;
|
||||
const struct device *display_dev;
|
||||
const struct device *backlight_dev;
|
||||
uint32_t backlight_idx;
|
||||
struct ui_main_model ui_model;
|
||||
bool lvgl_initialized;
|
||||
char date_text[DATETIME_EVENT_DATE_TEXT_LEN];
|
||||
char time_text[DATETIME_EVENT_TIME_TEXT_LEN];
|
||||
};
|
||||
|
||||
static int do_init(void);
|
||||
static int do_start(void);
|
||||
static int do_stop(void);
|
||||
|
||||
static const struct module_lifecycle_cfg lifecycle_cfg = {
|
||||
.mode = ML_MODE_POWER,
|
||||
.stopped_state = MODULE_STATE_STANDBY,
|
||||
};
|
||||
|
||||
static const struct module_lifecycle_ops lifecycle_ops = {
|
||||
.do_init = do_init,
|
||||
.do_start = do_start,
|
||||
.do_stop = do_stop,
|
||||
};
|
||||
|
||||
static struct display_module_ctx ctx = {
|
||||
.lc = {
|
||||
.state = LC_UNINIT,
|
||||
.cfg = &lifecycle_cfg,
|
||||
.ops = &lifecycle_ops,
|
||||
},
|
||||
.display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display)),
|
||||
.backlight_dev = DEVICE_DT_GET(DT_PARENT(DT_ALIAS(backlight))),
|
||||
.backlight_idx = DT_NODE_CHILD_IDX(DT_ALIAS(backlight)),
|
||||
.ui_model = {
|
||||
.theme_color = LV_COLOR_MAKE(BLINKY_THEME_DEFAULT_R,
|
||||
BLINKY_THEME_DEFAULT_G,
|
||||
BLINKY_THEME_DEFAULT_B),
|
||||
.inactive_border_color = LV_COLOR_MAKE(0x3A, 0x44, 0x52),
|
||||
.mode = MODE_SWITCH_BLE,
|
||||
},
|
||||
.date_text = "1970/01/01",
|
||||
.time_text = "00:00:00",
|
||||
};
|
||||
static bool initialized;
|
||||
static bool running;
|
||||
static bool lvgl_initialized;
|
||||
static char date_text[DATETIME_EVENT_DATE_TEXT_LEN] = "1970/01/01";
|
||||
static char time_text[DATETIME_EVENT_TIME_TEXT_LEN] = "00:00:00";
|
||||
|
||||
static int backlight_set(bool on)
|
||||
{
|
||||
if (on) {
|
||||
return led_on(backlight_dev, backlight_idx);
|
||||
return led_on(ctx.backlight_dev, ctx.backlight_idx);
|
||||
}
|
||||
|
||||
return led_off(backlight_dev, backlight_idx);
|
||||
return led_off(ctx.backlight_dev, ctx.backlight_idx);
|
||||
}
|
||||
|
||||
static int module_init(void)
|
||||
static int do_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
LOG_INF("Display init on %s", display_dev->name);
|
||||
LOG_INF("Display init on %s", ctx.display_dev->name);
|
||||
|
||||
if (!device_is_ready(display_dev)) {
|
||||
LOG_ERR("Display device %s not ready", display_dev->name);
|
||||
if (!device_is_ready(ctx.display_dev)) {
|
||||
LOG_ERR("Display device %s not ready", ctx.display_dev->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!device_is_ready(backlight_dev)) {
|
||||
LOG_ERR("Backlight device %s not ready", backlight_dev->name);
|
||||
if (!device_is_ready(ctx.backlight_dev)) {
|
||||
LOG_ERR("Backlight device %s not ready", ctx.backlight_dev->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
@@ -79,25 +108,25 @@ static int module_init(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int module_start(void)
|
||||
static int do_start(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (running) {
|
||||
if (module_lifecycle_is_running(&ctx.lc)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!lvgl_initialized) {
|
||||
if (!ctx.lvgl_initialized) {
|
||||
err = lvgl_init();
|
||||
if (err) {
|
||||
LOG_ERR("lvgl_init failed (%d)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
lvgl_initialized = true;
|
||||
ctx.lvgl_initialized = true;
|
||||
|
||||
lvgl_lock();
|
||||
ui_main_init(&ui_model, date_text, time_text);
|
||||
ui_main_init(&ctx.ui_model, ctx.date_text, ctx.time_text);
|
||||
lvgl_unlock();
|
||||
}
|
||||
|
||||
@@ -107,39 +136,39 @@ static int module_start(void)
|
||||
return err;
|
||||
}
|
||||
|
||||
err = display_blanking_off(display_dev);
|
||||
err = display_blanking_off(ctx.display_dev);
|
||||
if (err) {
|
||||
LOG_ERR("display_blanking_off failed (%d)", err);
|
||||
(void)backlight_set(false);
|
||||
return err;
|
||||
}
|
||||
|
||||
running = true;
|
||||
LOG_INF("LVGL display started");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void module_pause(void)
|
||||
static int do_stop(void)
|
||||
{
|
||||
if (!running) {
|
||||
return;
|
||||
if (!module_lifecycle_is_running(&ctx.lc)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
(void)display_blanking_on(display_dev);
|
||||
(void)display_blanking_on(ctx.display_dev);
|
||||
(void)backlight_set(false);
|
||||
running = false;
|
||||
LOG_INF("LVGL display paused");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void refresh_ui(void)
|
||||
{
|
||||
if (!lvgl_initialized) {
|
||||
if (!ctx.lvgl_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
lvgl_lock();
|
||||
ui_main_refresh_all(&ui_model, date_text, time_text);
|
||||
ui_main_refresh_all(&ctx.ui_model, ctx.date_text, ctx.time_text);
|
||||
lvgl_unlock();
|
||||
}
|
||||
|
||||
@@ -148,9 +177,9 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
||||
if (is_bat_state_event(aeh)) {
|
||||
const struct bat_state_event *event = cast_bat_state_event(aeh);
|
||||
|
||||
ui_model.battery_level = event->soc;
|
||||
ui_model.charging = event->charging;
|
||||
ui_model.full = event->full;
|
||||
ctx.ui_model.battery_level = event->soc;
|
||||
ctx.ui_model.charging = event->charging;
|
||||
ctx.ui_model.full = event->full;
|
||||
refresh_ui();
|
||||
return false;
|
||||
}
|
||||
@@ -158,7 +187,7 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
||||
if (is_mode_switch_event(aeh)) {
|
||||
const struct mode_switch_event *event = cast_mode_switch_event(aeh);
|
||||
|
||||
ui_model.mode = event->mode;
|
||||
ctx.ui_model.mode = event->mode;
|
||||
refresh_ui();
|
||||
return false;
|
||||
}
|
||||
@@ -166,7 +195,7 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
||||
if (is_hid_led_event(aeh)) {
|
||||
const struct hid_led_event *event = cast_hid_led_event(aeh);
|
||||
|
||||
ui_model.led_mask = event->led_bm;
|
||||
ctx.ui_model.led_mask = event->led_bm;
|
||||
refresh_ui();
|
||||
return false;
|
||||
}
|
||||
@@ -175,9 +204,9 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
||||
const struct theme_rgb_update_event *event =
|
||||
cast_theme_rgb_update_event(aeh);
|
||||
|
||||
ui_model.theme_color = (lv_color_t)LV_COLOR_MAKE(event->theme.r,
|
||||
event->theme.g,
|
||||
event->theme.b);
|
||||
ctx.ui_model.theme_color = (lv_color_t)LV_COLOR_MAKE(event->theme.r,
|
||||
event->theme.g,
|
||||
event->theme.b);
|
||||
refresh_ui();
|
||||
return false;
|
||||
}
|
||||
@@ -185,58 +214,35 @@ static bool app_event_handler(const struct app_event_header *aeh)
|
||||
if (is_datetime_event(aeh)) {
|
||||
const struct datetime_event *event = cast_datetime_event(aeh);
|
||||
|
||||
strncpy(date_text, event->date_text, sizeof(date_text));
|
||||
date_text[sizeof(date_text) - 1] = '\0';
|
||||
strncpy(time_text, event->time_text, sizeof(time_text));
|
||||
time_text[sizeof(time_text) - 1] = '\0';
|
||||
strncpy(ctx.date_text, event->date_text, sizeof(ctx.date_text));
|
||||
ctx.date_text[sizeof(ctx.date_text) - 1] = '\0';
|
||||
strncpy(ctx.time_text, event->time_text, sizeof(ctx.time_text));
|
||||
ctx.time_text[sizeof(ctx.time_text) - 1] = '\0';
|
||||
refresh_ui();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_module_state_event(aeh)) {
|
||||
const struct module_state_event *event = cast_module_state_event(aeh);
|
||||
int err;
|
||||
|
||||
if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
|
||||
if (!initialized) {
|
||||
err = module_init();
|
||||
if (err) {
|
||||
module_set_state(MODULE_STATE_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
err = module_start();
|
||||
if (err) {
|
||||
module_set_state(MODULE_STATE_ERROR);
|
||||
} else {
|
||||
module_set_state(MODULE_STATE_READY);
|
||||
}
|
||||
(void)module_set_lifecycle(&ctx.lc, LC_RUNNING);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_power_down_event(aeh)) {
|
||||
if (initialized) {
|
||||
module_pause();
|
||||
module_set_state(MODULE_STATE_STANDBY);
|
||||
if (module_lifecycle_is_initialized(&ctx.lc)) {
|
||||
(void)module_set_lifecycle(&ctx.lc, LC_STOPPED);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is_wake_up_event(aeh)) {
|
||||
if (initialized) {
|
||||
int err = module_start();
|
||||
|
||||
if (err) {
|
||||
module_set_state(MODULE_STATE_ERROR);
|
||||
} else {
|
||||
module_set_state(MODULE_STATE_READY);
|
||||
}
|
||||
if (module_lifecycle_is_initialized(&ctx.lc)) {
|
||||
(void)module_set_lifecycle(&ctx.lc, LC_RUNNING);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
Reference in New Issue
Block a user