#include "hsf.h" #include "hfconfig.h" #if defined(CONFIG_PWM_SUPPORT_LPM) #include "pm_veto.h" #endif #include "pinctrl.h" #include "gpio.h" #include "pinctrl.h" #include "pwm.h" #include "timer.h" #include "soc_osal.h" #include "systick.h" // #include "tcxo.h" #include "spotlight.h" #include "factory_test.h" // 函数前向声明 static void init_timer_system(void); static void init_fade_ctx(void); static void init_breath_ctx(void); static void stop_fade_task(void); static void stop_breath_task(void); static void stop_breath_timer(void); static void stop_spotlight_main_task(void); static void check_net_cfg_timeout(void); static void check_net_cfg_power_on_keep_time(void); static void set_light2breathtimeout(void); static void set_light2net_cfg_done(void); static void start_breath_timer(void); static void report_switch_status(void); void calculate_pwm_duty(device_control_t* pdevice_control); void close_light(void); // 定义上报函数类型 typedef void (*report_func_t)(void); static void start_report_task(uint32_t report_mask); static void report_fade_complete_status(void); static uint8_t calculate_checksum(const device_data_t* data); static bool write_device_data_to_addr(uint32_t addr, const device_data_t* data);; static void report_device_online_status(void); // 状态上报任务相关变量 #define REPORT_TASK_PRIO 80 #define REPORT_TASK_STACK_SIZE 0x1000 static osal_task *report_task_handle = NULL; static bool report_task_running = false; // 添加任务运行状态标志 // 新增:全局上报掩码变量和条件变量 static uint32_t g_report_mask = 0; static osal_semaphore report_sem; // 条件变量,用于唤醒report task bool g_reset_factory_flag = false; // 灯渐变任务相关定义 #define FADE_TASK_PRIO 80 #define FADE_TASK_STACK_SIZE 0x1000 // 呼吸灯任务相关定义 #define BREATH_TASK_PRIO 80 #define BREATH_TASK_STACK_SIZE 0x1000 static uint32_t pwm_period_cnt = 0; // PWM周期 40us static uint8_t channel_id_cw = 0; // 冷白LED通道ID static uint8_t channel_id_ww = 0; // 暖白LED通道ID // PWM参数更新调试标志引脚是否已初始化 static bool g_pwm_update_flag_inited = false; void save_device_data(void); void read_device_data(void); void req_save_device_data(void); static void stop_breath_timer(void); device_control_t g_device_control = DEFAULT_DEVICE_DATA; // 配网状态定义 typedef enum { NET_CFG_IDLE = 0, // 空闲状态 NET_CFG_BREATHING, // 呼吸灯状态,配网中 NET_CFG_TIMEOUT, // 超时状态 } net_cfg_state_e; // 配网状态相关变量 static net_cfg_state_e g_net_breath_state = NET_CFG_IDLE; // 配网状态 static uint64_t g_net_cfg_start_time = 0; // 配网开始时间 // 保存任务相关变量 static osal_task *save_task_handle = NULL; static bool save_task_running = false; static osal_semaphore save_data_sem; // 打印频率限制相关定义 #define PRINT_INTERVAL_MS 1000 // 最小打印间隔(ms) typedef struct { uint64_t last_print_time; // 上次打印时间 const char *prefix; // 打印前缀 } print_limiter_t; #define FADE_CTRL_DATA_SIZE(fade_ctx) ((fade_ctx).member_barrier - (uint8_t*)&(fade_ctx)) // 渐变控制相关变量 static struct fade_ctx_t { struct{ // 渐变控制参数 int32_t target_brightness; int32_t target_cct; int32_t current_brightness; int32_t current_cct; int32_t step_brightness; int32_t step_cct; bool is_fading; bool fade_completed; bool is_closing_fade; // 标记是否为关灯渐变 uint16_t fade_time; //s uint32_t smooth_time_us; // 渐变总时长(us) uint32_t update_interval; // 更新间隔(us) volatile bool timer_active; // 渐变定时器是否允许自重启(竞态保护) // 打印限制器 print_limiter_t print_limiter; }; uint8_t member_barrier[0]; // 用于计算前面成员变量大小 // 任务相关 osal_task *task_handle; bool task_running; osal_semaphore sem; timer_handle_t timer_handle; } fade_ctx = {0}; // 呼吸灯控制相关变量 static struct { // 呼吸灯控制参数 int32_t duty; int32_t step; uint32_t update_interval; // 更新间隔(us) bool is_initial_breath; // 是否是初始3秒呼吸 // 任务相关 osal_task *task_handle; bool task_running; osal_semaphore sem; timer_handle_t timer_handle; uint32_t start_time_ms; uint32_t breath_cnt; // 打印限制器 print_limiter_t print_limiter; } breath_ctx = {0}; print_limiter_t pwm_limiter = { .last_print_time = 0, .prefix = "[pwm]", }; // 定时器初始化标志 static bool timer_initialized = false; // 初始化定时器系统 static void init_timer_system(void) { if (!timer_initialized) { uapi_timer_init(); int ret = uapi_timer_adapter(TIMER_INDEX_1, TIMER_1_IRQN, 1); if (ret != 0) { e_printf("定时器适配器初始化失败\r\n"); return; } timer_initialized = true; } } // 初始化打印限制器 static void init_print_limiter(print_limiter_t *limiter, const char *prefix) { limiter->last_print_time = 0; limiter->prefix = prefix; } // 带频率限制的打印函数 static bool should_print(print_limiter_t *limiter) { uint64_t current_time = uapi_systick_get_ms(); if (current_time - limiter->last_print_time >= PRINT_INTERVAL_MS) { limiter->last_print_time = current_time; return true; } return false; } // 渐变灯任务函数 static void *fade_task(const char *arg) { unused(arg); e_printf("[fade_task] Task started\r\n"); device_control_t device_control = {}; while (fade_ctx.task_running) { // 等待渐变信号 if (osal_sem_down_timeout(&fade_ctx.sem, 100*1000) != OSAL_SUCCESS) { continue; } if (!fade_ctx.is_fading) { continue; } // 使用打印限制器控制打印频率 if (should_print(&fade_ctx.print_limiter)) { e_printf("%s Brightness: curr:%d, target:%d, step:%d, cct:curr:%d, target:%d, step:%d, closing:%d\r\n", fade_ctx.print_limiter.prefix, fade_ctx.current_brightness, fade_ctx.target_brightness, fade_ctx.step_brightness, fade_ctx.current_cct, fade_ctx.target_cct, fade_ctx.step_cct, fade_ctx.is_closing_fade); } // 检查是否达到目标值 bool brightness_reached = (fade_ctx.step_brightness > 0) ? (fade_ctx.current_brightness >= fade_ctx.target_brightness) : (fade_ctx.current_brightness <= fade_ctx.target_brightness); bool cct_reached = (fade_ctx.step_cct > 0) ? (fade_ctx.current_cct >= fade_ctx.target_cct) : (fade_ctx.current_cct <= fade_ctx.target_cct); // 更新当前值 if (!brightness_reached) { fade_ctx.current_brightness += fade_ctx.step_brightness; } if (!cct_reached) { fade_ctx.current_cct += fade_ctx.step_cct; } // 达到目标,停止渐变 if (brightness_reached && cct_reached) { e_printf("[fade_task] Fade completed, Final brightness: %d, CCT: %d, closing_fade: %d\r\n", fade_ctx.target_brightness, fade_ctx.target_cct, fade_ctx.is_closing_fade); fade_ctx.is_fading = false; fade_ctx.fade_completed = true; fade_ctx.current_brightness = fade_ctx.target_brightness; fade_ctx.current_cct = fade_ctx.target_cct; fade_ctx.timer_active = false; // 防止回调自重启 uapi_timer_stop(fade_ctx.timer_handle); } BRIGHTNESS_LITME_RANGE(fade_ctx.current_brightness); CCT_LITME_RANGE(fade_ctx.current_cct); // 更新PWM输出 device_control.brightness_local = fade_ctx.current_brightness; device_control.cct_local = fade_ctx.current_cct; calculate_pwm_duty(&device_control); // 根据is_closing_fade标志判断PWM开关状态 bool effective_on_state = fade_ctx.is_closing_fade ? true : g_device_control.on; update_pwm_output(effective_on_state, device_control.duty_cw, device_control.duty_ww); if (fade_ctx.fade_completed) { fade_ctx.fade_completed = false; if (fade_ctx.is_closing_fade) { // 关灯渐变完成:不更新g_device_control.brightness_local,保持原有目标亮度 fade_ctx.is_closing_fade = false; update_pwm_output(false, 0, 0); g_device_control.duty_cw = 0; g_device_control.duty_ww = 0; // 注意:这里不更新 g_device_control.brightness_local,保持之前的亮度值 e_printf("[fade_task] Close light fade completed, PWM turned off, brightness_local preserved: %d\r\n", g_device_control.brightness_local); } else { // 正常渐变完成:正常更新所有值 g_device_control.duty_ww = device_control.duty_ww; g_device_control.duty_cw = device_control.duty_cw; g_device_control.brightness_local = fade_ctx.current_brightness; if (g_device_control.colourMode == COLOUR_MODE_DUAL) { g_device_control.cct_local = fade_ctx.current_cct; } } e_printf("[fade_task] Status report: local brightness=%d, CCT=%d\r\n", g_device_control.brightness_local, g_device_control.cct_local); // 启动状态上报任务,使用渐变完成状态上报函数 start_report_task(REPORT_BRIGHTNESS | REPORT_CCT); req_save_device_data(); } } e_printf("[fade_task] Task exited\r\n"); return NULL; } // 呼吸灯任务函数 static void *breath_task(const char *arg) { unused(arg); e_printf("[breath_task] Task started\r\n"); while (breath_ctx.task_running) { // 等待呼吸信号 if (osal_sem_down_timeout(&breath_ctx.sem, 100*1000) != OSAL_SUCCESS) { continue; } if (g_net_breath_state != NET_CFG_BREATHING) { continue; } // 检查是否超过呼吸灯持续时间 uint32_t current_time = uapi_systick_get_ms(); uint32_t elapsed_time = current_time - g_net_cfg_start_time; if (elapsed_time >= NET_CFG_BREATH_DURATION) { set_light2breathtimeout(); stop_breath_timer(); continue; } // 检查是否需要改变方向 if (breath_ctx.duty >= BRIGHTNESS_LOCAL_MAX) { breath_ctx.duty = BRIGHTNESS_LOCAL_MAX; breath_ctx.step = -1 * breath_ctx.step; e_printf("%s breathing %d, down %dms\n", breath_ctx.print_limiter.prefix, breath_ctx.breath_cnt, uapi_systick_get_ms() - breath_ctx.start_time_ms); } else if (breath_ctx.duty <= 0) { breath_ctx.duty = 0; breath_ctx.step = -1 * breath_ctx.step; e_printf("%s breathing %d, up %dms\n", breath_ctx.print_limiter.prefix, breath_ctx.breath_cnt, uapi_systick_get_ms() - breath_ctx.start_time_ms); } // 更新亮度 breath_ctx.duty += breath_ctx.step; int32_t brightness_pwm = breath_ctx.duty; // 设置黄白灯交替呼吸 g_device_control.duty_ww = brightness_pwm; g_device_control.duty_cw = PWM_DUTY_RATIO_MAX - brightness_pwm; update_pwm_output(g_device_control.on, g_device_control.duty_cw, g_device_control.duty_ww); } e_printf("[breath_task] Task exited\r\n"); return NULL; } // 渐变定时器回调函数 static void fade_timer_callback(uintptr_t data) { // 若已被取消或未处于渐变态,禁止回调重入自重启,避免双定时器抖动 if (!fade_ctx.timer_active || !fade_ctx.is_fading) { return; } osal_sem_up(&fade_ctx.sem); // 唤醒渐变任务 fade_task uapi_timer_start(fade_ctx.timer_handle, fade_ctx.update_interval, fade_timer_callback, 0); } // 呼吸灯定时器回调函数 static void breath_timer_callback(uintptr_t data) { osal_sem_up(&breath_ctx.sem); uapi_timer_start(breath_ctx.timer_handle, breath_ctx.update_interval, breath_timer_callback, 0); } // 初始化渐变控制 static void init_fade_ctx(void) { init_timer_system(); int ret = uapi_timer_create(TIMER_INDEX_1, &fade_ctx.timer_handle); if (ret != 0) { e_printf("渐变定时器创建失败\r\n"); } // 初始化信号量 if (osal_sem_init(&fade_ctx.sem, 0) != OSAL_SUCCESS) { e_printf("[init_fade_ctx] Failed to init semaphore\n"); return; } // 初始化打印限制器 init_print_limiter(&fade_ctx.print_limiter, "[fade_task]"); // 🔧 智能初始化:根据设备状态决定初始值 if (g_device_control.read_done) { // 数据已读取完成(正常启动) if (g_device_control.on) { // 开机渐变:从0开始渐变到目标亮度 fade_ctx.current_brightness = 0; fade_ctx.current_cct = g_device_control.cct_local; // 色温保持目标值 e_printf("[init_fade_ctx] 开机渐变模式: brightness=0->%d, cct=%d\n", g_device_control.brightness_local, fade_ctx.current_cct); } else { // 设备关闭状态 fade_ctx.current_brightness = 0; fade_ctx.current_cct = g_device_control.cct_local; } } else { // 数据尚未读取(初始化阶段)- 保持原有逻辑 fade_ctx.current_brightness = 0; fade_ctx.current_cct = 0; e_printf("[init_fade_ctx] 初始化阶段: brightness=0, cct=0\n"); } // 创建渐变任务 osal_kthread_lock(); fade_ctx.task_handle = osal_kthread_create((osal_kthread_handler)fade_task, NULL, "FadeTask", FADE_TASK_STACK_SIZE); if (fade_ctx.task_handle != NULL) { fade_ctx.task_running = true; osal_kthread_set_priority(fade_ctx.task_handle, FADE_TASK_PRIO); e_printf("[init_fade_ctx] Fade task created successfully\n"); } else { e_printf("[init_fade_ctx] Failed to create fade task\n"); osal_sem_destroy(&fade_ctx.sem); } osal_kthread_unlock(); // 设置默认更新间隔 fade_ctx.update_interval = FADE_INTERVAL_MIN; fade_ctx.timer_active = false; // 默认禁用,只有开始渐变时启用 } // 初始化呼吸灯控制 static void init_breath_ctx(void) { init_timer_system(); int ret = uapi_timer_create(TIMER_INDEX_1, &breath_ctx.timer_handle); if (ret != 0) { e_printf("呼吸灯定时器创建失败\r\n"); } // 初始化信号量 if (osal_sem_init(&breath_ctx.sem, 0) != OSAL_SUCCESS) { e_printf("[init_breath_ctx] Failed to init semaphore\n"); return; } // 初始化打印限制器 init_print_limiter(&breath_ctx.print_limiter, "[breath_task]"); breath_ctx.duty = g_device_control.brightness_local; breath_ctx.step = BREARTH_STEP == 0 ? 1 : BREARTH_STEP; breath_ctx.update_interval = BREARTH_INTERVAL; breath_ctx.is_initial_breath = true; breath_ctx.start_time_ms = uapi_systick_get_ms(); e_printf("Breath task: brightness=%d, step=%d, update_interval=%d, is_initial_breath=%d\n", breath_ctx.duty, breath_ctx.step, breath_ctx.update_interval, breath_ctx.is_initial_breath); // 创建呼吸灯任务 osal_kthread_lock(); breath_ctx.task_handle = osal_kthread_create((osal_kthread_handler)breath_task, NULL, "BreathTask", BREATH_TASK_STACK_SIZE); if (breath_ctx.task_handle != NULL) { breath_ctx.task_running = true; osal_kthread_set_priority(breath_ctx.task_handle, BREATH_TASK_PRIO); e_printf("[init_breath_ctx] Breath task created successfully\n"); } else { e_printf("[init_breath_ctx] Failed to create breath task\n"); osal_sem_destroy(&breath_ctx.sem); } osal_kthread_unlock(); } // 停止渐变任务 static void stop_fade_task(void) { if (fade_ctx.task_handle == NULL) { return; } fade_ctx.task_running = false; osal_sem_up(&fade_ctx.sem); // 唤醒任务以使其退出 osal_kthread_lock(); osal_kthread_destroy(fade_ctx.task_handle, 0); fade_ctx.task_handle = NULL; osal_kthread_unlock(); osal_sem_destroy(&fade_ctx.sem); e_printf("[stop_fade_task] Fade task stopped\n"); } // 停止呼吸灯任务 void stop_breath_task(void) { if (breath_ctx.task_handle == NULL) { return; } breath_ctx.task_running = false; osal_sem_up(&breath_ctx.sem); // 唤醒任务以使其退出 osal_kthread_lock(); osal_kthread_destroy(breath_ctx.task_handle, 0); breath_ctx.task_handle = NULL; osal_kthread_unlock(); // osal_sem_destroy(&breath_ctx.sem); e_printf("[stop_breath_task] Breath task stopped\n"); } // 修改stop_breath_timer函数 static void stop_breath_timer(void) { if (breath_ctx.timer_handle) { uapi_timer_stop(breath_ctx.timer_handle); uapi_timer_delete(breath_ctx.timer_handle); } breath_ctx.timer_handle = NULL; stop_breath_task(); } // 计算PWM占空比 void calculate_pwm_duty(device_control_t* pdevice_control) { // 如果开关关闭,则占空比为0 uint32_t total_brightness_pwm = BRINGHTNING2PWMDUTY(pdevice_control->brightness_local); // 计算色温比例 (0-10000) float cct_ratio = ((pdevice_control->cct_local - CCT_LOCAL_MIN) * 1.0) / CCT_RANGE; // 根据色温比例计算CW和WW的占空比 // 总亮度保持不变,只调整CW和WW的比例 pdevice_control->duty_cw = total_brightness_pwm * cct_ratio + 0.5; pdevice_control->duty_ww = total_brightness_pwm - pdevice_control->duty_cw; } // 更新PWM输出 void update_pwm_output(bool on_state, uint16_t duty_cw_val, uint16_t duty_ww_val) { // 说明:为了避免每步“重相位 + 动态拼接”导致的低亮抖动, // 这里改为固定相位(offset_time=0),并避免每次重复start_group。 // 若平台支持 uapi_pwm_update_duty_ratio,可切换为更新接口;否则退回 open 配置。 pwm_config_t cfg = {0}; cfg.repeat = true; uint16_t current_duty_cw = duty_cw_val; uint16_t current_duty_ww = duty_ww_val; if (current_duty_cw > PWM_DUTY_RATIO_MAX) { current_duty_cw = PWM_DUTY_RATIO_MAX; } if (current_duty_ww > PWM_DUTY_RATIO_MAX) { current_duty_ww = PWM_DUTY_RATIO_MAX; } uint32_t high_cnt_cw = (pwm_period_cnt * current_duty_cw) / PWM_DUTY_RATIO_MAX; uint32_t low_cnt_cw = pwm_period_cnt - high_cnt_cw; uint32_t high_cnt_ww = (pwm_period_cnt * current_duty_ww) / PWM_DUTY_RATIO_MAX; uint32_t low_cnt_ww = pwm_period_cnt - high_cnt_ww; if (!on_state) { high_cnt_cw = 0; low_cnt_cw = pwm_period_cnt; // 关灯时保持低电平整周期 high_cnt_ww = 0; low_cnt_ww = pwm_period_cnt; } #if defined(CONFIG_PWM_USING_V150) // V150: 先更新占空,再通过 start_group 触发加载 (void)uapi_pwm_update_duty_ratio(channel_id_cw, low_cnt_cw, high_cnt_cw); (void)uapi_pwm_update_duty_ratio(channel_id_ww, low_cnt_ww, high_cnt_ww); // 需要显式触发加载 (void)uapi_pwm_start_group(CONFIG_PWM_GROUP_ID); #else // V151 场景 cfg.offset_time = 0; // 固定相位,避免相位不断重置造成抖动 #if defined(CONFIG_PWM_PRELOAD) // 使用预加载:配置写入影子寄存器,等当前周期结束后自动无缝切换。 cfg.high_time = high_cnt_cw; cfg.low_time = low_cnt_cw; (void)uapi_pwm_config_preload(CONFIG_PWM_GROUP_ID, channel_id_cw, &cfg); cfg.high_time = high_cnt_ww; cfg.low_time = low_cnt_ww; (void)uapi_pwm_config_preload(CONFIG_PWM_GROUP_ID, channel_id_ww, &cfg); // 预加载模式下不重复调用 start_group,避免打乱当前计数器与周期 #else // 无预加载能力时的回退:直接 open + start_group(可能导致轻微周期扰动) cfg.high_time = high_cnt_cw; cfg.low_time = low_cnt_cw; (void)uapi_pwm_open(channel_id_cw, &cfg); cfg.high_time = high_cnt_ww; cfg.low_time = low_cnt_ww; (void)uapi_pwm_open(channel_id_ww, &cfg); (void)uapi_pwm_start_group(CONFIG_PWM_GROUP_ID); #endif #endif if (should_print(&pwm_limiter)) { e_printf("on:%d, cw(H/L):%u/%u, duty:%u, ww(H/L):%u/%u, duty:%u\r\n", on_state, high_cnt_cw, low_cnt_cw, current_duty_cw, high_cnt_ww, low_cnt_ww, current_duty_ww); } // 调试:每次更新PWM参数后,翻转一次 GPIO10(PWM_UPDATE_FLAG_PIN) // 便于使用逻辑分析仪观察控制发生的时间点 if (g_pwm_update_flag_inited) { (void)uapi_gpio_toggle(PWM_UPDATE_FLAG_PIN); } } #define ABS(x) ((x) < 0 ? -(x) : (x)) // 计算渐变步长 static void calculate_fade_steps(struct fade_ctx_t *pfade_ctx) { // 从g_device_control获取渐变时间 pfade_ctx->smooth_time_us = pfade_ctx->fade_time * 1000 * 1000;//s->us e_printf("fade brightness:%d->%d, cct:%d->%d, time:%ds\r\n", pfade_ctx->current_brightness, pfade_ctx->target_brightness, pfade_ctx->current_cct, pfade_ctx->target_cct, pfade_ctx->fade_time); // 计算亮度渐变步长 int32_t brightness_diff = pfade_ctx->target_brightness - pfade_ctx->current_brightness; int32_t cct_diff = pfade_ctx->target_cct - pfade_ctx->current_cct; // 计算需要的总步数(取亮度和色温中变化较大的那个) uint32_t max_diff = (ABS(brightness_diff) > ABS(cct_diff)) ? ABS(brightness_diff) : ABS(cct_diff); uint32_t min_steps = 0; uint32_t available_interval = 0; // 如果变化太小或者不需要渐变,直接设置目标值 if (max_diff == 0 || pfade_ctx->smooth_time_us == 0) { pfade_ctx->current_brightness = pfade_ctx->target_brightness; pfade_ctx->current_cct = pfade_ctx->target_cct; pfade_ctx->step_brightness = 0; pfade_ctx->step_cct = 0; pfade_ctx->update_interval = FADE_INTERVAL_MIN; goto lab_exit; } min_steps = max_diff; // 计算实际可用的时间间隔 available_interval = pfade_ctx->smooth_time_us / min_steps; // 如果时间间隔太小(小于允许的最小更新间隔),则增加步长 if (available_interval < FADE_INTERVAL_MIN) { // 重新计算步长,确保在指定时间内完成 pfade_ctx->update_interval = FADE_INTERVAL_MIN; int32_t actual_steps = pfade_ctx->smooth_time_us / pfade_ctx->update_interval; // 计算新的步长 pfade_ctx->step_brightness = brightness_diff / actual_steps; pfade_ctx->step_cct = cct_diff / actual_steps; // 确保至少有一个最小步长 if (pfade_ctx->step_brightness == 0 && brightness_diff != 0) { pfade_ctx->step_brightness = (brightness_diff > 0) ? 1 : -1; } if (pfade_ctx->step_cct == 0 && cct_diff != 0) { pfade_ctx->step_cct = (cct_diff > 0) ? 1 : -1; } } else { // 使用计算出的时间间隔 pfade_ctx->update_interval = available_interval; pfade_ctx->step_brightness = (brightness_diff > 0) ? 1 : -1; pfade_ctx->step_cct = (cct_diff > 0) ? 1 : -1; } // 如果亮度或色温没有变化,则步长为0 if (brightness_diff == 0) { pfade_ctx->step_brightness = 0; } if (cct_diff == 0) { pfade_ctx->step_cct = 0; } lab_exit: e_printf("fade max_diff:%d, fade time:%uus, Brightness: diff:%d, step:%d, CCT: diff:%d, step:%d, update_interval:%uus\r\n", max_diff, pfade_ctx->smooth_time_us, brightness_diff, pfade_ctx->step_brightness, cct_diff, pfade_ctx->step_cct, pfade_ctx->update_interval); } static void cancel_current_light_fade(void) { // 竞态保护:先拉低标志再停计时器,避免回调自重启 fade_ctx.timer_active = false; uapi_timer_stop(fade_ctx.timer_handle); // 如果我打断了渐变,则将当前值更新到目标值不然下次计算会异常 // g_device_control.cct_local = fade_ctx.current_cct; // g_device_control.brightness_local = fade_ctx.current_brightness; // memset(&fade_ctx, 0, FADE_CTRL_DATA_SIZE(fade_ctx)); } // 计算校验和 static uint8_t calculate_checksum(const device_data_t* data) { uint8_t sum = 0; const uint8_t* ptr = (const uint8_t*)(((char*)data) + sizeof(data->checksum)); size_t len = sizeof(device_data_t) - sizeof(data->checksum); // 减去checksum字段的大小 for (size_t i = 0; i < len; i++) { sum ^= ptr[i]; } return sum; } // 验证数据有效性 static bool verify_device_data(const device_data_t* data) { if (data->magic != DEVICE_DATA_MAGIC) { e_printf("magic error:%x\n", data->magic); return false; } if (data->version > DEVICE_DATA_VERSION) { e_printf("versoin missmatch:%x\n", data->version); return false; } uint8_t checksum = calculate_checksum(data); if (checksum != data->checksum) { e_printf("check sum error:%x\n", data->version); return false; } return true; } // 从指定地址读取设备数据 static bool read_device_data_from_addr(uint32_t addr, device_data_t* data) { int ret = hfuflash_read(addr, (char*)data, sizeof(device_data_t)); if (ret != sizeof(device_data_t)) { e_printf("从地址0x%x读取设备数据失败,实际读取长度:%d\r\n", addr, ret); return false; } if (!verify_device_data(data)) { e_printf("地址0x%x的数据无效\r\n", addr); return false; } return true; } // 写入数据到指定地址 static bool write_device_data_to_addr(uint32_t addr, const device_data_t* data) { int ret = hfuflash_erase_page(addr, 1); if (ret != HF_SUCCESS) { e_printf("擦除地址0x%x的Flash页失败,错误码:%d\r\n", addr, ret); return false; } ret = hfuflash_write(addr, (char*)data, sizeof(device_data_t)); if (ret != sizeof(device_data_t)) { e_printf("写入数据到地址0x%x失败,实际写入长度:%d\r\n", addr, ret); return false; } return true; } void read_device_data(void) { #if SUPPORT_SAVE_TO_FLASH device_data_t data; bool main_valid = false; bool backup_valid = false; // 尝试读取主数据区 main_valid = read_device_data_from_addr(DEVICE_DATA_FLASH_ADDR, &data); // 如果主数据区无效,尝试读取备份区 if (!main_valid) { backup_valid = read_device_data_from_addr(DEVICE_DATA_BACKUP_ADDR, &data); } if (!main_valid && backup_valid) { // 如果主数据区无效但备份区有效,从备份区恢复 e_printf("从备份区恢复数据\r\n"); write_device_data_to_addr(DEVICE_DATA_FLASH_ADDR, &data); } else if (!main_valid && !backup_valid) { // 如果两个区域都无效,使用默认值 e_printf("主数据和备份数据都无效,使用默认值\r\n"); // 只打印g_device_control的当前值,不打印data.control e_printf("上电次数: %d\r\n", g_device_control.power_on_cnt); e_printf("配网状态: %d\r\n", g_device_control.is_bound); e_printf("是否是新设备: %d\r\n", !g_device_control.is_net_configured); e_printf("开关状态: %d\r\n", g_device_control.on); e_printf("灯光模式: %d\r\n", g_device_control.elightMode); e_printf("亮度: %d\r\n", g_device_control.brightness_local); e_printf("色温: %d\r\n", g_device_control.cct_local); e_printf("冷白LED: %d\r\n", g_device_control.duty_cw); e_printf("暖白LED: %d\r\n", g_device_control.duty_ww); e_printf("渐变时间: %d\r\n", g_device_control.fade_time); goto lab_exit; } // 更新设备控制状态 e_printf("设备状态恢复:\r\n"); e_printf("上电次数: %d => %d\r\n", g_device_control.power_on_cnt, data.control.power_on_cnt); e_printf("配网状态: %d => %d\r\n", g_device_control.is_bound, data.control.is_bound); e_printf("是否是新设备: %d => %d\r\n", !g_device_control.is_net_configured, !data.control.is_net_configured); e_printf("开关状态: %d => %d\r\n", g_device_control.on, data.control.on); e_printf("灯光模式: %d => %d\r\n", g_device_control.elightMode, data.control.elightMode); e_printf("亮度: %d => %d\r\n", g_device_control.brightness_local, data.control.brightness_local); e_printf("色温: %d => %d\r\n", g_device_control.cct_local, data.control.cct_local); e_printf("色温模式: %d => %d\r\n", g_device_control.colourMode, data.control.colourMode); e_printf("冷白LED: %d => %d\r\n", g_device_control.duty_cw, data.control.duty_cw); e_printf("暖白LED: %d => %d\r\n", g_device_control.duty_ww, data.control.duty_ww); e_printf("渐变时间: %d => %d\r\n", g_device_control.fade_time, data.control.fade_time); data.control.read_done = false; g_device_control = data.control; // fastboot的时候就已经亮起来了,所以当前测温直接变为目标值 // fade_ctx.current_brightness = g_device_control.brightness_local; // fade_ctx.current_cct = g_device_control.cct_local; lab_exit: #endif g_device_control.read_done = true; e_printf("读取设备数据成功\r\n"); } void save_device_data(void) { e_printf("Starting to save device data\n"); #if SUPPORT_SAVE_TO_FLASH // 使用静态变量保存上一次的数据状态 static device_control_t last_control = {0}; static bool is_first_save = true; // 需要比较的字段(根据注释标记的持久化维持部分) bool need_save = is_first_save || last_control.on != g_device_control.on || last_control.elightMode != g_device_control.elightMode || last_control.brightness_local != g_device_control.brightness_local || last_control.fade_time != g_device_control.fade_time || last_control.cct_local != g_device_control.cct_local || last_control.colourMode != g_device_control.colourMode || last_control.power_on_cnt != g_device_control.power_on_cnt || last_control.is_bound != g_device_control.is_bound || last_control.is_net_configured != g_device_control.is_net_configured; if (!need_save) { e_printf("No changes detected, skip saving\n"); return; } device_data_t data; // 准备要保存的数据 data.magic = DEVICE_DATA_MAGIC; data.version = DEVICE_DATA_VERSION; data.control = g_device_control; data.checksum = calculate_checksum(&data); // 先写入备份区 if (!write_device_data_to_addr(DEVICE_DATA_BACKUP_ADDR, &data)) { e_printf("Failed to write backup data\n"); return; } // 再写入主数据区 if (!write_device_data_to_addr(DEVICE_DATA_FLASH_ADDR, &data)) { e_printf("Failed to write main data, but backup data saved\n"); } // 更新上一次的数据状态 last_control = g_device_control; is_first_save = false; e_printf("Device data saved successfully\n"); #endif e_printf("Save device data done\n"); } void req_save_device_data(void) { osal_sem_up(&save_data_sem); } // 保存任务函数 static void *save_data_task(const char *arg) { e_printf("[save_data_task] Save task started\n"); while (save_task_running) { // 等待保存信号 if (osal_sem_down_timeout(&save_data_sem, 100*1000) != OSAL_SUCCESS) { continue; } while(OSAL_SUCCESS == osal_sem_trydown(&save_data_sem));//消耗所有的信号一次性刷入 save_device_data(); } e_printf("[save_data_task] Save task exited\n"); return NULL; } // 初始化保存任务 static void init_save_task(void) { if (save_task_handle != NULL) { return; } // 初始化信号量 if (osal_sem_init(&save_data_sem, 0) != OSAL_SUCCESS) { e_printf("[init_save_task] Failed to init semaphore\n"); return; } // 创建保存任务 osal_kthread_lock(); save_task_handle = osal_kthread_create((osal_kthread_handler)save_data_task, NULL, "SaveDataTask", SAVE_TASK_STACK_SIZE); if (save_task_handle != NULL) { save_task_running = true; osal_kthread_set_priority(save_task_handle, SAVE_TASK_PRIO); e_printf("[init_save_task] Save task created successfully\n"); } else { e_printf("[init_save_task] Failed to create save task\n"); osal_sem_destroy(&save_data_sem); } osal_kthread_unlock(); } // 停止保存任务 static void stop_save_task(void) { if (save_task_handle == NULL) { return; } save_task_running = false; osal_sem_up(&save_data_sem); // 唤醒任务以使其退出 osal_kthread_lock(); osal_kthread_destroy(save_task_handle, 0); save_task_handle = NULL; osal_kthread_unlock(); osal_sem_destroy(&save_data_sem); e_printf("[stop_save_task] Save task stopped\n"); } // 设置灯光状态(统一控制函数) // 参数: // source: 控制源,用于区分不同的控制场景 // current_brightness_local: 当前亮度值 // current_cct_local: 当前色温值 // brightness_local_target: 亮度目标值 // cct_local_target: 色温目标值 // 返回值: // 0: 成功 // -111: 异步上报 // -1: 失败 int set_light(light_ctrl_source_e source, int32_t brightness_local_target, int32_t cct_local_target) { bool was_on = g_device_control.on; struct fade_ctx_t tmp_fade_ctx = {0}; if (fade_ctx.is_fading) { bool closing_fade_active = fade_ctx.is_closing_fade; bool suppress_cancel = false; // 在关灯渐变过程中,属性/模式变更不应打断关灯过程 if (closing_fade_active) { if (source == APP_CHANGE_LIGHT_BRIGHTNESS_CCT || source == APP_CHANGE_LIGHT_MODE || source == APP_CLOSE_LIGHT) { suppress_cancel = true; // 允许继续关灯渐变;再次关灯请求可复用或稍后重启 } } if (!suppress_cancel) { cancel_current_light_fade(); } } // 如果打开灯,则需要手动将前置状态设置为关闭的样子,这样子后面计算渐变才能正常计算 if (APP_OPEN_LIGHT == source || DEV_POWER_ON == source) { g_device_control.on = true; if (DEV_POWER_ON == source || (APP_OPEN_LIGHT == source && !was_on)) { // 开机或关灯→开灯:从0开始渐变 fade_ctx.current_brightness = 0; fade_ctx.current_cct = g_device_control.cct_local; // 色温保持目标值 e_printf("[set_light] 开灯渐变设置: brightness=0->%d, cct=%d\n", g_device_control.brightness_local, fade_ctx.current_cct); } brightness_local_target = g_device_control.brightness_local; // 色温不进行变化,只改变亮度 cct_local_target = g_device_control.cct_local; if (g_device_control.colourMode != COLOUR_MODE_DUAL) { fade_ctx.current_cct = SINGLE_COLOUR_CCT_LOCAL; cct_local_target = SINGLE_COLOUR_CCT_LOCAL; } } memcpy(&tmp_fade_ctx, &fade_ctx, FADE_CTRL_DATA_SIZE(fade_ctx)); // 默认目标应为“当前设备状态”,避免在未指定字段时误用上一次渐变的目标(可能为0)。 tmp_fade_ctx.target_brightness = g_device_control.brightness_local; tmp_fade_ctx.target_cct = g_device_control.cct_local; if (brightness_local_target >= 0) { BRIGHTNESS_LITME_RANGE(brightness_local_target); tmp_fade_ctx.target_brightness = brightness_local_target; } else { e_printf("[set_light] keep brightness:%d (source:%d)\r\n", tmp_fade_ctx.target_brightness, source); } if (cct_local_target >= 0) { CCT_LITME_RANGE(cct_local_target); tmp_fade_ctx.target_cct = cct_local_target; } else { e_printf("[set_light] keep cct:%d (source:%d)\r\n", tmp_fade_ctx.target_cct, source); } e_printf("source:%d, lightMode:%d, local brightness: base:%d, target:%d, local cct: base:%d, target:%d\r\n", source, g_device_control.elightMode, tmp_fade_ctx.current_brightness, tmp_fade_ctx.target_brightness, tmp_fade_ctx.current_cct, tmp_fade_ctx.target_cct); tmp_fade_ctx.fade_time = g_device_control.fade_time; tmp_fade_ctx.is_closing_fade = false; switch (source) { case APP_CLOSE_LIGHT: // 使用渐变方式关灯:设置目标亮度为0,使用is_closing_fade标志 g_device_control.on = false; // 设置开关状态为关闭(用于状态上报) tmp_fade_ctx.is_closing_fade = true; // 标记为关灯渐变 tmp_fade_ctx.target_brightness = 0; // 目标亮度设为0 tmp_fade_ctx.target_cct = tmp_fade_ctx.current_cct; // 色温保持不变 tmp_fade_ctx.fade_time = NORMAL_FADE_TIME; // 使用默认渐变时长 tmp_fade_ctx.is_fading = true; tmp_fade_ctx.fade_completed = false; if (tmp_fade_ctx.is_fading) { cancel_current_light_fade(); } calculate_fade_steps(&tmp_fade_ctx); // 复用原有计算流程 memcpy(&fade_ctx, &tmp_fade_ctx, FADE_CTRL_DATA_SIZE(tmp_fade_ctx)); e_printf("start close light fade\r\n"); fade_ctx.timer_active = true; uapi_timer_start(fade_ctx.timer_handle, fade_ctx.update_interval, fade_timer_callback, 0); start_report_task(REPORT_SWITCH | REPORT_LIGHT_MODE); req_save_device_data(); return -111; // 异步上报 break; case DEV_POWER_ON: case APP_OPEN_LIGHT: tmp_fade_ctx.fade_time = NORMAL_FADE_TIME; // 上电时,直接设置为默认渐变时长 case APP_CHANGE_LIGHT_MODE: // 开灯场景或上电:执行渐变;关灯状态下仅更新目标不执行渐变 if (was_on || source != APP_CHANGE_LIGHT_MODE) { if (g_device_control.colourMode == COLOUR_MODE_DUAL) { g_device_control.cct_local = tmp_fade_ctx.target_cct; } g_device_control.brightness_local = tmp_fade_ctx.target_brightness; tmp_fade_ctx.is_fading = true; tmp_fade_ctx.fade_completed = false; if (tmp_fade_ctx.is_fading) { cancel_current_light_fade(); } calculate_fade_steps(&tmp_fade_ctx); memcpy(&fade_ctx, &tmp_fade_ctx, FADE_CTRL_DATA_SIZE(tmp_fade_ctx)); e_printf("start fade\r\n"); fade_ctx.timer_active = true; uapi_timer_start(fade_ctx.timer_handle, fade_ctx.update_interval, fade_timer_callback, 0); start_report_task(REPORT_SWITCH | REPORT_BRIGHTNESS | REPORT_CCT | REPORT_LIGHT_MODE | REPORT_COLOUR_MODE); req_save_device_data(); return 0; // 异步上报 } else { // 灯处于关闭:仅更新目标值,保持当前亮度为0,不触发渐变 if (g_device_control.colourMode == COLOUR_MODE_DUAL) { g_device_control.cct_local = tmp_fade_ctx.target_cct; // 关灯渐变进行中不改动 fade_ctx,避免打断渐变过程的内部状态 if (!fade_ctx.is_closing_fade) { fade_ctx.current_cct = tmp_fade_ctx.target_cct; // 预设色温,开灯后按新色温渐变 } } g_device_control.brightness_local = tmp_fade_ctx.target_brightness; e_printf("[set_light] off-state mode change, preserve current_brightness:%d, target_brightness:%d\r\n", fade_ctx.current_brightness, g_device_control.brightness_local); start_report_task(REPORT_BRIGHTNESS | REPORT_CCT | REPORT_LIGHT_MODE | REPORT_COLOUR_MODE); req_save_device_data(); return -111; } break; case APP_CHANGE_LIGHT_BRIGHTNESS_CCT: if (!was_on) { // 关灯状态:仅更新目标,不执行渐变,保持 current_brightness=0,避免开灯时跳变 if (g_device_control.colourMode == COLOUR_MODE_DUAL && cct_local_target >= 0) { g_device_control.cct_local = tmp_fade_ctx.target_cct; if (!fade_ctx.is_closing_fade) { fade_ctx.current_cct = tmp_fade_ctx.target_cct; // 预设色温 } } if (brightness_local_target >= 0) { g_device_control.brightness_local = tmp_fade_ctx.target_brightness; } e_printf("[set_light] off-state attr change, keep current_brightness:%d, target_brightness:%d\r\n", fade_ctx.current_brightness, g_device_control.brightness_local); start_report_task(REPORT_BRIGHTNESS | REPORT_CCT | REPORT_LIGHT_MODE | REPORT_COLOUR_MODE); req_save_device_data(); } else { // 开灯状态:执行正常渐变 if (g_device_control.colourMode == COLOUR_MODE_DUAL && cct_local_target >= 0) { // 双色温且明确修改时才更新色温 g_device_control.cct_local = tmp_fade_ctx.target_cct; } if (brightness_local_target >= 0) { // 明确修改亮度时才更新亮度 g_device_control.brightness_local = tmp_fade_ctx.target_brightness; } tmp_fade_ctx.is_fading = true; tmp_fade_ctx.fade_completed = false; if (tmp_fade_ctx.is_fading) { cancel_current_light_fade(); } calculate_fade_steps(&tmp_fade_ctx); memcpy(&fade_ctx, &tmp_fade_ctx, FADE_CTRL_DATA_SIZE(tmp_fade_ctx)); e_printf("start fade\r\n"); fade_ctx.timer_active = true; uapi_timer_start(fade_ctx.timer_handle, fade_ctx.update_interval, fade_timer_callback, 0); start_report_task(REPORT_BRIGHTNESS | REPORT_CCT | REPORT_LIGHT_MODE | REPORT_COLOUR_MODE); req_save_device_data(); } #if 0 等待渐变完成 while (!fade_ctx.fade_completed) { msleep(10); } return 0; // 同步上报 #else return -111; // 异步上报 #endif break; } e_printf("set_light error, source:%d, current_brightness_local:%d, current_cct_local:%d, brightness_local_target:%d, cct_local_target:%d\r\n", source, tmp_fade_ctx.current_brightness, tmp_fade_ctx.current_cct, brightness_local_target, cct_local_target); return -1; } void close_light(void) { g_device_control.on = false; if (fade_ctx.is_fading) { cancel_current_light_fade(); } fade_ctx.current_brightness = 0; fade_ctx.current_cct = 0; update_pwm_output(false, 0, 0); req_save_device_data(); } static void gpio_init(pin_t pin) { /* PINCTRL init. */ uapi_pin_init(); uapi_pin_set_mode(pin, HAL_PIO_FUNC_GPIO); uapi_gpio_set_dir(pin, GPIO_DIRECTION_OUTPUT); uapi_pin_set_ds(pin, PIN_DS_3); uapi_pin_set_pull(pin, PIN_PULL_TYPE_DOWN); uapi_gpio_set_val(pin, CLOSE_LIGHT); } static void pwm_sys_init(void) { uapi_pwm_deinit(); } static void pwm_init(pin_t pin, pin_t pin1) { pwm_config_t cfg_repeat = {0}; cfg_repeat.repeat = true; uapi_pin_set_mode(pin, PIN_MODE_1); uapi_pin_set_mode(pin1, PIN_MODE_1); uapi_pwm_init(); // 基准时钟固定 80MHz(客户指定)。不要使用 uapi_pwm_get_frequency 返回值。 channel_id_cw = pin % 8; channel_id_ww = pin1 % 8; const uint32_t base_clk = 80 * 1000 * 1000; // 80MHz 固定 pwm_period_cnt = (base_clk / PWM_FREQUENCY); // 初始为关灯:高电平0,低电平整周期;固定相位 cfg_repeat.high_time = 0; cfg_repeat.low_time = pwm_period_cnt; cfg_repeat.offset_time = 0; // 先打开两个通道 (void)uapi_pwm_open(channel_id_cw, &cfg_repeat); (void)uapi_pwm_open(channel_id_ww, &cfg_repeat); // 设置分组并启动(分组只需启动一次) uint8_t channel_ids[2] = {channel_id_cw, channel_id_ww}; (void)uapi_pwm_set_group(CONFIG_PWM_GROUP_ID, channel_ids, sizeof(channel_ids)); (void)uapi_pwm_start_group(CONFIG_PWM_GROUP_ID); e_printf("PWM基础时钟频率(固定): %uHz, 目标时钟频率: %dHz, 周期计数: %u\r\n", base_clk, PWM_FREQUENCY, pwm_period_cnt); } extern int start_hilink_ble_net_config(int32_t net_cfg_time_s); void start_net_config(void) { e_printf("进入配网状态,上电次数:%d, is_new设备:%d\r\n", g_device_control.power_on_cnt, !g_device_control.is_net_configured); // 按新规则:上电计数仅能在上电超过5秒后自然清零, // 配网流程不再主动清除 power_on_cnt。 int ret = start_hilink_ble_net_config(NET_CFG_TOTAL_TIMEOUT/1000); if (ret) { // FIXME: 这里简单恢复之前等待配网的灯效即可 e_printf("start net_cfg fail:%n\r\n", ret); req_save_device_data(); // extern int HILINK_RestoreFactorySettings(void); // HILINK_RestoreFactorySettings(); return; } // 初始化呼吸灯控制 init_breath_ctx(); start_breath_timer(); } void stop_net_config(void) { stop_breath_timer(); start_hilink_ble_net_config(0); } // 配网状态管理相关函数 static int handle_network_status(void) { uint8_t start_net_cfg = 0; // 增加上电计数 g_device_control.power_on_cnt++; e_printf("现在是第 %d 次上电\r\n", g_device_control.power_on_cnt); // 检查是否需要进入配网状态或恢复出厂设置 if (g_device_control.power_on_cnt >= NET_CFG_ENTRY_CNT) { // 任何状态下达到阈值都强制解绑并恢复出厂设置 e_printf("快速上电达到 %d 次,强制恢复出厂设置(解绑)\r\n", NET_CFG_ENTRY_CNT); g_reset_factory_flag = true; g_device_control.power_on_cnt = 0; extern int HILINK_RestoreFactorySettings(void); while (!hf_hilink_main_is_runing()) { msleep(10); } HILINK_RestoreFactorySettings(); return start_net_cfg; } else if (!g_device_control.is_net_configured) { // 未出厂设备直接进入配网 start_net_config(); start_net_cfg = 1; } // 保存设备状态 req_save_device_data(); // 如果已经配网,直接返回 if (g_device_control.is_bound) { // 如果已经配网,则设置发出ble广播确保如果没法连接路由器可以转为本地蓝牙控制 start_hilink_ble_net_config(0xFFFFFFFF); return start_net_cfg; } return start_net_cfg; } // 设备上线时的状态上报 static void report_device_online_status(void) { e_printf("Starting to report all service status\r\n"); fast_report(SVC_ID_SWITCH); fast_report(SVC_ID_BRIGHTNESS); fast_report(SVC_ID_CCT); fast_report(SVC_ID_LIGHT_MODE); fast_report(SVC_ID_FADE_TIME); fast_report(SVC_ID_COLOUR_MODE); // fast_report(SVC_ID_NET_INFO); e_printf("Status report completed\r\n"); } // 渐变结束时的状态上报 static void report_fade_complete_status(void) { req_save_device_data(); e_printf("Reporting fade complete status\r\n"); fast_report(SVC_ID_LIGHT_MODE); fast_report(SVC_ID_BRIGHTNESS); fast_report(SVC_ID_CCT); e_printf("Fade status report completed\r\n"); } // 渐变结束时的状态上报 static void report_switch_status(void) { req_save_device_data(); fast_report(SVC_ID_SWITCH); } static const struct { const char* svc_id; } report_mask_map[] = { [REPORT_SWITCH] = {SVC_ID_SWITCH}, [REPORT_BRIGHTNESS] = {SVC_ID_BRIGHTNESS}, [REPORT_CCT] = {SVC_ID_CCT}, [REPORT_LIGHT_MODE] = {SVC_ID_LIGHT_MODE}, [REPORT_FADE_TIME] = {SVC_ID_FADE_TIME}, [REPORT_COLOUR_MODE] = {SVC_ID_COLOUR_MODE}, }; // 状态上报任务函数 static void *report_task(const char *arg) { unused(arg); e_printf("[report_task] Task started\r\n"); // 等待hilink和数据ready while (!(g_device_control.read_done && hf_hilink_main_is_runing())) { e_printf("read_done%d, hilink:%d\r\n", g_device_control.read_done, hf_hilink_main_is_runing()); osal_msleep(50); } while (report_task_running) { // 等待信号量唤醒 if (g_report_mask == 0 && osal_sem_down_timeout(&report_sem, 100*1000) != OSAL_SUCCESS) { continue; } e_printf("[report_task] Reported mask: 0x%x\r\n", g_report_mask); // 根据掩码进行上报 if (g_report_mask & REPORT_SWITCH) { g_report_mask &= ~REPORT_SWITCH; fast_report(SVC_ID_SWITCH); } if (g_report_mask & REPORT_BRIGHTNESS) { g_report_mask &= ~REPORT_BRIGHTNESS; fast_report(SVC_ID_BRIGHTNESS); } if (g_report_mask & REPORT_CCT) { g_report_mask &= ~REPORT_CCT; fast_report(SVC_ID_CCT); } if (g_report_mask & REPORT_LIGHT_MODE) { g_report_mask &= ~REPORT_LIGHT_MODE; fast_report(SVC_ID_LIGHT_MODE); } if (g_report_mask & REPORT_FADE_TIME) { g_report_mask &= ~REPORT_FADE_TIME; fast_report(SVC_ID_FADE_TIME); } if (g_report_mask & REPORT_COLOUR_MODE) { g_report_mask &= ~REPORT_COLOUR_MODE; fast_report(SVC_ID_COLOUR_MODE); } } e_printf("[report_task] Task exited\r\n"); return NULL; } // 启动状态上报任务 static void start_report_task(uint32_t report_mask) { // 设置全局掩码 g_report_mask |= report_mask; osal_sem_up(&report_sem); // 只在第一次创建任务 if (!report_task_running) { osal_kthread_lock(); if (report_task_running) { osal_kthread_unlock(); return; } report_task_running = true; e_printf("[start_report_task] Creating report task\r\n"); report_task_handle = osal_kthread_create((osal_kthread_handler)report_task, NULL, "ReportStaTask", REPORT_TASK_STACK_SIZE); if (report_task_handle != NULL) { osal_kthread_set_priority(report_task_handle, REPORT_TASK_PRIO); e_printf("[start_report_task] Report task created successfully\r\n"); } else { e_printf("[start_report_task] Failed to create report task\r\n"); report_task_running = false; } osal_kthread_unlock(); } else { e_printf("[start_report_task] Report task already running, mask: 0x%x\r\n", report_mask); } } // 设备注册事件:仅处理配网相关(绑定标志、退出配网) void handle_device_register(void) { e_printf("device registered!\r\n"); g_device_control.is_net_configured = true; // 视为完成一次配网流程 if (!g_device_control.is_bound) { e_printf("设备首次注册,记录配网状态\r\n"); g_device_control.is_bound = true; stop_breath_timer(); set_light2net_cfg_done(); req_save_device_data(); } g_net_breath_state = NET_CFG_IDLE; g_net_cfg_start_time = 0; } // 设备注销事件:仅清理配网行为(不涉及online/offline状态) void handle_device_unregister(void) { e_printf("device unregistered!\r\n"); stop_breath_timer(); g_net_breath_state = NET_CFG_IDLE; g_net_cfg_start_time = 0; } // 处理设备解绑 void handle_device_unbind(void) { e_printf("设备被解绑,重置配网状态:%d\r\n", g_device_control.is_bound); if (g_device_control.is_bound) { g_device_control.is_bound = false; // stop_spotlight_main_task(); device_control_t tmp = DEFAULT_DEVICE_DATA;//恢复默认 // if (!g_reset_factory_flag) { // tmp.is_net_configured = g_device_control.is_net_configured; // } g_device_control = tmp; } save_device_data(); } uint64_t startup_time = 0; static void check_net_cfg_power_on_keep_time(void) { if (g_device_control.power_on_cnt <= 0) { return; } if (uapi_systick_get_ms() - startup_time > INIT_NET_CFG_PWOER_ON_KEEP_TIME) { e_printf("power_on keep time is %llums must < %ds, we will reset cnt\r\n", uapi_systick_get_ms(), INIT_NET_CFG_PWOER_ON_KEEP_TIME/1000); g_device_control.power_on_cnt = 0; req_save_device_data(); } } // spotlight主任务相关变量 #define SPOTLIGHT_MAIN_TASK_PRIO 23 #define SPOTLIGHT_MAIN_TASK_STACK_SIZE 0x1000 static osal_task *spotlight_main_task_handle = NULL; static bool spotlight_main_task_running = false; // spotlight主任务函数 static void *spotlight_main_task(const char *arg) { unused(arg); e_printf("[spotlight_main_task] Task started\r\n"); uint32_t current_time = 0; //uapi_systick_get_ms(); // 自愈:在HiLink Main运行后做一次绑定状态一致性检查 static bool s_bind_consistency_checked = false; while (spotlight_main_task_running) { // 检查配网超时 check_net_cfg_timeout(); check_net_cfg_power_on_keep_time(); if (!s_bind_consistency_checked && hf_hilink_main_is_runing()) { // 仅执行一次:检查应用层与HiLink SDK的绑定状态是否一致 extern int HILINK_IsRegister(void); extern int HILINK_RestoreFactorySettings(void); int reg = HILINK_IsRegister(); bool sdk_bound = (reg != 0); bool app_bound = g_device_control.is_bound; if (sdk_bound != app_bound) { e_printf("[consistency] app_bound=%d, sdk_bound=%d, do factory reset\r\n", app_bound, sdk_bound); // 触发完整流程:由HiLink框架内部清理持久化并按注册的重启回调执行 HILINK_RestoreFactorySettings(); } s_bind_consistency_checked = true; } osal_msleep(20); } // 停止保存任务 stop_save_task(); e_printf("[spotlight_main_task] Task exited\r\n"); return NULL; } // 启动spotlight主任务 static void start_spotlight_main_task(void) { if (spotlight_main_task_handle != NULL) { e_printf("[start spotlight task] Task already running\r\n"); return; } e_printf("[start spotlight task] Starting task\r\n"); osal_kthread_lock(); spotlight_main_task_handle = osal_kthread_create((osal_kthread_handler)spotlight_main_task, NULL, "SpotlightMain", SPOTLIGHT_MAIN_TASK_STACK_SIZE); if (spotlight_main_task_handle != NULL) { spotlight_main_task_running = true; osal_kthread_set_priority(spotlight_main_task_handle, SPOTLIGHT_MAIN_TASK_PRIO); e_printf("[start spotlight task] Task created successfully\r\n"); } else { e_printf("[start spotlight task] Failed to create task\r\n"); } osal_kthread_unlock(); } // 停止spotlight主任务 static void stop_spotlight_main_task(void) { if (spotlight_main_task_handle == NULL) { return; } spotlight_main_task_running = false; osal_kthread_lock(); osal_kthread_destroy(spotlight_main_task_handle, 0); spotlight_main_task_handle = NULL; osal_kthread_unlock(); // 停止report task if (report_task_running) { report_task_running = false; osal_sem_up(&report_sem); // 唤醒任务以使其退出 osal_kthread_lock(); if (report_task_handle) { osal_kthread_destroy(report_task_handle, 0); report_task_handle = NULL; } osal_kthread_unlock(); osal_sem_destroy(&report_sem); e_printf("[stop_spotlight_main_task] Report task stopped\r\n"); } e_printf("[stop_spotlight_main_task] Task stopped\r\n"); } // 检查配网超时 static void check_net_cfg_timeout(void) { if (g_net_breath_state != NET_CFG_BREATHING) { return; } uint64_t current_time = uapi_systick_get_ms(); uint64_t elapsed_time = current_time - g_net_cfg_start_time; if (elapsed_time >= NET_CFG_TOTAL_TIMEOUT) { e_printf("[Net Cfg] 配网超过10分钟,退出配网模式\r\n"); g_net_breath_state = NET_CFG_TIMEOUT; } } // 修改spotlight_main函数 int spotlight_main(void) { uapi_systick_init(); startup_time = uapi_systick_get_ms(); e_printf("uapi_timer_get_max_us:%uus, start_time:%uus\r\n", uapi_timer_get_max_us(), uapi_systick_get_ms()); read_device_data(); // 初始化GPIO并将灯关闭 gpio_init(SWITCH_PIN); // 初始化 PWM 更新标志引脚(GPIO10)为普通GPIO输出,默认拉低 gpio_init(PWM_UPDATE_FLAG_PIN); g_pwm_update_flag_inited = true; // 初始化PWM系统 pwm_sys_init(); pwm_init(BRIGHTNESS_PIN, CCT_PIN); // 初始化渐变控制 init_fade_ctx(); // 初始化保存任务 init_save_task(); // 初始化report task信号量 if (osal_sem_init(&report_sem, 0) != OSAL_SUCCESS) { e_printf("[spotlight_main] Failed to init report semaphore\r\n"); return -1; } // 检查配网状态,确定是否需要进入配网状态 handle_network_status(); //上电亮灯也是需要缓慢亮起来, 如果是在配网的话就不用了。交给配网的代码进行控制 if (g_net_breath_state == NET_CFG_IDLE && g_device_control.on == true){ if (g_device_control.colourMode == COLOUR_MODE_SINGLE) { set_light(DEV_POWER_ON, g_device_control.brightness_local, SINGLE_COLOUR_CCT_LOCAL); } else { set_light(DEV_POWER_ON, g_device_control.brightness_local, g_device_control.cct_local); } // set_light(DEV_POWER_ON, g_device_control.brightness_local, g_device_control.cct_local); } if (!g_device_control.is_bound && !g_device_control.is_net_configured) { try_detect_factory_test(); } start_spotlight_main_task(); return 0; } // 设置渐变时长 int set_smooth_time(uint32_t smooth_time) { e_printf("[set_smooth_time] Setting smooth time: %d s\r\n", smooth_time); if (smooth_time < SMOOTH_TIME_MIN) { e_printf("[set_smooth_time] Smooth time below minimum, adjusted to: %d s\r\n", SMOOTH_TIME_MIN); smooth_time = SMOOTH_TIME_MIN; } if (smooth_time > SMOOTH_TIME_MAX) { e_printf("[set_smooth_time] Smooth time above maximum, adjusted to: %d s\r\n", SMOOTH_TIME_MAX); smooth_time = SMOOTH_TIME_MAX; } g_device_control.fade_time = smooth_time; req_save_device_data(); e_printf("[set_smooth_time] Smooth time setting completed\r\n"); return 0; } // 设置灯光到配网超时状态 static void set_light2breathtimeout(void) { e_printf("[Net cfg] 配网超过1分钟,退出呼吸灯状态\r\n"); // 恢复到自定义模式 g_device_control.brightness_local = BRIGHTNESS_REMOTE2LOCAL(NET_CFG_TIMEOUT_BRIGHTNESS); g_device_control.cct_local = CCT_REMOTE2LOCAL(NET_CFG_TIMEOUT_CCT); fade_ctx.current_brightness = g_device_control.brightness_local; fade_ctx.current_cct = g_device_control.cct_local; calculate_pwm_duty(&g_device_control); update_pwm_output(g_device_control.on, g_device_control.duty_cw, g_device_control.duty_ww); } // 设置灯光到配网完成状态 static void set_light2net_cfg_done(void) { g_device_control.elightMode = NET_CFG_DEFAULT_LIGHTMODE; g_device_control.brightness_local = BRIGHTNESS_REMOTE2LOCAL(NET_CFG_DEFAULT_BRIGHTNESS); g_device_control.cct_local = CCT_REMOTE2LOCAL(NET_CFG_DEFAULT_CCT); g_device_control.fade_time = NET_CFG_DEFAULT_FADE_TIME; // 🔧 关键修复:配网完成后直接使用目标色温,不从PWM反推 // PWM反推逻辑是错误的,因为呼吸灯PWM状态不代表用户期望的色温 fade_ctx.current_brightness = g_device_control.brightness_local; fade_ctx.current_cct = g_device_control.cct_local; // 直接使用目标色温 e_printf("[set_light2net_cfg_done] 配网完成,同步色温: brightness=%d, cct=%d\n", fade_ctx.current_brightness, fade_ctx.current_cct); // 设置目标值(与当前值一致,避免不必要的渐变) fade_ctx.target_brightness = g_device_control.brightness_local; fade_ctx.target_cct = g_device_control.cct_local; calculate_pwm_duty(&g_device_control); update_pwm_output(g_device_control.on, g_device_control.duty_cw, g_device_control.duty_ww); e_printf("[set_light2net_cfg_done] 配网完成状态同步: current_cct=%d, target_cct=%d\n", fade_ctx.current_cct, fade_ctx.target_cct); } // 启动呼吸灯 static void start_breath_timer(void) { g_net_breath_state = NET_CFG_BREATHING; g_net_cfg_start_time = uapi_systick_get_ms(); uapi_timer_start(breath_ctx.timer_handle, breath_ctx.update_interval, breath_timer_callback, 0); } // 模式转换函数:将bitmask转换为上报用的枚举值 lightMode_e convert_mode_for_report(lightMode_e current_mode) { // 如果处于离家模式,上报离家模式 if (LIGHT_MODE_IS_LEAVE(current_mode)) { return LIGHT_MODE_LEAVE; } // 否则上报基础模式 return LIGHT_MODE_GET_BASE(current_mode); }