/****************************************************************************** * @file app_arbiter.c * @brief CBR2 喷淋仲裁(规格书第 13 章):手动 > 计划队列 > 联动 * @author cyWu <1917507415@qq.com> * @date 2026.09.09 * @version V1.0.0, 首次发布 * * @note 决策落点(13 章冲突表逐条对应): * 手动开 vs 任何轮 → req_restart/req_start(10.5)+ 作废联动 * 手动停 vs 任何轮 → req_stop + 本模块 intervene(作废联动) * 计划到点 vs 在跑 → 计划入队不插队(app_timer_task 排队) * 计划轮 vs 联动 → 联动查 owner==PLAN / 队列让位(app_linkage) * 联动 vs 空闲 → 联动开/停(app_linkage) * 本模块只做两件事:手动作废转调 + 轮结束边沿分发(计划自毁 / * 出队续跑 / 联动补判),避免收口逻辑散落在调用点。 * 全部接口只在任务上下文调用。 ******************************************************************************/ #include "system/includes.h" #include "app_arbiter.h" #include "app_spray.h" #include "app_linkage.h" #include "app_timer_task.h" #define LOG_TAG_CONST APP #define LOG_TAG "[ARB]" #define LOG_INFO_ENABLE #include "debug.h" /** * @brief 初始化仲裁器 * @return 无 */ void app_arbiter_init(void) { log_info("arbiter init\n"); } /** * @brief 消费轮结束事件并收口(500ms 任务上下文) * @return 无 */ void app_arbiter_poll(void) { uint8_t owner; uint8_t slot; while (app_spray_pop_done(&owner, &slot)) { app_arbiter_on_round_done(owner, slot); } } /** * @brief 手动介入:作废联动轮(RAM 标志,不写 VM;规格书 13 章) * @return 无 */ void app_arbiter_manual_intervene(void) { app_linkage_void(); } /** * @brief 轮结束边沿收口(规格书 12.4 / 13 章) * @param owner 结束轮来源 * @param slot 结束轮槽位(owner==PLAN 时有效) * @return 无 */ void app_arbiter_on_round_done(uint8_t owner, uint8_t slot) { if (owner == (uint8_t)APP_SPRAY_OWNER_PLAN) { /* 单次计划:正常跑完或被手动停都清该条使能(12.3-4 / 10.4) */ app_timer_on_plan_done(slot); } /* 计划队列优先于联动:队列非空立刻续跑(不插队当前轮的承诺由 * "只在空闲 kick"保证);否则计划/手动/联动轮结束后补判联动 */ if (app_timer_has_pending()) { app_timer_kick(); } else { app_linkage_reeval(); } }