From 881b36274c49ce951214df21738681e70cef68af Mon Sep 17 00:00:00 2001 From: skiinder Date: Wed, 1 Apr 2026 16:18:52 +0800 Subject: [PATCH] =?UTF-8?q?feat(qdec=5Fmodule):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E7=94=B5=E6=BA=90=E7=AE=A1=E7=90=86=E5=8A=9F=E8=83=BD=E6=94=AF?= =?UTF-8?q?=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 引入pm/device.h和sys/atomic.h头文件以支持电源管理和原子操作 - 添加active原子变量来跟踪模块激活状态 - 实现qdec_module_suspend()和qdec_module_resume()函数处理挂起和唤醒 - 集成power_event事件订阅,在电源下电时挂起模块,在唤醒时恢复模块 - 修改工作调度逻辑,确保仅在活动状态下执行旋转编码器数据处理 - 重构初始化逻辑,使用qdec_reset_state()函数重置内部状态 --- src/modules/qdec_module.c | 96 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 4 deletions(-) diff --git a/src/modules/qdec_module.c b/src/modules/qdec_module.c index 1d5ae1d..0ff4bdc 100644 --- a/src/modules/qdec_module.c +++ b/src/modules/qdec_module.c @@ -3,8 +3,11 @@ #include #include #include +#include +#include #include +#include #define MODULE qdec #include @@ -24,6 +27,7 @@ struct qdec_ctx { const struct device *dev; struct sensor_trigger trigger; struct k_work_delayable emit_work; + atomic_t active; int32_t acc_deg; bool emit_scheduled; }; @@ -36,8 +40,31 @@ static struct qdec_ctx qdec = { }, }; +static void qdec_reset_state(void) +{ + qdec.acc_deg = 0; + qdec.emit_scheduled = false; +} + +static int qdec_device_set_enabled(bool enable) +{ + int err = pm_device_action_run(qdec.dev, + enable ? PM_DEVICE_ACTION_RESUME : + PM_DEVICE_ACTION_SUSPEND); + + if ((err == 0) || (err == -EALREADY)) { + return 0; + } + + return err; +} + static void schedule_emit_work(void) { + if (!atomic_get(&qdec.active)) { + return; + } + if (qdec.emit_scheduled) { return; } @@ -52,6 +79,11 @@ static void qdec_emit_work_handler(struct k_work *work) ARG_UNUSED(work); + if (!atomic_get(&qdec.active)) { + qdec.emit_scheduled = false; + return; + } + qdec.emit_scheduled = false; if ((qdec.acc_deg < QDEC_DEG_PER_STEP_EVENT) && @@ -83,6 +115,10 @@ static void qdec_data_handler(const struct device *dev, ARG_UNUSED(trigger); + if (!atomic_get(&qdec.active)) { + return; + } + err = sensor_sample_fetch_chan(dev, SENSOR_CHAN_ROTATION); if (err) { LOG_ERR("QDEC sample fetch failed: %d", err); @@ -113,8 +149,8 @@ static int qdec_init(void) return -ENODEV; } - qdec.acc_deg = 0; - qdec.emit_scheduled = false; + qdec_reset_state(); + atomic_set(&qdec.active, false); k_work_init_delayable(&qdec.emit_work, qdec_emit_work_handler); err = sensor_trigger_set(qdec.dev, &qdec.trigger, qdec_data_handler); @@ -123,12 +159,52 @@ static int qdec_init(void) return err; } - LOG_INF("QDEC initialized: %d deg/step, <=1 step per %d ms", + LOG_INF("QDEC initialized: %d deg/step, <=1 step per %d ms", QDEC_DEG_PER_STEP_EVENT, QDEC_EVENT_INTERVAL_MS); return 0; } +static void qdec_module_suspend(void) +{ + int err; + + if (!atomic_get(&qdec.active)) { + return; + } + + atomic_set(&qdec.active, false); + (void)k_work_cancel_delayable(&qdec.emit_work); + qdec_reset_state(); + + err = qdec_device_set_enabled(false); + if (err) { + LOG_WRN("QDEC suspend failed: %d", err); + } + + module_set_state(MODULE_STATE_STANDBY); +} + +static void qdec_module_resume(void) +{ + int err; + + if (atomic_get(&qdec.active)) { + return; + } + + err = qdec_device_set_enabled(true); + if (err) { + LOG_ERR("QDEC resume failed: %d", err); + module_set_state(MODULE_STATE_ERROR); + return; + } + + qdec_reset_state(); + atomic_set(&qdec.active, true); + module_set_state(MODULE_STATE_READY); +} + static bool app_event_handler(const struct app_event_header *aeh) { if (is_module_state_event(aeh)) { @@ -140,16 +216,28 @@ static bool app_event_handler(const struct app_event_header *aeh) if (err) { module_set_state(MODULE_STATE_ERROR); } else { - module_set_state(MODULE_STATE_READY); + qdec_module_resume(); } } return false; } + if (is_power_down_event(aeh)) { + qdec_module_suspend(); + return false; + } + + if (is_wake_up_event(aeh)) { + qdec_module_resume(); + return false; + } + __ASSERT_NO_MSG(false); return false; } APP_EVENT_LISTENER(MODULE, app_event_handler); APP_EVENT_SUBSCRIBE(MODULE, module_state_event); +APP_EVENT_SUBSCRIBE_EARLY(MODULE, power_down_event); +APP_EVENT_SUBSCRIBE(MODULE, wake_up_event);