feat(mode_switch): 添加无效模式枚举值并更新事件处理

添加 MODE_SWITCH_INVALID 枚举值到 mode_switch_mode 中,
用于表示无效的模式状态。同时更新相关的事件处理逻辑,
确保在模式切换时能够正确处理无效模式的情况。

refactor(mode_policy): 简化模块上下文结构并优化模式策略

将模块上下文中的 ble_adv_suspended 和 usb_enabled 标志位
替换为 active_mode 枚举值,简化了数据结构。重新设计了
模式策略应用逻辑,使其更清晰易懂,并改进了BLE和USB设备
的启用/暂停控制流程。

refactor(usb_device): 重构USB设备生命周期管理

移除了 USB_STACK_DISABLED 状态,简化了USB栈的状态管理。
改进了USB设备的启动和停止逻辑,更好地与模块生命周期
集成。现在USB状态事件仅在模块初始化后提交,避免了
不必要的事件发布。

feat(logging): 增加详细的状态转换日志记录

为BLE NUS模块添加了业务状态转换的日志记录功能,
增加了详细的错误和警告日志,包括生命周期状态、
业务状态和连接信息,便于调试和问题排查。

refactor(mode_switch): 优化模式检测和报告机制

修改了模式切换采样的判断逻辑,移除了force_report和
mode_valid标志位,改用last_mode状态来决定是否提交
模式切换事件,使代码更简洁且易于理解。
This commit is contained in:
2026-04-18 11:27:48 +08:00
parent ceebaaa600
commit caf8d5acc6
8 changed files with 292 additions and 159 deletions

View File

@@ -9,6 +9,7 @@ extern "C" {
#endif
enum mode_switch_mode {
MODE_SWITCH_INVALID,
MODE_SWITCH_USB,
MODE_SWITCH_24G,
MODE_SWITCH_BLE,

View File

@@ -58,6 +58,52 @@ static struct ble_nus_ctx ctx = {
.active_conn = NULL,
};
static const char *lifecycle_name(enum module_lifecycle state)
{
switch (state) {
case LC_UNINIT:
return "UNINIT";
case LC_RUNNING:
return "RUNNING";
case LC_STOPPED:
return "STOPPED";
case LC_SUSPENDED:
return "SUSPENDED";
case LC_ERROR:
return "ERROR";
default:
return "?";
}
}
static const char *business_state_name(enum ble_nus_business_state state)
{
switch (state) {
case BLE_NUS_STACK_OFFLINE:
return "STACK_OFFLINE";
case BLE_NUS_IDLE:
return "IDLE";
case BLE_NUS_WAIT_NOTIFY:
return "WAIT_NOTIFY";
case BLE_NUS_SESSION_READY:
return "SESSION_READY";
default:
return "?";
}
}
static const char *link_state_name(enum proto_transport_link_state state)
{
switch (state) {
case PROTO_TRANSPORT_LINK_DOWN:
return "DOWN";
case PROTO_TRANSPORT_LINK_READY:
return "READY";
default:
return "?";
}
}
static bool lifecycle_is_ready(void)
{
return module_lifecycle_is_running(&ctx.lc);
@@ -96,6 +142,9 @@ static void business_state_set(enum ble_nus_business_state new_state)
return;
}
LOG_INF("BLE NUS business %s -> %s",
business_state_name(ctx.business),
business_state_name(new_state));
ctx.business = new_state;
state_reconcile(old_lifecycle, old_business);
}
@@ -136,6 +185,11 @@ static void received(struct bt_conn *conn, const void *data, uint16_t len,
if (!lifecycle_is_ready() || (ctx.business == BLE_NUS_STACK_OFFLINE) ||
(conn != ctx.active_conn)) {
LOG_WRN("BLE NUS drop RX len:%u lc:%s business:%s active_conn:%p conn:%p link:%s",
len, lifecycle_name(ctx.lc.state),
business_state_name(ctx.business),
(void *)ctx.active_conn, (void *)conn,
link_state_name(transport_link_state_get()));
return;
}
@@ -190,6 +244,9 @@ static int apply_lifecycle(enum module_lifecycle target)
if (!err) {
state_reconcile(old_lifecycle, old_business);
} else {
LOG_WRN("BLE NUS lifecycle change failed target:%s err:%d",
lifecycle_name(target), err);
}
return err;

View File

@@ -7,6 +7,8 @@
static const char *mode_name(enum mode_switch_mode mode)
{
switch (mode) {
case MODE_SWITCH_INVALID:
return "INVALID";
case MODE_SWITCH_USB:
return "USB";
case MODE_SWITCH_24G:

View File

@@ -5,6 +5,8 @@
static const char *mode_name(enum mode_switch_mode mode)
{
switch (mode) {
case MODE_SWITCH_INVALID:
return "INVALID";
case MODE_SWITCH_USB:
return "USB";
case MODE_SWITCH_24G:

View File

@@ -16,8 +16,7 @@ LOG_MODULE_REGISTER(MODULE, LOG_LEVEL_INF);
struct mode_policy_module_ctx {
struct module_lifecycle_ctx lc;
bool ble_adv_suspended;
bool usb_enabled;
enum mode_switch_mode active_mode;
};
static int do_init(void);
@@ -41,69 +40,115 @@ static struct mode_policy_module_ctx ctx = {
.cfg = &lifecycle_cfg,
.ops = &lifecycle_ops,
},
.ble_adv_suspended = true,
.active_mode = MODE_SWITCH_USB,
};
static void broadcast_ble_adv_req(bool suspend)
static void mode_policy_set_ble(bool enable)
{
if (suspend) {
struct module_suspend_req_event *event = new_module_suspend_req_event();
event->sink_module_id = MODULE_ID(ble_adv);
event->src_module_id = MODULE_ID(MODULE);
APP_EVENT_SUBMIT(event);
} else {
if (enable) {
struct module_resume_req_event *event = new_module_resume_req_event();
event->sink_module_id = MODULE_ID(ble_adv);
event->src_module_id = MODULE_ID(MODULE);
APP_EVENT_SUBMIT(event);
} else {
struct module_suspend_req_event *event = new_module_suspend_req_event();
event->sink_module_id = MODULE_ID(ble_adv);
event->src_module_id = MODULE_ID(MODULE);
APP_EVENT_SUBMIT(event);
}
}
static void apply_mode_policy(enum mode_switch_mode mode)
static void mode_policy_set_usb(bool enable)
{
bool should_suspend_ble_adv = (mode != MODE_SWITCH_BLE);
bool should_enable_usb = (mode == MODE_SWITCH_USB);
if (should_suspend_ble_adv != ctx.ble_adv_suspended) {
ctx.ble_adv_suspended = should_suspend_ble_adv;
broadcast_ble_adv_req(should_suspend_ble_adv);
}
if (should_enable_usb != ctx.usb_enabled) {
ctx.usb_enabled = should_enable_usb;
if (ctx.usb_enabled) {
struct module_resume_req_event *event =
new_module_resume_req_event();
if (enable) {
struct module_resume_req_event *event = new_module_resume_req_event();
event->sink_module_id = MODULE_ID(usb_device_module);
event->src_module_id = MODULE_ID(MODULE);
APP_EVENT_SUBMIT(event);
} else {
struct module_suspend_req_event *event =
new_module_suspend_req_event();
struct module_suspend_req_event *event = new_module_suspend_req_event();
event->sink_module_id = MODULE_ID(usb_device_module);
event->src_module_id = MODULE_ID(MODULE);
APP_EVENT_SUBMIT(event);
}
}
static void apply_active_mode(void)
{
switch (ctx.active_mode) {
case MODE_SWITCH_BLE:
mode_policy_set_ble(true);
mode_policy_set_usb(false);
break;
case MODE_SWITCH_USB:
mode_policy_set_ble(false);
mode_policy_set_usb(true);
break;
case MODE_SWITCH_24G:
mode_policy_set_ble(false);
mode_policy_set_usb(false);
break;
default:
break;
}
}
static void apply_ble_mode_policy(void)
{
switch (ctx.active_mode) {
case MODE_SWITCH_BLE:
mode_policy_set_ble(true);
break;
case MODE_SWITCH_USB:
mode_policy_set_ble(false);
break;
case MODE_SWITCH_24G:
mode_policy_set_ble(false);
break;
default:
break;
}
}
static void apply_usb_mode_policy(void)
{
switch (ctx.active_mode) {
case MODE_SWITCH_BLE:
mode_policy_set_usb(false);
break;
case MODE_SWITCH_USB:
mode_policy_set_usb(true);
break;
case MODE_SWITCH_24G:
mode_policy_set_usb(false);
break;
default:
break;
}
}
static int do_init(void)
{
ctx.ble_adv_suspended = true;
ctx.usb_enabled = false;
ctx.active_mode = MODE_SWITCH_USB;
return 0;
}
static int do_start(void)
{
if (module_lifecycle_is_running(&ctx.lc)) {
return 0;
}
apply_active_mode();
return 0;
}
@@ -118,7 +163,8 @@ static bool app_event_handler(const struct app_event_header *aeh)
const struct mode_switch_event *event = cast_mode_switch_event(aeh);
if (module_lifecycle_is_running(&ctx.lc)) {
apply_mode_policy(event->mode);
ctx.active_mode = event->mode;
apply_active_mode();
}
return false;
@@ -129,6 +175,21 @@ static bool app_event_handler(const struct app_event_header *aeh)
if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
(void)module_set_lifecycle(&ctx.lc, LC_RUNNING);
return false;
}
if (check_state(event, MODULE_ID(ble_adv), MODULE_STATE_READY)) {
if (module_lifecycle_is_running(&ctx.lc)) {
apply_ble_mode_policy();
}
return false;
}
if (check_state(event, MODULE_ID(usb_device_module),
MODULE_STATE_READY)) {
if (module_lifecycle_is_running(&ctx.lc)) {
apply_usb_mode_policy();
}
}
return false;

View File

@@ -31,8 +31,6 @@ struct mode_switch_module_ctx {
struct module_lifecycle_ctx lc;
const struct device *mode_switch_adc_dev;
struct k_work_delayable mode_switch_sample_work;
bool force_report;
bool mode_valid;
enum mode_switch_mode last_mode;
};
@@ -115,12 +113,10 @@ static void mode_switch_sample_fn(struct k_work *work)
uint16_t sample_mv = (uint16_t)((voltage.val1 * 1000) + (voltage.val2 / 1000));
enum mode_switch_mode mode = detect_mode(sample_mv);
if (ctx.force_report || !ctx.mode_valid || (mode != ctx.last_mode)) {
if ((ctx.last_mode == MODE_SWITCH_INVALID) || (mode != ctx.last_mode)) {
submit_mode_switch_event(mode, sample_mv);
ctx.last_mode = mode;
ctx.mode_valid = true;
ctx.force_report = false;
}
reschedule:
@@ -138,8 +134,7 @@ static int do_init(void)
}
k_work_init_delayable(&ctx.mode_switch_sample_work, mode_switch_sample_fn);
ctx.mode_valid = false;
ctx.force_report = false;
ctx.last_mode = MODE_SWITCH_INVALID;
return 0;
}
@@ -157,7 +152,6 @@ static int do_start(void)
return err;
}
ctx.force_report = true;
k_work_reschedule(&ctx.mode_switch_sample_work, K_NO_WAIT);
return 0;
@@ -182,6 +176,15 @@ static bool app_event_handler(const struct app_event_header *aeh)
if (check_state(event, MODULE_ID(main), MODULE_STATE_READY)) {
(void)module_set_lifecycle(&ctx.lc, LC_RUNNING);
return false;
}
if (check_state(event, MODULE_ID(mode_policy_module),
MODULE_STATE_READY)) {
if (ctx.last_mode != MODE_SWITCH_INVALID) {
submit_mode_switch_event(ctx.last_mode, 0U);
}
return false;
}
return false;

View File

@@ -75,6 +75,50 @@ static struct protocol_module_ctx ctx = {
#define session_state ctx.session_state
static const char *lifecycle_name(enum module_lifecycle state)
{
switch (state) {
case LC_UNINIT:
return "UNINIT";
case LC_RUNNING:
return "RUNNING";
case LC_STOPPED:
return "STOPPED";
case LC_SUSPENDED:
return "SUSPENDED";
case LC_ERROR:
return "ERROR";
default:
return "?";
}
}
static const char *proto_session_name(enum proto_session_state state)
{
switch (state) {
case PROTO_SESSION_DOWN:
return "DOWN";
case PROTO_SESSION_WAIT_HELLO:
return "WAIT_HELLO";
case PROTO_SESSION_ACTIVE:
return "ACTIVE";
default:
return "?";
}
}
static const char *proto_transport_name(enum proto_transport transport)
{
switch (transport) {
case PROTO_TRANSPORT_USB_CDC:
return "usb_cdc";
case PROTO_TRANSPORT_BLE_NUS:
return "ble_nus";
default:
return "?";
}
}
static int decode_body(const uint8_t *payload, size_t payload_len,
CdcPacketBody *body)
{
@@ -230,6 +274,9 @@ int protocol_module_process_message(enum proto_transport transport,
}
if (!module_lifecycle_is_running(&ctx.lc)) {
LOG_WRN("Reject proto msg transport:%s len:%u lc:%s",
proto_transport_name(transport), (uint32_t)req_payload_len,
lifecycle_name(ctx.lc.state));
return -EAGAIN;
}
@@ -241,6 +288,10 @@ int protocol_module_process_message(enum proto_transport transport,
switch (body.which_body) {
case CdcPacketBody_hello_req_tag:
if (session_state[transport] == PROTO_SESSION_DOWN) {
LOG_WRN("Reject HelloReq transport:%s session:%s lc:%s",
proto_transport_name(transport),
proto_session_name(session_state[transport]),
lifecycle_name(ctx.lc.state));
return -EAGAIN;
}
@@ -354,7 +405,11 @@ static bool handle_proto_rx_event(const struct proto_rx_event *event)
&rsp_payload_len);
if (err) {
if (err != -ENOTSUP) {
LOG_WRN("Protocol processing failed (%d)", err);
LOG_WRN("Protocol processing failed (%d) transport:%s session:%s lc:%s len:%u",
err, proto_transport_name(event->transport),
proto_session_name(session_state[event->transport]),
lifecycle_name(ctx.lc.state),
(uint32_t)event->dyndata.size);
}
return false;

View File

@@ -43,7 +43,6 @@ static const char *const class_blocklist[] = {
enum usb_stack_state {
USB_STACK_UNINITIALIZED = 0,
USB_STACK_DISABLED,
USB_STACK_READY,
USB_STACK_ENABLED,
};
@@ -91,8 +90,8 @@ static struct usb_owner_ctx usb_ctx = {
static inline enum usb_state usb_public_state_get(void)
{
if ((usb_ctx.stack == USB_STACK_UNINITIALIZED) ||
(usb_ctx.stack == USB_STACK_DISABLED)) {
if (!module_lifecycle_is_running(&usb_ctx.lc) ||
(usb_ctx.stack == USB_STACK_UNINITIALIZED)) {
return USB_STATE_DISABLED;
}
@@ -110,11 +109,6 @@ static inline enum usb_state usb_public_state_get(void)
}
}
static inline bool usb_stack_was_initialized(void)
{
return (usb_ctx.stack != USB_STACK_UNINITIALIZED);
}
static inline void usb_bus_set(enum usb_bus_state state)
{
if (usb_ctx.bus == state) {
@@ -122,7 +116,10 @@ static inline void usb_bus_set(enum usb_bus_state state)
}
usb_ctx.bus = state;
if (module_lifecycle_is_initialized(&usb_ctx.lc)) {
submit_usb_state(usb_public_state_get());
}
}
static void update_power_manager_restriction(bool vbus_present)
@@ -222,31 +219,30 @@ static void usbd_msg_cb(struct usbd_context *const usbd_ctx,
switch (msg->type) {
case USBD_MSG_VBUS_READY:
update_power_manager_restriction(true);
usb_bus_set(USB_BUS_POWERED);
if (usb_ctx.stack == USB_STACK_READY) {
int err = usbd_enable(&blinky_usbd);
if (module_lifecycle_is_running(&usb_ctx.lc) &&
(usb_ctx.stack == USB_STACK_READY)) {
int err = do_start();
if (err) {
LOG_ERR("usbd_enable failed (%d)", err);
} else {
usb_ctx.stack = USB_STACK_ENABLED;
usb_bus_set(USB_BUS_POWERED);
LOG_ERR("USB start on VBUS ready failed (%d)", err);
}
}
break;
case USBD_MSG_VBUS_REMOVED:
update_power_manager_restriction(false);
if (usb_ctx.stack == USB_STACK_ENABLED) {
int err = usbd_disable(&blinky_usbd);
int err = do_stop();
if (err) {
LOG_ERR("usbd_disable failed (%d)", err);
LOG_ERR("USB stop on VBUS removed failed (%d)", err);
}
} else {
update_power_manager_restriction(false);
}
if (usb_ctx.stack != USB_STACK_DISABLED) {
if (usb_ctx.stack != USB_STACK_UNINITIALIZED) {
usb_ctx.stack = USB_STACK_READY;
}
@@ -278,16 +274,13 @@ static void usbd_msg_cb(struct usbd_context *const usbd_ctx,
}
}
static int usb_stack_init_once(void)
static int do_init(void)
{
int err;
if (usb_stack_was_initialized()) {
if (usb_ctx.stack == USB_STACK_DISABLED) {
usb_ctx.stack = USB_STACK_READY;
}
return 0;
}
usb_ctx.stack = USB_STACK_UNINITIALIZED;
usb_ctx.bus = USB_BUS_DISCONNECTED;
update_power_manager_restriction(false);
STRUCT_SECTION_FOREACH(usb_function_hook, hook) {
if (hook->pre_stack_init == NULL) {
@@ -321,6 +314,17 @@ static int usb_stack_init_once(void)
usb_ctx.stack = USB_STACK_READY;
return 0;
}
static int do_start(void)
{
int err;
if (usb_ctx.stack == USB_STACK_ENABLED) {
return 0;
}
if (!usbd_can_detect_vbus(&blinky_usbd)) {
err = usbd_enable(&blinky_usbd);
if (err) {
@@ -329,24 +333,15 @@ static int usb_stack_init_once(void)
}
usb_ctx.stack = USB_STACK_ENABLED;
usb_bus_set(USB_BUS_POWERED);
}
usb_ctx.bus = USB_BUS_POWERED;
update_power_manager_restriction(true);
return 0;
}
if (usb_ctx.bus == USB_BUS_DISCONNECTED) {
return 0;
}
static int usb_stack_enable_if_needed(void)
{
int err;
err = usb_stack_init_once();
if (err) {
return err;
}
if ((usb_ctx.stack == USB_STACK_READY) &&
(!usbd_can_detect_vbus(&blinky_usbd) ||
(usb_ctx.bus != USB_BUS_DISCONNECTED))) {
err = usbd_enable(&blinky_usbd);
if (err) {
LOG_ERR("usbd_enable failed (%d)", err);
@@ -354,64 +349,24 @@ static int usb_stack_enable_if_needed(void)
}
usb_ctx.stack = USB_STACK_ENABLED;
if (usb_ctx.bus == USB_BUS_DISCONNECTED) {
usb_bus_set(USB_BUS_POWERED);
} else {
submit_usb_state(usb_public_state_get());
}
return 0;
}
submit_usb_state(usb_public_state_get());
update_power_manager_restriction(true);
return 0;
}
static int usb_stack_disable_if_needed(void)
static int do_stop(void)
{
if (usb_ctx.stack == USB_STACK_ENABLED) {
int err = usbd_disable(&blinky_usbd);
int err;
if (usb_ctx.stack == USB_STACK_ENABLED) {
err = usbd_disable(&blinky_usbd);
if (err) {
LOG_ERR("usbd_disable failed (%d)", err);
return err;
}
}
usb_ctx.stack = USB_STACK_DISABLED;
usb_ctx.stack = USB_STACK_READY;
update_power_manager_restriction(false);
submit_usb_state(usb_public_state_get());
return 0;
}
static int do_init(void)
{
usb_ctx.stack = USB_STACK_UNINITIALIZED;
usb_ctx.bus = USB_BUS_DISCONNECTED;
update_power_manager_restriction(false);
return 0;
}
static int do_start(void)
{
if (module_lifecycle_is_running(&usb_ctx.lc)) {
return 0;
}
submit_usb_state(usb_public_state_get());
return 0;
}
static int do_stop(void)
{
if (!module_lifecycle_is_running(&usb_ctx.lc)) {
return 0;
}
submit_usb_state(usb_public_state_get());
return 0;
}
@@ -421,7 +376,9 @@ static bool handle_module_state_event(const struct module_state_event *event)
return false;
}
(void)module_set_lifecycle(&usb_ctx.lc, LC_RUNNING);
if (module_set_lifecycle(&usb_ctx.lc, LC_RUNNING) == 0) {
submit_usb_state(usb_public_state_get());
}
return false;
}
@@ -434,14 +391,10 @@ static bool handle_module_suspend_req_event(
return false;
}
int err = usb_stack_disable_if_needed();
if (err) {
LOG_WRN("USB suspend request failed (%d)", err);
return false;
if (module_set_lifecycle(&usb_ctx.lc, LC_SUSPENDED) == 0) {
submit_usb_state(usb_public_state_get());
}
(void)module_set_lifecycle(&usb_ctx.lc, LC_SUSPENDED);
return false;
}
@@ -453,15 +406,10 @@ static bool handle_module_resume_req_event(
return false;
}
int err = usb_stack_enable_if_needed();
if (err) {
LOG_WRN("USB resume request failed (%d)", err);
return false;
if (module_set_lifecycle(&usb_ctx.lc, LC_RUNNING) == 0) {
submit_usb_state(usb_public_state_get());
}
(void)module_set_lifecycle(&usb_ctx.lc, LC_RUNNING);
return false;
}
@@ -483,7 +431,9 @@ static bool app_event_handler(const struct app_event_header *aeh)
if (is_power_down_event(aeh)) {
if (module_lifecycle_is_initialized(&usb_ctx.lc)) {
(void)module_set_lifecycle(&usb_ctx.lc, LC_STOPPED);
if (module_set_lifecycle(&usb_ctx.lc, LC_STOPPED) == 0) {
submit_usb_state(usb_public_state_get());
}
}
return false;
@@ -491,7 +441,9 @@ static bool app_event_handler(const struct app_event_header *aeh)
if (is_wake_up_event(aeh)) {
if (module_lifecycle_is_initialized(&usb_ctx.lc)) {
(void)module_set_lifecycle(&usb_ctx.lc, LC_RUNNING);
if (module_set_lifecycle(&usb_ctx.lc, LC_RUNNING) == 0) {
submit_usb_state(usb_public_state_get());
}
}
return false;