/****************************************************************************** * @file app_arbiter.c * @brief CBR3 模式仲裁器实现(规格书第 12 章:手动 > 定时 > 条件) * @author cyWu <1917507415@qq.com> * @date 2026.08.31 * @version V1.0.0 * @history * - V1.0.0, 2026.08.31, cyWu, 首次发布(P2) * * @note 本模块是唯一模式占用源,运行在 usr_timer_loop(任务上下文)。 * 规则落地(规格书 12 章): * - 手动动作 → manual_intervene():owner=NONE; * 条件引擎感知后作废本轮(RAM,须回安全再满时长才重新触发); * 定时引擎感知后本窗剩余时间不自动抢回(等下一窗开始沿)。 * - 定时窗开始 → timer_take()(定时 > 条件,条件即使满时长也不开); * - 条件触发 → cond_take()(仅 owner!=TIMER 允许;快照只存第一次); * - 两路条件后触发覆盖 → 仍走 cond_take(),快照不变(不回栈)。 ******************************************************************************/ #include "app_arbiter.h" #include "app_mode.h" #include "app_fan.h" #define LOG_TAG_CONST APP #define LOG_TAG "[ARB]" #define LOG_INFO_ENABLE #include "debug.h" /** 仲裁器上下文 */ typedef struct { ArbOwner_t owner; /**< 当前占用者 */ uint8_t snap_valid; /**< 条件快照是否有效 */ uint8_t snap_mode; /**< 快照模式(第一次条件抢权前) */ uint8_t snap_gear; /**< 快照档位 */ } AppArbiterCtx_t; static AppArbiterCtx_t s_arb; /** * @brief 初始化仲裁器 * @return 无 */ void app_arbiter_init(void) { s_arb.owner = ARB_OWNER_NONE; s_arb.snap_valid = 0; s_arb.snap_mode = 0; s_arb.snap_gear = 0; log_info("arbiter init\n"); } /** * @brief 当前模式占用者 * @return ArbOwner_t */ uint8_t app_arbiter_get_owner(void) { return (uint8_t)s_arb.owner; } /** * @brief 手动动作统一入口:释放一切自动化占用 * @note 条件/定时引擎下个 tick 查 owner 感知后各自作废;不恢复快照 * (手动已接管,快照对应的用户状态已过时) * @return 无 */ void app_arbiter_manual_intervene(void) { if (s_arb.owner != ARB_OWNER_NONE) { log_info("manual intervene, owner %d -> none\n", s_arb.owner); } s_arb.owner = ARB_OWNER_NONE; } /** * @brief 条件引擎尝试占用 * @return 1=成功;0=定时占用中(规格书 12:定时 vs 条件 → 定时胜) */ uint8_t app_arbiter_cond_take(void) { if (s_arb.owner == ARB_OWNER_TIMER) { return 0; /* 定时窗内条件不触发 */ } if (!s_arb.snap_valid) { /* 第一次条件抢权前快照用户状态;后覆盖/多次触发不改快照(10.3-6) */ s_arb.snap_mode = app_mode_get_active(); s_arb.snap_gear = app_fan_get_gear(); s_arb.snap_valid = 1; log_info("cond take, snapshot mode=%d gear=%d\n", s_arb.snap_mode, s_arb.snap_gear); } s_arb.owner = ARB_OWNER_COND; return 1; } /** * @brief 条件是否仍在占用 * @return 1=owner==COND */ uint8_t app_arbiter_cond_active(void) { return (s_arb.owner == ARB_OWNER_COND) ? 1 : 0; } /** * @brief 条件自然失效:恢复快照后调用(清 owner 与快照) * @return 无 */ void app_arbiter_cond_release(void) { if (s_arb.owner == ARB_OWNER_COND) { s_arb.owner = ARB_OWNER_NONE; } s_arb.snap_valid = 0; } /** * @brief 取条件快照 * @param mode 输出模式 * @param gear 输出档位 * @return 无 */ void app_arbiter_cond_get_snapshot(uint8_t *mode, uint8_t *gear) { *mode = s_arb.snap_mode; *gear = s_arb.snap_gear; } /** * @brief 条件被手动打断:只清快照(不恢复、不清 owner) * @return 无 */ void app_arbiter_cond_snapshot_clear(void) { s_arb.snap_valid = 0; } /** * @brief 定时窗开始占用(优先级高于条件) * @return 1=成功 */ uint8_t app_arbiter_timer_take(void) { if (s_arb.owner != ARB_OWNER_TIMER) { log_info("timer take\n"); } s_arb.owner = ARB_OWNER_TIMER; return 1; } /** * @brief 定时窗结束释放(调用方负责收口:风扇 0、mode 0) * @return 无 */ void app_arbiter_timer_release(void) { if (s_arb.owner == ARB_OWNER_TIMER) { s_arb.owner = ARB_OWNER_NONE; } }