diff --git a/.gitignore b/.gitignore
index 5e00332..350e6ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
+.cache/
+.spec-workflow/
+.vscode/
*.a
*.so
*.bin
diff --git a/LPT262_PWM_user_guide.md b/LPT262_PWM_user_guide.md
new file mode 100644
index 0000000..85dbb42
--- /dev/null
+++ b/LPT262_PWM_user_guide.md
@@ -0,0 +1,1056 @@
+# WS63 PWM 技术使用文档
+
+## 文档概述
+
+本文档基于WS63平台的PWM驱动实现,为不同经验的开发人员提供PWM(脉宽调制)功能的配置与控制指导。
+
+**适用人群**:
+- 🌱 **新手开发者**:只熟悉0-255亮度控制,希望快速上手PWM
+- 🛠️ **进阶开发者**:需要深入了解PWM参数配置和高级功能
+- 🔍 **系统调试者**:需要问题诊断和性能优化
+
+**平台基础参数**:
+- MCU平台:WS63 (HiSilicon)
+- 系统时钟:80 MHz
+- 计数器位宽:32-bit(u32)
+- PWM版本:CONFIG_PWM_USING_V151
+- 支持特性:多通道、PWM组、相位控制、运行时更新
+
+## 文档导航
+
+### 🌱 新手必读(建议阅读顺序)
+1. **章节1 - 快速入门**: 5分钟了解PWM和快速上手
+2. **章节5 - 参数详解**: 从0-255到PWM参数的转换和理解
+3. **章节11 - 错误处理**: 常见问题解决
+
+### 🛠️ 进阶内容(可选阅读)
+- **章节2-4**: PWM系统架构、API和初始化流程
+- **章节6-10**: 高级功能(频率配置、相位控制、PWM组等)
+- **章节12**: 完整流程图和技术参考
+
+---
+
+## 1. 快速入门(新手必读)
+
+### 1.1 PWM是什么?
+
+PWM就像一个非常快的开关,通过控制"开"和"关"的时间比例来调节LED的亮度、电机的速度等。
+
+**简单理解**:
+- 如果一直开着 = 100%亮度
+- 如果一直关着 = 0%亮度
+- 如果一半时间开、一半时间关 = 50%亮度
+
+### 1.2 你之前的使用方式 vs 现在的PWM方式
+
+**你之前的方式**:
+```c
+// 简单直观,但是功能有限
+set_led_brightness(128); // 0-255范围
+```
+
+**现在的PWM方式**:
+```c
+// 功能强大,但是参数复杂
+pwm_config_t cfg = {
+ .high_time = 40000, // 高电平时间(计数)
+ .low_time = 40000, // 低电平时间(计数)
+ .offset_time = 0, // 相位偏移
+ .repeat = true, // 是否重复
+ .cycles = 0 // 循环次数
+};
+```
+
+**不用担心!**本文档提供了简化函数,让你像以前一样使用0-255的数值。
+
+### 1.3 5分钟快速上手
+
+```c
+// 第1步:初始化PWM系统
+uapi_pwm_init();
+
+// 第2步:使用简化函数设置亮度(就像以前一样)
+set_pwm_brightness_simple(0, 128); // 通道0,50%亮度
+
+// 第3步:启动PWM输出
+uapi_pwm_start(0);
+
+// 完成!LED就会以50%亮度点亮
+```
+
+**简化函数**(复制到你的代码里):
+```c
+// 这个函数让PWM像以前一样简单
+errcode_t set_pwm_brightness_simple(uint8_t channel, uint8_t brightness_0_255)
+{
+ uint32_t frequency = 1000; // 固定1000Hz,适合LED调光
+ float duty_percent = (brightness_0_255 / 255.0f) * 100.0f;
+ uint32_t period_cnt = 80000000 / frequency; // 80000
+ uint32_t high_time = (uint32_t)(period_cnt * duty_percent / 100.0f);
+ uint32_t low_time = period_cnt - high_time;
+
+ pwm_config_t cfg = {
+ .high_time = high_time,
+ .low_time = low_time,
+ .offset_time = 0,
+ .repeat = true,
+ .cycles = 0
+ };
+
+ return uapi_pwm_open(channel, &cfg);
+}
+```
+
+---
+
+## 2. PWM系统架构(进阶内容)
+
+### 2.1 驱动层次结构
+
+```mermaid
+graph TB
+ A[应用层] --> B[PWM驱动接口 pwm.h]
+ B --> C[HAL层 hal_pwm_v151.h]
+ C --> D[寄存器操作层 hal_pwm_v151_regs_op.h]
+ D --> E[硬件寄存器层]
+
+ A --> F[GPIO配置]
+ F --> G[PWM输出引脚]
+
+ A --> I[PWM组控制]
+ I --> J[多通道同步控制]
+
+ style A fill:#e1f5fe
+ style B fill:#f3e5f5
+ style C fill:#e8f5e8
+ style D fill:#fff3e0
+```
+
+### 2.2 PWM工作原理
+
+```mermaid
+graph LR
+ A[频率配置] --> B[周期计算]
+ B --> C[占空比设置]
+ C --> D[high_time/low_time计算]
+ D --> E[PWM波形输出]
+
+ F[相位控制] --> E
+ G[PWM组同步] --> E
+
+ style B fill:#e3f2fd
+ style D fill:#f1f8e9
+ style E fill:#fff3e0
+```
+
+---
+
+## 3. PWM核心数据结构与API(进阶内容)
+
+### 3.1 PWM配置结构体
+
+```c
+// 源码位置:include/driver/pwm.h
+typedef struct pwm_config {
+ uint32_t low_time; // 低电平持续的计数数
+ uint32_t high_time; // 高电平持续的计数数
+ uint32_t offset_time; // PWM相位偏移时间
+ uint16_t cycles; // PWM重复周期,范围:0~32767
+ bool repeat; // 连续输出标志
+} pwm_config_t;
+```
+
+### 3.2 关键API函数
+
+```c
+// PWM系统初始化和控制
+errcode_t uapi_pwm_init(void); // 初始化PWM系统
+errcode_t uapi_pwm_open(uint8_t channel, const pwm_config_t *cfg); // 打开PWM通道
+errcode_t uapi_pwm_start(uint8_t channel); // 启动单个PWM通道
+errcode_t uapi_pwm_close(uint8_t channel); // 关闭PWM通道
+uint32_t uapi_pwm_get_frequency(uint8_t channel); // 获取PWM工作频率
+
+// PWM组控制
+errcode_t uapi_pwm_set_group(uint8_t group, const uint8_t *channel_set, uint32_t channel_set_len);
+errcode_t uapi_pwm_start_group(uint8_t group); // 同步启动PWM组
+errcode_t uapi_pwm_stop_group(uint8_t group); // 同步停止PWM组
+errcode_t uapi_pwm_clear_group(uint8_t group); // 清理PWM组
+
+// 运行时占空比更新
+errcode_t uapi_pwm_update_duty_ratio(uint8_t channel, uint32_t low_time, uint32_t high_time);
+
+// 中断处理
+errcode_t uapi_pwm_register_interrupt(uint8_t channel, pwm_callback_t callback);
+errcode_t uapi_pwm_unregister_interrupt(uint8_t channel);
+```
+
+---
+
+## 4. PWM初始化流程(进阶内容)
+
+### 4.1 初始化时序图
+
+```mermaid
+sequenceDiagram
+ participant App as 应用层
+ participant PWM as PWM驱动
+ participant HAL as HAL层
+ participant GPIO as GPIO系统
+
+ App->>PWM: uapi_pwm_init()
+ PWM->>HAL: hal_pwm_v151初始化
+ HAL-->>PWM: 返回success
+
+ App->>PWM: uapi_pwm_get_frequency(channel)
+ PWM-->>App: 返回基础频率(80MHz)
+
+ App->>App: 计算周期计数值
+
+ App->>GPIO: 配置GPIO引脚为PWM功能
+ GPIO-->>App: GPIO配置完成
+
+ App->>PWM: uapi_pwm_open(channel, config)
+ PWM-->>App: PWM通道配置完成
+
+ App->>PWM: uapi_pwm_start(channel)
+ PWM-->>App: PWM开始输出
+
+ Note over App: PWM波形输出
+```
+
+### 4.2 初始化代码实现
+
+```c
+// PWM初始化示例
+void pwm_init_example(uint8_t gpio_pin, uint32_t target_frequency)
+{
+ pwm_config_t cfg = {0};
+
+ // 1. 初始化PWM驱动
+ errcode_t ret = uapi_pwm_init();
+ if (ret != ERRCODE_SUCC) {
+ printf("PWM初始化失败: %d\n", ret);
+ return;
+ }
+
+ // 2. 获取PWM基础频率 (通常为80MHz)
+ uint8_t channel = gpio_pin % 8; // GPIO转PWM通道
+ uint32_t base_frequency = uapi_pwm_get_frequency(channel);
+
+ // 3. 计算PWM周期计数值
+ uint32_t period_cnt = base_frequency / target_frequency;
+
+ // 4. 配置PWM参数(初始50%占空比)
+ cfg.high_time = period_cnt / 2;
+ cfg.low_time = period_cnt - cfg.high_time;
+ cfg.offset_time = 0; // 无相位偏移
+ cfg.repeat = true; // 连续输出
+ cfg.cycles = 0; // 无限循环
+
+ // 5. 打开PWM通道
+ ret = uapi_pwm_open(channel, &cfg);
+ if (ret != ERRCODE_SUCC) {
+ printf("PWM通道打开失败: %d\n", ret);
+ return;
+ }
+
+ // 6. 启动PWM输出
+ ret = uapi_pwm_start(channel);
+ if (ret != ERRCODE_SUCC) {
+ printf("PWM启动失败: %d\n", ret);
+ return;
+ }
+
+ printf("PWM初始化成功: 频率=%dHz, 周期=%d计数\n",
+ target_frequency, period_cnt);
+}
+```
+
+---
+
+## 5. PWM参数详解(小白入门篇)
+
+### 5.1 什么是PWM?
+
+PWM就像开关灯一样,快速地开关来控制亮度。想象你手里有个开关,如果一直开着,灯就是100%亮;如果一直关着,灯就是0%亮。但如果你快速地开开关关,开的时间长一点,灯就亮一点;关的时间长一点,灯就暗一点。
+
+**关键概念**:
+- **频率**:一秒钟开关多少次(就像你手开关灯的频率)
+- **占空比**:一个开关周期中,"开"的时间占多少比例
+- **周期**:完成一次"开-关"动作需要的时间
+
+### 5.2 从0-255到实际参数的转换
+
+你熟悉的0-255其实就是占空比的另一种表示方法:
+
+```c
+// 你熟悉的方式:0-255的数值
+uint8_t brightness = 128; // 相当于50%亮度
+
+// 转换成PWM需要的参数
+float duty_percent = (brightness / 255.0f) * 100.0f; // 转换成百分比
+
+// 例子:
+// brightness = 0 → duty_percent = 0% (完全不亮)
+// brightness = 64 → duty_percent = 25% (1/4亮度)
+// brightness = 128 → duty_percent = 50% (一半亮度)
+// brightness = 192 → duty_percent = 75% (3/4亮度)
+// brightness = 255 → duty_percent = 100% (最亮)
+```
+
+### 5.3 参数计算原理(用通俗的话解释)
+
+```c
+// 第1步:确定系统时钟(这是硬件固定的,不用改)
+uint32_t system_clock = 80000000; // 80MHz = 每秒8000万次计数
+
+// 第2步:设定PWM频率(就是每秒开关多少次)
+uint32_t pwm_frequency = 1000; // 1000Hz = 每秒开关1000次
+
+// 第3步:计算一个开关周期需要多少个时钟计数
+// 打个比方:如果系统每秒数8000万下,你要让它每秒开关1000次
+// 那么每次开关就需要:8000万 ÷ 1000 = 80000个计数
+uint32_t period_count = system_clock / pwm_frequency;
+
+// 第4步:根据亮度(占空比)计算开和关的时间
+// 如果要60%亮度,那么80000个计数中,48000个用来"开",32000个用来"关"
+float brightness_percent = 60.0; // 60%亮度
+uint32_t on_time = (uint32_t)(period_count * brightness_percent / 100.0);
+uint32_t off_time = period_count - on_time;
+```
+
+### 5.4 简单的参数设置函数(推荐使用)
+
+```c
+// 简化版本:像以前一样用0-255设置亮度
+errcode_t set_pwm_brightness_simple(uint8_t channel, uint8_t brightness_0_255)
+{
+ // 固定使用1000Hz频率(适合大多数LED调光应用)
+ uint32_t frequency = 1000;
+
+ // 将0-255转换为百分比
+ float duty_percent = (brightness_0_255 / 255.0f) * 100.0f;
+
+ // 计算周期计数(80MHz ÷ 1000Hz = 80000)
+ uint32_t period_cnt = 80000000 / frequency;
+
+ // 计算高低电平时间
+ uint32_t high_time = (uint32_t)(period_cnt * duty_percent / 100.0f);
+ uint32_t low_time = period_cnt - high_time;
+
+ // 配置PWM
+ pwm_config_t cfg = {
+ .high_time = high_time, // "开"的时间(计数值)
+ .low_time = low_time, // "关"的时间(计数值)
+ .offset_time = 0, // 不需要相位偏移
+ .repeat = true, // 持续输出
+ .cycles = 0 // 无限循环
+ };
+
+ return uapi_pwm_open(channel, &cfg);
+}
+
+// 使用示例:
+// set_pwm_brightness_simple(0, 0); // 通道0,0%亮度(关闭)
+// set_pwm_brightness_simple(0, 128); // 通道0,50%亮度
+// set_pwm_brightness_simple(0, 255); // 通道0,100%亮度(最亮)
+```
+
+### 5.5 高级参数详解(可选阅读)
+
+```c
+如果你想深入了解PWM的各个参数,这里详细解释每个参数的含义:
+
+**pwm_config_t结构体中的参数:**
+
+1. **high_time(高电平时间)**:
+ - 就是"开关"中"开"的时间,用时钟计数表示
+ - 例如:如果high_time = 40000,系统时钟80MHz,那么"开"的时间 = 40000 ÷ 80000000 = 0.5ms
+
+2. **low_time(低电平时间)**:
+ - 就是"开关"中"关"的时间,用时钟计数表示
+ - 例如:如果low_time = 40000,那么"关"的时间也是0.5ms
+ - high_time + low_time = 一个完整周期的时间
+
+3. **offset_time(相位偏移)**:
+ - 用来控制多个PWM通道之间的时间差
+ - 大多数情况下设为0即可
+ - 高级应用:比如多色LED,可以让红绿蓝三色错开时间启动
+
+4. **cycles(重复次数)**:
+ - 设为0表示无限重复(常用)
+ - 设为具体数字表示输出多少个周期后停止
+
+5. **repeat(连续输出标志)**:
+ - true:持续输出PWM波形(常用)
+ - false:只输出指定次数后停止
+
+```c
+// 标准的占空比设置函数
+errcode_t set_pwm_duty_cycle(uint8_t channel, float duty_cycle_percent)
+{
+ // 参数检查
+ if (duty_cycle_percent < 0.0f) duty_cycle_percent = 0.0f;
+ if (duty_cycle_percent > 100.0f) duty_cycle_percent = 100.0f;
+
+ // 使用固定的1000Hz频率
+ uint32_t period_cnt = 80000; // 80MHz ÷ 1000Hz = 80000
+
+ // 计算高低电平时间
+ uint32_t high_time = (uint32_t)(period_cnt * duty_cycle_percent / 100.0f);
+ uint32_t low_time = period_cnt - high_time;
+
+ // 配置PWM
+ pwm_config_t cfg = {
+ .high_time = high_time,
+ .low_time = low_time,
+ .offset_time = 0, // 无相位偏移
+ .repeat = true, // 持续输出
+ .cycles = 0 // 无限循环
+ };
+
+ return uapi_pwm_open(channel, &cfg);
+}
+
+// 运行时更新占空比(V151版本)
+errcode_t update_pwm_duty_runtime(uint8_t channel, float duty_cycle_percent)
+{
+ // V151需要重新配置整个通道来更新占空比
+ return set_pwm_duty_cycle(channel, duty_cycle_percent);
+}
+```
+
+```
+
+### 5.6 完整的PWM使用示例(推荐新手使用)
+
+```c
+// 完整的PWM初始化和使用流程
+void pwm_simple_example(void)
+{
+ // 第1步:初始化PWM系统
+ if (uapi_pwm_init() != ERRCODE_SUCC) {
+ printf("PWM初始化失败!\n");
+ return;
+ }
+
+ // 第2步:配置GPIO引脚为PWM功能(这里假设已经配置好)
+
+ // 第3步:设置PWM通道0的亮度
+ uint8_t channel = 0; // 使用PWM通道0
+
+ // 设置不同亮度测试
+ printf("开始PWM亮度测试...\n");
+
+ // 0% 亮度(关闭)
+ set_pwm_brightness_simple(channel, 0);
+ uapi_pwm_start(channel);
+ printf("当前亮度: 0%% (关闭)\n");
+ // delay_ms(1000); // 延时1秒
+
+ // 25% 亮度
+ set_pwm_brightness_simple(channel, 64);
+ printf("当前亮度: 25%%\n");
+ // delay_ms(1000);
+
+ // 50% 亮度
+ set_pwm_brightness_simple(channel, 128);
+ printf("当前亮度: 50%%\n");
+ // delay_ms(1000);
+
+ // 75% 亮度
+ set_pwm_brightness_simple(channel, 192);
+ printf("当前亮度: 75%%\n");
+ // delay_ms(1000);
+
+ // 100% 亮度(最亮)
+ set_pwm_brightness_simple(channel, 255);
+ printf("当前亮度: 100%% (最亮)\n");
+
+ printf("PWM测试完成!\n");
+}
+
+// 渐变效果示例
+void pwm_fade_example(void)
+{
+ uint8_t channel = 0;
+
+ // 从暗到亮的渐变
+ printf("渐亮效果...\n");
+ for (int brightness = 0; brightness <= 255; brightness += 5) {
+ set_pwm_brightness_simple(channel, brightness);
+ // delay_ms(50); // 每步延时50ms,实现平滑渐变
+ }
+
+ // 从亮到暗的渐变
+ printf("渐暗效果...\n");
+ for (int brightness = 255; brightness >= 0; brightness -= 5) {
+ set_pwm_brightness_simple(channel, brightness);
+ // delay_ms(50);
+ }
+
+ printf("渐变效果完成!\n");
+}
+```
+
+---
+
+## 6. PWM频率与周期配置(进阶内容)
+
+### 6.1 常用频率配置表
+
+**基于80MHz系统时钟的配置参数**:
+
+| 目标频率 | 周期计数值 | 周期时间 | 最小占空比步进 | 应用场景 | 说明 |
+|----------|------------|----------|----------------|----------|------|
+| 100 Hz | 800,000 | 10.0 ms | 0.000125% | 低频控制 | 人眼可见闪烁 |
+| 1 kHz | 80,000 | 1.0 ms | 0.00125% | LED调光 | **推荐频率** - 无闪烁,适合照明 |
+| 10 kHz | 8,000 | 100 μs | 0.0125% | 音频PWM | 超出听觉范围 |
+| 20 kHz | 4,000 | 50 μs | 0.025% | 电机控制 | 无噪音,适合电机驱动 |
+| 100 kHz | 800 | 10 μs | 0.125% | 高频开关 | 开关电源应用 |
+| 1 MHz | 80 | 1 μs | 1.25% | 快速响应 | 高速信号生成 |
+
+### 6.2 频率配置示例
+
+```c
+// 不同应用场景的频率配置
+typedef struct {
+ uint32_t frequency;
+ uint32_t period_cnt;
+ const char* application;
+} pwm_freq_preset_t;
+
+const pwm_freq_preset_t pwm_presets[] = {
+ {100, 800000, "低频控制信号(有闪烁)"},
+ {1000, 80000, "LED调光(推荐使用)"},
+ {20000, 4000, "电机控制(无噪音)"},
+ {100000, 800, "高频开关电源"},
+ {1000000, 80, "高速信号生成"}
+};
+
+// 快速配置函数
+errcode_t pwm_quick_setup(uint8_t channel, uint8_t preset_index, float duty_percent)
+{
+ if (preset_index >= sizeof(pwm_presets)/sizeof(pwm_presets[0])) {
+ return ERRCODE_INVALID_PARAM;
+ }
+
+ const pwm_freq_preset_t* preset = &pwm_presets[preset_index];
+
+ uint32_t high_time = (uint32_t)(preset->period_cnt * duty_percent / 100.0f);
+ uint32_t low_time = preset->period_cnt - high_time;
+
+ pwm_config_t cfg = {
+ .high_time = high_time,
+ .low_time = low_time,
+ .repeat = true
+ };
+
+ printf("配置PWM: %s\n", preset->application);
+ printf(" - 频率: %dHz\n", preset->frequency);
+ printf(" - 占空比: %.1f%%\n", duty_percent);
+ printf(" - 周期时间: %.2fms\n", 1000.0f / preset->frequency);
+
+ return uapi_pwm_open(channel, &cfg);
+}
+```
+
+---
+
+## 7. PWM波形与相位控制(进阶内容)
+
+### 7.1 PWM波形分析
+
+```
+基本PWM波形 (以1kHz频率,60%占空比为例):
+
+周期 = 1ms (80000计数)
+高电平时间 = 0.6ms (48000计数)
+低电平时间 = 0.4ms (32000计数)
+
+ ████████████████████████████████ ████████████████████████████████
+____ ________ ____
+ |←─────── 48000 cnt ────────→| |←─────── 48000 cnt ────────→|
+ |←─────────────── 80000 cnt (1ms) ──────────→|←──────────── 80000 cnt ──────→|
+```
+
+### 7.2 相位偏移控制
+
+```c
+// 相位偏移示例:两个PWM通道错相输出
+void setup_phase_shifted_pwm(uint8_t ch1, uint8_t ch2, uint32_t frequency, float duty_percent)
+{
+ uint32_t period_cnt = 80000000 / frequency;
+ uint32_t high_time = (uint32_t)(period_cnt * duty_percent / 100.0f);
+ uint32_t low_time = period_cnt - high_time;
+
+ // 通道1:正常输出
+ pwm_config_t cfg1 = {
+ .high_time = high_time,
+ .low_time = low_time,
+ .offset_time = 0, // 无偏移
+ .repeat = true
+ };
+
+ // 通道2:相位偏移180度
+ pwm_config_t cfg2 = {
+ .high_time = high_time,
+ .low_time = low_time,
+ .offset_time = period_cnt / 2, // 半周期偏移
+ .repeat = true
+ };
+
+ uapi_pwm_open(ch1, &cfg1);
+ uapi_pwm_open(ch2, &cfg2);
+ uapi_pwm_start(ch1);
+ uapi_pwm_start(ch2);
+}
+```
+
+### 7.3 互补输出波形
+
+```
+互补PWM输出 (避免直通,添加死区时间):
+
+Channel A: ████████ ████████ ████████
+Channel B: ████████ ████████ ████████
+ |dt| |dt| |dt| |dt| |dt| |dt|
+ 死区 死区 死区 死区 死区 死区
+
+死区时间计算:
+dead_time_ns = 500; // 500ns死区
+dead_time_cnt = (500 * 80000000) / 1000000000 = 40计数
+```
+
+---
+
+## 8. PWM组同步控制(进阶内容)
+
+### 8.1 PWM组管理
+
+```c
+// PWM组配置和同步控制
+#define PWM_GROUP_0 0
+#define MAX_CHANNELS_PER_GROUP 8
+
+errcode_t setup_pwm_group(uint8_t group_id, uint8_t* channels, uint8_t channel_count)
+{
+ errcode_t ret;
+
+ // 1. 清除现有组配置
+ ret = uapi_pwm_clear_group(group_id);
+ if (ret != ERRCODE_SUCC) return ret;
+
+ // 2. 设置新的PWM组
+ ret = uapi_pwm_set_group(group_id, channels, channel_count);
+ if (ret != ERRCODE_SUCC) return ret;
+
+ printf("PWM组%d配置完成,包含%d个通道\n", group_id, channel_count);
+
+ return ERRCODE_SUCC;
+}
+
+// 同步启动PWM组
+errcode_t start_pwm_group_sync(uint8_t group_id)
+{
+ return uapi_pwm_start_group(group_id);
+}
+
+// 同步停止PWM组
+errcode_t stop_pwm_group_sync(uint8_t group_id)
+{
+ return uapi_pwm_stop_group(group_id);
+}
+```
+
+### 8.2 组同步流程
+
+```mermaid
+sequenceDiagram
+ participant App as 应用层
+ participant Group as PWM组控制
+ participant CH0 as 通道0
+ participant CH1 as 通道1
+ participant CH2 as 通道2
+
+ App->>Group: uapi_pwm_set_group(0, [0,1,2])
+ Group->>CH0: 加入组0
+ Group->>CH1: 加入组0
+ Group->>CH2: 加入组0
+
+ App->>CH0: uapi_pwm_open(0, config0)
+ App->>CH1: uapi_pwm_open(1, config1)
+ App->>CH2: uapi_pwm_open(2, config2)
+
+ App->>Group: uapi_pwm_start_group(0)
+ Group->>CH0: 同步启动
+ Group->>CH1: 同步启动
+ Group->>CH2: 同步启动
+
+ Note over CH0,CH2: 所有通道同时开始PWM输出
+```
+
+---
+
+## 9. 动态PWM调整(进阶内容)
+
+### 9.1 运行时参数更新
+
+```c
+// 动态调整PWM参数
+errcode_t dynamic_pwm_update(uint8_t channel, uint32_t new_frequency, float new_duty_percent)
+{
+ // 计算新参数
+ uint32_t period_cnt = 80000000 / new_frequency;
+ uint32_t high_time = (uint32_t)(period_cnt * new_duty_percent / 100.0f);
+ uint32_t low_time = period_cnt - high_time;
+
+ // 重新配置PWM
+ pwm_config_t cfg = {
+ .high_time = high_time,
+ .low_time = low_time,
+ .repeat = true
+ };
+
+ errcode_t ret = uapi_pwm_open(channel, &cfg);
+ if (ret != ERRCODE_SUCC) {
+ return ret;
+ }
+
+ return uapi_pwm_start(channel);
+}
+
+// 渐变调节函数
+typedef struct {
+ uint8_t channel;
+ float current_duty;
+ float target_duty;
+ float step_size;
+ uint32_t interval_ms;
+} pwm_fade_t;
+
+void pwm_fade_step(pwm_fade_t* fade)
+{
+ if (abs(fade->current_duty - fade->target_duty) < fade->step_size) {
+ fade->current_duty = fade->target_duty;
+ return; // 渐变完成
+ }
+
+ if (fade->current_duty < fade->target_duty) {
+ fade->current_duty += fade->step_size;
+ } else {
+ fade->current_duty -= fade->step_size;
+ }
+
+ set_pwm_duty_cycle(fade->channel, fade->current_duty);
+}
+```
+
+### 9.2 PWM调制模式
+
+```c
+// PWM调制模式示例
+typedef enum {
+ PWM_MODE_CONSTANT, // 恒定输出
+ PWM_MODE_BREATHING, // 呼吸模式
+ PWM_MODE_BLINKING, // 闪烁模式
+ PWM_MODE_SAWTOOTH, // 锯齿波模式
+} pwm_modulation_mode_t;
+
+typedef struct {
+ uint8_t channel;
+ pwm_modulation_mode_t mode;
+ uint32_t period_ms; // 调制周期
+ float min_duty; // 最小占空比
+ float max_duty; // 最大占空比
+ uint32_t step_count; // 步数
+} pwm_modulation_t;
+
+void pwm_modulation_update(pwm_modulation_t* mod, uint32_t current_step)
+{
+ float duty = mod->min_duty;
+
+ switch (mod->mode) {
+ case PWM_MODE_BREATHING:
+ // 正弦波呼吸
+ duty = mod->min_duty + (mod->max_duty - mod->min_duty) *
+ (1.0f + sinf(2 * 3.14159f * current_step / mod->step_count)) / 2.0f;
+ break;
+
+ case PWM_MODE_SAWTOOTH:
+ // 锯齿波
+ duty = mod->min_duty + (mod->max_duty - mod->min_duty) *
+ current_step / mod->step_count;
+ break;
+
+ case PWM_MODE_BLINKING:
+ // 方波闪烁
+ duty = (current_step < mod->step_count/2) ? mod->max_duty : mod->min_duty;
+ break;
+
+ default:
+ duty = mod->max_duty;
+ break;
+ }
+
+ set_pwm_duty_cycle(mod->channel, duty);
+}
+```
+
+---
+
+## 10. PWM应用示例(进阶内容)
+
+### 10.1 电机PWM控制
+
+```c
+// 电机PWM控制示例
+void motor_pwm_control(uint8_t motor_channel, float speed_percent, bool direction)
+{
+ // 电机PWM频率通常选择20kHz以避免听到噪音
+ uint32_t motor_frequency = 20000;
+
+ // 限制速度范围
+ if (speed_percent < 0) speed_percent = 0;
+ if (speed_percent > 100) speed_percent = 100;
+
+ // 计算周期和占空比
+ uint32_t period_cnt = 80000000 / motor_frequency;
+ uint32_t high_time = (uint32_t)(period_cnt * speed_percent / 100.0f);
+ uint32_t low_time = period_cnt - high_time;
+
+ pwm_config_t cfg = {
+ .high_time = high_time,
+ .low_time = low_time,
+ .repeat = true
+ };
+
+ uapi_pwm_open(motor_channel, &cfg);
+ uapi_pwm_start(motor_channel);
+
+ // 方向控制需要额外的GPIO控制
+ // gpio_set_direction_pin(direction);
+
+ printf("电机PWM: 速度=%.1f%%, 方向=%s\n",
+ speed_percent, direction ? "正转" : "反转");
+}
+```
+
+### 10.2 伺服电机控制
+
+```c
+// 伺服电机PWM控制 (50Hz, 1-2ms脉宽)
+void servo_pwm_control(uint8_t servo_channel, float angle_degrees)
+{
+ // 伺服PWM频率固定为50Hz (20ms周期)
+ uint32_t servo_frequency = 50;
+ uint32_t period_cnt = 80000000 / servo_frequency; // 1,600,000计数 (20ms)
+
+ // 角度范围限制 (-90° 到 +90°)
+ if (angle_degrees < -90) angle_degrees = -90;
+ if (angle_degrees > 90) angle_degrees = 90;
+
+ // 脉宽计算:1ms(-90°) 到 2ms(+90°)
+ float pulse_width_ms = 1.5f + (angle_degrees / 90.0f) * 0.5f;
+ uint32_t high_time = (uint32_t)(80000 * pulse_width_ms); // 80000计数/ms
+ uint32_t low_time = period_cnt - high_time;
+
+ pwm_config_t cfg = {
+ .high_time = high_time,
+ .low_time = low_time,
+ .repeat = true
+ };
+
+ uapi_pwm_open(servo_channel, &cfg);
+ uapi_pwm_start(servo_channel);
+
+ printf("伺服控制: 角度=%.1f°, 脉宽=%.2fms\n", angle_degrees, pulse_width_ms);
+}
+```
+
+### 10.3 音频PWM输出
+
+```c
+// 简单音频PWM输出
+void audio_pwm_tone(uint8_t audio_channel, uint32_t tone_frequency, uint32_t duration_ms)
+{
+ // 音频PWM载波频率选择高于20kHz
+ uint32_t carrier_frequency = 44100; // 44.1kHz载波
+
+ uint32_t period_cnt = 80000000 / carrier_frequency;
+
+ // 音频调制(简单50%占空比)
+ uint32_t high_time = period_cnt / 2;
+ uint32_t low_time = period_cnt - high_time;
+
+ pwm_config_t cfg = {
+ .high_time = high_time,
+ .low_time = low_time,
+ .repeat = true
+ };
+
+ uapi_pwm_open(audio_channel, &cfg);
+ uapi_pwm_start(audio_channel);
+
+ // 持续时间控制
+ // delay_ms(duration_ms);
+ // uapi_pwm_stop(audio_channel);
+
+ printf("音频输出: 载波=%dHz, 持续=%dms\n", carrier_frequency, duration_ms);
+}
+```
+
+---
+
+## 11. 错误处理与调试
+
+### 11.1 常见问题诊断
+
+| 问题现象 | 可能原因 | 解决方案 | 验证方法 |
+|----------|----------|----------|----------|
+| PWM无输出 | 通道未启动 | 调用uapi_pwm_start() | 示波器检查引脚 |
+| 频率不正确 | 计算错误 | 检查period_cnt计算 | 频率计测量 |
+| 占空比异常 | high_time设置错误 | 检查占空比计算公式 | 占空比测量 |
+| 多通道不同步 | 未使用PWM组 | 使用uapi_pwm_start_group() | 示波器多通道观察 |
+| PWM抖动 | 中断影响 | 关闭不必要中断 | 波形稳定性分析 |
+
+### 11.2 调试代码示例
+
+```c
+// PWM状态监控和调试
+void pwm_debug_info(uint8_t channel)
+{
+ uint32_t frequency = uapi_pwm_get_frequency(channel);
+ printf("=== PWM通道%d调试信息 ===\n", channel);
+ printf("基础频率: %d Hz\n", frequency);
+ printf("系统时钟: 80MHz\n");
+
+ // 假设当前配置
+ uint32_t target_freq = 1000;
+ uint32_t period_cnt = 80000000 / target_freq;
+ float duty_cycle = 60.0f;
+ uint32_t high_time = (uint32_t)(period_cnt * duty_cycle / 100.0f);
+ uint32_t low_time = period_cnt - high_time;
+
+ printf("目标频率: %d Hz\n", target_freq);
+ printf("周期计数: %d\n", period_cnt);
+ printf("高电平计数: %d (%.2fms)\n", high_time, (float)high_time/80000);
+ printf("低电平计数: %d (%.2fms)\n", low_time, (float)low_time/80000);
+ printf("占空比: %.1f%%\n", duty_cycle);
+ printf("实际周期: %.2fms\n", (float)period_cnt/80000);
+}
+
+// PWM波形验证
+bool verify_pwm_output(uint8_t channel, uint32_t expected_freq, float expected_duty)
+{
+ // 这里需要硬件支持或外部测量设备
+ // 返回验证结果
+ printf("验证PWM通道%d: 期望频率=%dHz, 期望占空比=%.1f%%\n",
+ channel, expected_freq, expected_duty);
+ return true; // 简化示例
+}
+```
+
+### 11.3 性能优化建议
+
+```c
+// PWM性能优化建议
+void pwm_performance_tips(void)
+{
+ // 1. 使用PWM组进行批量操作
+ uint8_t channels[] = {0, 1, 2, 3};
+ uapi_pwm_set_group(0, channels, 4);
+ uapi_pwm_start_group(0); // 比逐个启动效率高
+
+ // 2. 避免频繁的参数更改
+ // 缓存计算结果,批量更新
+
+ // 3. 合理选择PWM频率
+ // 过高频率会增加功耗,过低可能产生可见闪烁
+
+ // 4. 使用合适的占空比精度
+ // 不需要过高精度时使用整数运算
+
+ // 5. 中断优化
+ // 只在必要时注册PWM中断回调
+}
+```
+
+---
+
+## 12. 完整PWM控制流程
+
+### 12.1 PWM完整使用流程
+
+```mermaid
+flowchart TD
+ A[系统启动] --> B[uapi_pwm_init 初始化]
+ B --> C[GPIO配置为PWM功能]
+ C --> D[计算PWM参数]
+
+ D --> E{单通道?}
+ E -->|是| F[uapi_pwm_open 配置通道]
+ E -->|否| G[uapi_pwm_set_group 配置组]
+
+ F --> H[uapi_pwm_start 启动单通道]
+ G --> I[批量配置各通道]
+ I --> J[uapi_pwm_start_group 同步启动]
+
+ H --> K[PWM波形输出]
+ J --> K
+
+ K --> L{需要调整?}
+ L -->|是| M[更新参数]
+ L -->|否| N[持续运行]
+
+ M --> O[uapi_pwm_open 重新配置]
+ O --> K
+
+ N --> P{停止?}
+ P -->|否| L
+ P -->|是| Q[uapi_pwm_close 关闭]
+ Q --> R[结束]
+
+ style B fill:#e3f2fd
+ style D fill:#f1f8e9
+ style K fill:#fff3e0
+ style O fill:#e8f5e8
+```
+
+---
+
+## 附录:技术参考
+
+### A.1 WS63 PWM技术规格
+
+| 规格项 | 参数值 | 说明 |
+|--------|--------|------|
+| 系统时钟 | 80 MHz | PWM计数基准 |
+| 计数器位宽 | 32-bit | 支持超长周期 |
+| PWM通道数 | 8 | 每组最多8通道 |
+| PWM组数 | 多组 | 支持同步控制 |
+| 最高频率 | 40 MHz | 理论最大值 |
+| 最低频率 | 1.2 Hz | 32位计数器极限 |
+| 占空比精度 | 0.0000012% | 32位分辨率 |
+| 相位控制 | 支持 | offset_time参数 |
+
+### A.2 应用场景频率推荐
+
+| 应用场景 | 推荐频率 | 原因 |
+|----------|----------|------|
+| LED调光 | 1-20 kHz | 避免频闪,超出人眼感知 |
+| 电机控制 | 10-50 kHz | 超出听觉范围,降低噪音 |
+| 伺服控制 | 50 Hz | 伺服电机标准频率 |
+| 开关电源 | 100-500 kHz | 减小磁性元件尺寸 |
+| 音频输出 | 20-100 kHz | 超出人类听觉范围 |
+| 数字通信 | 1-10 MHz | 高速数据传输 |
+
+---
+
+**文档版本**:V3.0
+**更新日期**:2025年
+**适用平台**:WS63 (HiSilicon)
+**PWM版本**:CONFIG_PWM_USING_V151
+**系统时钟**:80MHz
+
+本文档提供通用PWM技术指导,适用于各种基于WS63平台的PWM应用开发。
\ No newline at end of file
diff --git a/PWM参数计算详解.md b/PWM参数计算详解.md
new file mode 100644
index 0000000..ab354e3
--- /dev/null
+++ b/PWM参数计算详解.md
@@ -0,0 +1,320 @@
+# PWM参数计算详解(通俗易懂版)
+
+## 文档说明
+
+本文档专门解释PWM的各个参数计算原理,用通俗的语言和图表帮助理解复杂的PWM概念。适合只熟悉0-255亮度控制的开发者快速理解PWM参数。
+
+---
+
+## 1. 什么是PWM?
+
+PWM就像开关灯一样,快速地开关来控制亮度。想象你手里有个开关,如果一直开着,灯就是100%亮;如果一直关着,灯就是0%亮。但如果你快速地开开关关,开的时间长一点,灯就亮一点;关的时间长一点,灯就暗一点。
+
+### PWM波形图解
+
+```
+100%亮度 (一直开着):
+████████████████████████████████████████████████████
+
+50%亮度 (一半时间开,一半时间关):
+████████ ████████ ████████ ████
+
+25%亮度 (1/4时间开,3/4时间关):
+████ ████ ████ ████ ████ ████ ████
+
+0%亮度 (一直关着):
+________________________________________________
+```
+
+### 关键概念图解
+
+```mermaid
+graph LR
+ A[频率
每秒开关多少次] --> B[周期
一次开关的总时间]
+ B --> C[占空比
开的时间占比例]
+ C --> D[亮度效果
人眼感知的亮度]
+
+ style A fill:#e3f2fd
+ style B fill:#f1f8e9
+ style C fill:#fff3e0
+ style D fill:#fce4ec
+```
+
+---
+
+## 2. 从0-255到实际参数的转换
+
+### 2.1 对应关系表
+
+| 你熟悉的数值 | 百分比 | PWM术语 | 实际效果 |
+|-------------|--------|---------|----------|
+| 0 | 0% | 0%占空比 | 完全不亮 |
+| 64 | 25% | 25%占空比 | 1/4亮度 |
+| 128 | 50% | 50%占空比 | 一半亮度 |
+| 192 | 75% | 75%占空比 | 3/4亮度 |
+| 255 | 100% | 100%占空比 | 最亮 |
+
+### 2.2 转换公式
+
+```c
+// 从你熟悉的0-255转换到百分比
+uint8_t brightness = 128; // 你设置的亮度值
+float duty_percent = (brightness / 255.0f) * 100.0f; // 转换成百分比
+
+// 例子:
+// brightness = 0 → duty_percent = 0% (完全不亮)
+// brightness = 64 → duty_percent = 25% (1/4亮度)
+// brightness = 128 → duty_percent = 50% (一半亮度)
+// brightness = 192 → duty_percent = 75% (3/4亮度)
+// brightness = 255 → duty_percent = 100% (最亮)
+```
+
+---
+
+## 3. PWM参数计算原理
+
+### 3.1 基础概念图解
+
+```
+系统就像一个超快的时钟(80MHZ),每秒"滴答(cycle)"8000万次,每个滴答节奏所对应的时间是固定的。
+也就是这个PWM的最高精度就是(1/80*1000*1000)s =
+
+如果我们要让PWM 1000HZ,也就是每秒开关1000次:
+那么每次开关需要:80M ÷ 1000 = 80000 cycle所对应的时间
+所以我们控制PWM本质上是控制这个PWM,一个周期的cycle总个数以及比例分配。
+
+比如我要 PWM 是1KHZ
+首先计算,1KHZ 一个PWM周期就是1/1000s 也就是1ms
+然后计算1ms 对应多少个cycle: 0.001 / (1/80*1000*1000) = 80,000
+然后再根据占空比去分配这 80,000 个数字就行了
+只要确保high_time low_time加起来是8000就行
+
+```
+
+### 3.2 时间轴图解
+
+```
+一个PWM周期 (1000Hz = 1ms):
+
+0 20000 40000 60000 80000
+|---------|---------|---------|---------|
+ 25% 50% 75% 100%
+
+如果要50%亮度:
+████████████████████████████████████████
+|←----- 开40000-----→|←---- 关40000 ----|
+
+如果要75%亮度:
+████████████████████████████████████████████████████████
+|←-------- 开 (60000滴答) ---------→|←- 关 (20000滴答) -|
+```
+
+### 3.3 计算步骤详解
+
+```c
+// 第1步:确定系统时钟(这是硬件固定的,不用改)
+uint32_t system_clock = 80000000; // 80MHz = 每秒8000万次计数
+
+// 第2步:设定PWM频率(就是每秒开关多少次)
+uint32_t pwm_frequency = 1000; // 1000Hz = 每秒开关1000次
+
+// 第3步:计算一个开关周期需要多少个时钟计数
+// 打个比方:如果系统每秒有8000万下,你要让它每秒开关1000次
+// 那么每次开关就需要:8000万 ÷ 1000 = 80000个计数
+uint32_t period_count = system_clock / pwm_frequency;
+
+// 第4步:根据亮度(占空比)计算开和关的时间
+// 如果要60%亮度,那么80000个计数中,48000个用来"开",32000个用来"关"
+float brightness_percent = 60.0; // 60%亮度
+uint32_t on_time = (uint32_t)(period_count * brightness_percent / 100.0);
+uint32_t off_time = period_count - on_time;
+
+// 结果:
+// on_time = 48000 (开的时间)
+// off_time = 32000 (关的时间)
+```
+
+---
+
+## 4. PWM参数详解图表
+
+### 4.1 pwm_config_t结构体参数图解
+
+```c
+typedef struct pwm_config {
+ uint32_t high_time; // 高电平时间("开"的时间,用计数表示)
+ uint32_t low_time; // 低电平时间("关"的时间,用计数表示)
+ uint32_t offset_time; // 相位偏移时间(延迟启动时间)
+ uint16_t cycles; // 重复次数(0=无限重复)
+ bool repeat; // 连续输出标志(true=一直输出)
+} pwm_config_t;
+```
+
+### 4.2 参数关系图
+
+```mermaid
+graph TB
+ A[一个PWM周期] --> B[high_time
开的时间]
+ A --> C[low_time
关的时间]
+
+ B --> D[占空比 = high_time / (high_time + low_time)]
+ C --> D
+
+ D --> E[最终亮度效果]
+
+ F[offset_time
延迟启动] --> G[多通道同步控制]
+ H[cycles
重复次数] --> I[输出控制]
+ J[repeat
连续标志] --> I
+
+ style A fill:#e3f2fd
+ style D fill:#f1f8e9
+ style E fill:#fff3e0
+```
+
+### 4.3 各参数的通俗解释
+
+#### **high_time(高电平时间)**
+- **通俗理解**:就是"开关"中"开"的时间,用时钟计数表示
+- **计算方法**:`high_time = 周期计数 × 亮度百分比`
+- **例子**:如果high_time = 40000,系统时钟80MHz,那么"开"的时间 = 40000 ÷ 80000000 = 0.5ms
+
+#### **low_time(低电平时间)**
+- **通俗理解**:就是"开关"中"关"的时间,用时钟计数表示
+- **计算方法**:`low_time = 周期计数 - high_time`
+- **例子**:如果low_time = 40000,那么"关"的时间也是0.5ms
+
+#### **offset_time(相位偏移)**
+- **通俗理解**:延迟多长时间再开始PWM输出
+- **使用场景**:多个LED需要错开时间启动,避免同时启动造成电流冲击
+- **大多数情况**:设为0即可
+
+#### **cycles(重复次数)**
+- **通俗理解**:PWM波形重复多少次后停止
+- **常用设置**:
+ - `0`:无限重复(最常用)
+ - `具体数字`:输出指定次数后停止
+
+#### **repeat(连续输出标志)**
+- **通俗理解**:是否持续输出PWM波形
+- **常用设置**:
+ - `true`:持续输出(最常用)
+ - `false`:只输出指定次数后停止
+
+---
+
+## 5. 实际计算示例
+
+### 5.1 示例1:设置50%亮度
+
+```c
+// 目标:PWM频率1000Hz,50%亮度
+
+// 第1步:计算周期计数
+uint32_t period_cnt = 80000000 / 1000; // = 80000
+
+// 第2步:计算高低电平时间
+uint32_t high_time = 80000 * 50 / 100; // = 40000
+uint32_t low_time = 80000 - 40000; // = 40000
+
+// 第3步:配置PWM
+pwm_config_t cfg = {
+ .high_time = 40000, // "开" 0.5ms
+ .low_time = 40000, // "关" 0.5ms
+ .offset_time = 0, // 不延迟
+ .repeat = true, // 持续输出
+ .cycles = 0 // 无限重复
+};
+```
+
+### 5.2 示例2:设置75%亮度
+
+```c
+// 目标:PWM频率1000Hz,75%亮度
+
+uint32_t period_cnt = 80000;
+uint32_t high_time = 80000 * 75 / 100; // = 60000
+uint32_t low_time = 80000 - 60000; // = 20000
+
+pwm_config_t cfg = {
+ .high_time = 60000, // "开" 0.75ms (更长)
+ .low_time = 20000, // "关" 0.25ms (更短)
+ .offset_time = 0,
+ .repeat = true,
+ .cycles = 0
+};
+```
+
+### 5.3 波形对比图
+
+```
+50%占空比 (high_time=40000, low_time=40000):
+████████████████████████████████████████ ████████████████████████████████████████
+|←-------- 0.5ms ------→|←-- 0.5ms --→| |←-------- 0.5ms ------→|←-- 0.5ms --→|
+
+75%占空比 (high_time=60000, low_time=20000):
+████████████████████████████████████████████████████████ ████████████████████████████████████████████████████████
+|←-------------- 0.75ms ------------→|0.25ms| |←-------------- 0.75ms ------------→|0.25ms|
+
+25%占空比 (high_time=20000, low_time=60000):
+████████████████████ ████████████████████
+|←-- 0.25ms --→|←---- 0.75ms ----→| |←-- 0.25ms --→|←---- 0.75ms ----→|
+```
+---
+
+## 7. 简化使用函数
+
+### 7.1 推荐的简化函数
+
+```c
+// 这个函数让PWM像以前一样简单
+errcode_t set_pwm_brightness_simple(uint8_t channel, uint8_t brightness_0_255)
+{
+ // 固定使用1000Hz频率,适合LED调光
+ uint32_t frequency = 1000;
+
+ // 将0-255转换为百分比
+ float duty_percent = (brightness_0_255 / 255.0f) * 100.0f;
+
+ // 计算周期计数(80MHz ÷ 1000Hz = 80000)
+ uint32_t period_cnt = 80000000 / frequency;
+
+ // 计算高低电平时间
+ uint32_t high_time = (uint32_t)(period_cnt * duty_percent / 100.0f);
+ uint32_t low_time = period_cnt - high_time;
+
+ // 配置PWM
+ pwm_config_t cfg = {
+ .high_time = high_time, // "开"的时间(计数值)
+ .low_time = low_time, // "关"的时间(计数值)
+ .offset_time = 0, // 不需要相位偏移
+ .repeat = true, // 持续输出
+ .cycles = 0 // 无限循环
+ };
+
+ return uapi_pwm_open(channel, &cfg);
+}
+```
+
+---
+
+## 8. 常见问题解答
+
+### Q1: 为什么不能直接用0-255,要用这些复杂参数?
+**A**: PWM硬件需要知道具体的时钟计数,不是百分比。就像你告诉司机"开快点",司机需要知道具体开多少码一样。
+
+### Q2: high_time和low_time的单位是什么?
+**A**: 单位是时钟计数次数,不是时间。1个计数 = 1/80000000秒 = 12.5纳秒。
+
+### Q3: 为什么推荐1000Hz频率?
+**A**:
+- 高于100Hz:人眼看不到闪烁
+- 低于20kHz:不会产生高频噪音
+- 1000Hz刚好在这个范围内,且计算简单
+
+### Q4: offset_time什么时候用?
+**A**: 主要用于多通道同步,比如RGB灯的三个颜色错开启动,避免电流冲击。
+
+### Q5: 如何实现渐变效果?
+**A**: 在循环中逐步改变brightness_0_255的值,每次改变后调用set_pwm_brightness_simple()。
+
+---
diff --git a/application/samples/wifi/ohos_connect/hilink_adapt/adapter/oh_sle_srv_ssap_server.c b/application/samples/wifi/ohos_connect/hilink_adapt/adapter/oh_sle_srv_ssap_server.c
index 041ecea..ba672b0 100755
--- a/application/samples/wifi/ohos_connect/hilink_adapt/adapter/oh_sle_srv_ssap_server.c
+++ b/application/samples/wifi/ohos_connect/hilink_adapt/adapter/oh_sle_srv_ssap_server.c
@@ -54,11 +54,15 @@ errcode_t SsapsAddDescriptorSync(uint8_t serverId, uint16_t serviceHandle, uint1
return ssaps_add_descriptor_sync(serverId, serviceHandle, propertyHandle, (ssaps_desc_info_t *)descriptor);
}
+#define DEFAULT_SLE_SPEED_MTU_SIZE 1500
errcode_t SsapsStartService(uint8_t serverId, uint16_t serviceHandle)
{
+ SsapcExchangeInfo info = {0};
+ info.mtuSize = DEFAULT_SLE_SPEED_MTU_SIZE;
+ info.version = 1;
+ SsapsSetInfo(serverId, &info);
return ssaps_start_service(serverId, serviceHandle);
}
-
errcode_t SsapsDeleteAllServices(uint8_t serverId)
{
return ssaps_delete_all_services(serverId);
diff --git a/application/samples/wifi/ohos_connect/hilink_adapt/entry/hilink_ble_main.c b/application/samples/wifi/ohos_connect/hilink_adapt/entry/hilink_ble_main.c
index ce4d209..dbc4c4e 100755
--- a/application/samples/wifi/ohos_connect/hilink_adapt/entry/hilink_ble_main.c
+++ b/application/samples/wifi/ohos_connect/hilink_adapt/entry/hilink_ble_main.c
@@ -294,7 +294,7 @@ static void HILINK_BT_StateChangeHandler(HILINK_BT_SdkStatus event, const void *
HILINK_SAL_ERROR("set addr err\n");
}
/* 设置蓝牙广播格式,包括靠近发现、碰一碰等,下一次发送广播生效 */
- BLE_SetAdvType(BLE_ADV_NEARBY_V0);
+ BLE_SetAdvType(BLE_ADV_LOCAL_NAME);
/* BLE配网广播控制:参数代表广播时间,0:停止;0xFFFFFFFF:一直广播,其他:广播指定时间后停止,单位秒 */
if(ble_adv_time) {
@@ -617,7 +617,7 @@ int hilink_ble_main(void)
}
/* 设置广播方式为靠近发现 */
- BLE_SetAdvType(BLE_ADV_NEARBY_V0);
+ BLE_SetAdvType(BLE_ADV_LOCAL_NAME);
/* 初始化ble sdk */
ret = BLE_CfgNetInit(&g_bleInitParam, &g_bleCfgNetCb);
diff --git a/application/samples/wifi/ohos_connect/hilink_adapt/entry/hilink_indie_upgrade_main.c b/application/samples/wifi/ohos_connect/hilink_adapt/entry/hilink_indie_upgrade_main.c
index fb0a342..7aea1c1 100755
--- a/application/samples/wifi/ohos_connect/hilink_adapt/entry/hilink_indie_upgrade_main.c
+++ b/application/samples/wifi/ohos_connect/hilink_adapt/entry/hilink_indie_upgrade_main.c
@@ -18,7 +18,7 @@
#define APP_BIN_ADDR (APP_PROGRAM_ORIGIN - FLASH_START - 0x300)
#define CODE_AREA_HASH_OFFSET 0x128
-bool hexify(const unsigned char *inBuf, unsigned int inBufLen, char *outBuf, unsigned int outBufLen)
+bool hexify(const unsigned char *inBuf, unsigned int inBufLen, char *outBuf, unsigned int outBufLen)
{
if (outBufLen < HEXIFY_LEN(inBufLen)) {
return false;
@@ -91,4 +91,4 @@ int hilink_indie_upgrade_main(void)
return 0;
}
-#endif
\ No newline at end of file
+#endif
diff --git a/application/samples/wifi/ohos_connect/hilink_adapt/product/device_profile.h b/application/samples/wifi/ohos_connect/hilink_adapt/product/device_profile.h
index 9ac9852..40b63df 100755
--- a/application/samples/wifi/ohos_connect/hilink_adapt/product/device_profile.h
+++ b/application/samples/wifi/ohos_connect/hilink_adapt/product/device_profile.h
@@ -30,7 +30,7 @@ extern "C" {
#define DEVICE_HIVERSION "1.0.0"
/* 设备固件版本号 */
-#define FIRMWARE_VER "1.0.13"
+#define FIRMWARE_VER "1.0.6"
/* 设备硬件版本号 */
#define HARDWARE_VER "1.0.0"
/* 设备软件版本号 */
diff --git a/application/samples/wifi/ohos_connect/hilink_adapt/product/hilink_device.c b/application/samples/wifi/ohos_connect/hilink_adapt/product/hilink_device.c
index 8441a01..75e2cae 100755
--- a/application/samples/wifi/ohos_connect/hilink_adapt/product/hilink_device.c
+++ b/application/samples/wifi/ohos_connect/hilink_adapt/product/hilink_device.c
@@ -112,7 +112,7 @@ int HILINK_GetDevInfo(HILINK_DevInfo *devinfo)
return -1;
}
HILINK_SAL_DEBUG("HILINK_GetDevInfo manuName: [%s]\r\n", devinfo->manuName);
-#ifdef CONFIG_SUPPORT_HILINK_INDIE_UPGRADE
+#if 0 //def CONFIG_SUPPORT_HILINK_INDIE_UPGRADE
err = sprintf_s(devinfo->fwv, sizeof(devinfo->fwv), "%s_%s_%s", "103","1.312", FIRMWARE_VER);
if (err <= 0) {
HILINK_SAL_ERROR("sprintf_s err:%d\r\n", err);
@@ -632,6 +632,7 @@ void HILINK_NotifyDevStatus(int status)
case HILINK_LINK_CONNECTED_WIFI:
/* 设备已经连上路由器,请在此处添加实现 */
hf_set_wifi_state(1);
+ handle_device_online();
break;
case HILINK_M2M_CONNECTTING_CLOUD:
/* 设备正在连接云端,请在此处添加实现 */
diff --git a/application/ws63/user_main/spotlight/device_module.c b/application/ws63/user_main/spotlight/device_module.c
index 7ce7a9d..b99f196 100755
--- a/application/ws63/user_main/spotlight/device_module.c
+++ b/application/ws63/user_main/spotlight/device_module.c
@@ -57,6 +57,10 @@ int myhandle_put_brightness(const char* svc_id, const char* payload, unsigned in
// 处理色温控制
int myhandle_put_cct(const char* svc_id, const char* payload, unsigned int len)
{
+ // 🔧 添加调试信息:显示调用前的状态
+ e_printf("[put_cct] 调用开始: g_device_control.cct_local=%d, duty_cw=%d, duty_ww=%d\n",
+ g_device_control.cct_local, g_device_control.duty_cw, g_device_control.duty_ww);
+
int ret = -1;
cJSON *json = cJSON_Parse(payload);
if (json == NULL) {
diff --git a/application/ws63/user_main/spotlight/spotlight.h b/application/ws63/user_main/spotlight/spotlight.h
index d7e8099..16a8635 100755
--- a/application/ws63/user_main/spotlight/spotlight.h
+++ b/application/ws63/user_main/spotlight/spotlight.h
@@ -100,8 +100,14 @@ typedef struct __attribute__((packed, aligned(1))) {
#define BRIGHTNESS_MAX 100 // 最大亮度
#define BRIGHTNESS_LOCAL_MIN 0 // 最小亮度
#define BRIGHTNESS_LOCAL_MAX 10000 // 最大亮度
-#define BRIGHTNESS_REMOTE2LOCAL(x) (x * 100) //变化范围0 -10000
-#define BRIGHTNESS_LOCAL2REMOTE(x) (x / 100)
+
+// 亮度映射函数:仅对1-10%范围进行映射到2-10%,11-100%保持不变
+// 映射公式:
+// - 1-10%: 实际亮度 = 2 + (APP亮度 - 1) * 8 / 9
+// - 11-100%: 实际亮度 = APP亮度
+// 当APP亮度为1%时,实际亮度为2%;当APP亮度为10%时,实际亮度为10%;11%及以上保持不变
+#define BRIGHTNESS_REMOTE2LOCAL(x) (((x) <= 0) ? 0 : ((x) <= 10 ? (200 + (((x) - 1) * 800) / 9) : ((x) * 100)))
+#define BRIGHTNESS_LOCAL2REMOTE(x) (((x) <= 0) ? 0 : ((x) <= 1000 ? (1 + (((x) - 200) * 9) / 800) : ((x) / 100)))
#define BRIGHTNESS_LITME_RANGE(x) do { \
if (x > BRIGHTNESS_LOCAL_MAX) x = BRIGHTNESS_LOCAL_MAX; \
@@ -113,9 +119,9 @@ typedef struct __attribute__((packed, aligned(1))) {
#define INIT_STA__BRIGHTNESS 50
#define INIT_STA__CCT 4000
-#define INIT_NET_CFG_PWOER_ON_KEEP_TIME (5 * 1000) // 统计进入配网每次打开状态的保持时间
+#define INIT_NET_CFG_PWOER_ON_KEEP_TIME (5 * 1000) // 上电保持超过该时间则清零计数(防误触)
-#define NET_CFG_ENTRY_CNT 8 // 配网进入的上电次数
+#define NET_CFG_ENTRY_CNT 8 // 快速上电计数阈值:达到即强制解绑并恢复出厂
#define NET_CFG_BREATH_DURATION 1*60*1000 // 配网呼吸灯持续时间(ms)
#define NET_CFG_TOTAL_TIMEOUT 10*60*1000 // 配网总超时时间(ms)
@@ -195,6 +201,10 @@ typedef enum {
#define CCT_PIN GPIO_00 // 暖白LED (WW)
#define SWITCH_PIN GPIO_13
+// PWM 更新标志输出引脚(用于逻辑分析仪观察控制时序)
+// 选取 GPIO10:每次调用 update_pwm_output() 时翻转一次电平
+#define PWM_UPDATE_FLAG_PIN GPIO_10
+
#define CONFIG_PWM_GROUP_ID 2
#define OPEN_LIGHT GPIO_LEVEL_HIGH
@@ -213,6 +223,7 @@ typedef enum {
.is_net_configured = false, \
.duty_cw = 0, \
.duty_ww = 0, \
+ .power_on_cnt = 0, \
};
int spotlight_main(void);
@@ -228,4 +239,3 @@ void stop_net_config(void);
extern int fast_report(const char* svc_id);
#endif
-
diff --git a/application/ws63/user_main/spotlight/spotlight_main.c b/application/ws63/user_main/spotlight/spotlight_main.c
index 2cca2bd..79520bf 100755
--- a/application/ws63/user_main/spotlight/spotlight_main.c
+++ b/application/ws63/user_main/spotlight/spotlight_main.c
@@ -64,6 +64,8 @@ bool g_reset_factory_flag = false;
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);
@@ -112,6 +114,7 @@ static struct fade_ctx_t {
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;
};
@@ -208,7 +211,7 @@ static void *fade_task(const char *arg)
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);
@@ -216,14 +219,14 @@ static void *fade_task(const char *arg)
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);
@@ -231,6 +234,7 @@ static void *fade_task(const char *arg)
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);
}
@@ -335,6 +339,10 @@ static void *breath_task(const char *arg)
// 渐变定时器回调函数
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);
}
@@ -364,6 +372,27 @@ static void init_fade_ctx(void)
// 初始化打印限制器
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",
@@ -380,8 +409,7 @@ static void init_fade_ctx(void)
// 设置默认更新间隔
fade_ctx.update_interval = FADE_INTERVAL_MIN;
- // fade_ctx.current_brightness = g_device_control.brightness_local;
- // fade_ctx.current_cct = g_device_control.cct_local;
+ fade_ctx.timer_active = false; // 默认禁用,只有开始渐变时启用
}
// 初始化呼吸灯控制
@@ -491,8 +519,12 @@ void calculate_pwm_duty(device_control_t* pdevice_control)
// 更新PWM输出
void update_pwm_output(bool on_state, uint16_t duty_cw_val, uint16_t duty_ww_val)
{
- pwm_config_t cfg_repeat = {0};
- cfg_repeat.repeat = true;
+ // 说明:为了避免每步“重相位 + 动态拼接”导致的低亮抖动,
+ // 这里改为固定相位(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;
@@ -512,29 +544,53 @@ void update_pwm_output(bool on_state, uint16_t duty_cw_val, uint16_t duty_ww_val
if (!on_state) {
high_cnt_cw = 0;
- low_cnt_cw = pwm_period_cnt; // Ensure low_cnt is full period if off
+ low_cnt_cw = pwm_period_cnt; // 关灯时保持低电平整周期
high_cnt_ww = 0;
- low_cnt_ww = pwm_period_cnt; // Ensure low_cnt is full period if off
+ low_cnt_ww = pwm_period_cnt;
}
- // uapi_pwm_stop_group(CONFIG_PWM_GROUP_ID);
- cfg_repeat.high_time = high_cnt_cw;
- cfg_repeat.low_time = low_cnt_cw;
- uapi_pwm_open(channel_id_cw, &cfg_repeat);
- // uapi_pwm_update_duty_ratio(channel_id_cw, cfg_repeat.low_time, cfg_repeat.high_time);
+#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_repeat.high_time = high_cnt_ww;
- cfg_repeat.low_time = low_cnt_ww;
- cfg_repeat.offset_time = high_cnt_cw; // WW PWM starts after CW PWM high time
+ 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);
- uapi_pwm_open(channel_id_ww, &cfg_repeat);
- // uapi_pwm_update_duty_ratio(channel_id_ww, cfg_repeat.low_time, cfg_repeat.high_time);
-
- uapi_pwm_start_group(CONFIG_PWM_GROUP_ID);
+ 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:high:%u, low:%u, duty:%u/%u, ww:high:%u, low:%u, duty:%u/%u, offset_time:%u\r\n",
- on_state, high_cnt_cw, low_cnt_cw, current_duty_cw, PWM_DUTY_RATIO_MAX, high_cnt_ww, low_cnt_ww, current_duty_ww, PWM_DUTY_RATIO_MAX, cfg_repeat.offset_time);
+ 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);
}
}
@@ -608,6 +664,8 @@ lab_exit:
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;
@@ -887,10 +945,17 @@ int set_light(light_ctrl_source_e source,
// 如果打开灯,则需要手动将前置状态设置为关闭的样子,这样子后面计算渐变才能正常计算
if (APP_OPEN_LIGHT == source || DEV_POWER_ON == source) {
g_device_control.on = true;
- // fade_ctx.current_brightness = 0;
+
+ if (DEV_POWER_ON == source) {
+ // 🔧 开机渐变:明确设置从0开始
+ fade_ctx.current_brightness = 0; // 从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;
// 色温不进行变化,只改变亮度
- fade_ctx.current_cct = g_device_control.cct_local;
cct_local_target = g_device_control.cct_local;
if (g_device_control.colourMode != COLOUR_MODE_DUAL) {
@@ -930,6 +995,7 @@ int set_light(light_ctrl_source_e source,
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();
@@ -953,6 +1019,7 @@ int set_light(light_ctrl_source_e source,
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();
@@ -972,6 +1039,7 @@ int set_light(light_ctrl_source_e source,
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();
@@ -1025,27 +1093,34 @@ static void pwm_init(pin_t pin, pin_t pin1)
uapi_pin_set_mode(pin, PIN_MODE_1);
uapi_pin_set_mode(pin1, PIN_MODE_1);
uapi_pwm_init();
- uint32_t frequency = uapi_pwm_get_frequency(pin%8);
- // uint32_t pwm_base_period_ns = 1000 * 1000 * 1000 / frequency;
- // uint32_t pwm_base_period_ns = 1000 * 1000 * 1000 / (80 * 1000 * 1000);// 80MHZ
- // uint32_t pwm_target_period_ns = 1000 * 1000 * 1000 / PWM_FREQUENCY;
- pwm_period_cnt = ((80 * 1000 * 1000) / PWM_FREQUENCY);
+ // 基准时钟固定 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;
- // 设置PWM组
- channel_id_cw = pin%8;
- channel_id_ww = pin1%8;
+ 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};
- // uapi_pwm_open(channel_id_cw, &cfg_repeat);
- // uapi_pwm_open(channel_id_ww, &cfg_repeat);
- uapi_pwm_set_group(CONFIG_PWM_GROUP_ID, channel_ids, sizeof(channel_ids));
- // uapi_pwm_start_group(CONFIG_PWM_GROUP_ID);
- e_printf("PWM基础时钟频率: %dHz, 目标时钟频率: %dHz, 周期计数: %d\r\n", frequency, PWM_FREQUENCY, pwm_period_cnt);
+ (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_device:%d\r\n", g_device_control.power_on_cnt, !g_device_control.is_net_configured);
- g_device_control.power_on_cnt = 0;//
+ 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: 这里简单恢复之前等待配网的灯效即可
@@ -1075,23 +1150,16 @@ static int handle_network_status(void)
// 检查是否需要进入配网状态或恢复出厂设置
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;
- if (g_device_control.is_net_configured) {
- // 已出厂设备:上下电6次后恢复出厂设置并重启
- e_printf("已到达出厂设备上电次,执行恢复出厂设置\r\n");
- g_reset_factory_flag = true;
- extern int HILINK_RestoreFactorySettings(void);
- while (!hf_hilink_main_is_runing()) {
- msleep(10);
- }
- HILINK_RestoreFactorySettings();
- return start_net_cfg;
- } else {
- // 未出厂设备:进入配网模式
- e_printf("未出厂设备上电6次,进入配网模式\r\n");
- start_net_config();
- start_net_cfg = 1;
+ 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();
@@ -1274,18 +1342,17 @@ void handle_device_offline(void)
// 处理设备解绑
void handle_device_unbind(void)
{
- e_printf("设备被解绑,重置配网状态\r\n");
+ e_printf("设备被解绑,重置配网状态:%d\r\n", g_device_control.is_bound);
if (g_device_control.is_bound) {
g_device_control.is_bound = false;
- g_device_control.power_on_cnt = 0; // 重置上电计数
// 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();
+ g_device_control = tmp;
}
+ save_device_data();
}
uint64_t startup_time = 0;
@@ -1312,10 +1379,27 @@ 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);
}
@@ -1402,6 +1486,10 @@ int spotlight_main(void) {
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);
@@ -1476,12 +1564,23 @@ static void set_light2net_cfg_done(void)
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;
+ 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);
}
// 启动呼吸灯
@@ -1502,4 +1601,3 @@ lightMode_e convert_mode_for_report(lightMode_e current_mode)
// 否则上报基础模式
return LIGHT_MODE_GET_BASE(current_mode);
}
-
diff --git a/build/config/target_config/ws63/config.py b/build/config/target_config/ws63/config.py
index 0d29cef..b2d5720 100755
--- a/build/config/target_config/ws63/config.py
+++ b/build/config/target_config/ws63/config.py
@@ -130,7 +130,7 @@ target = {
'-:hal_systick', 'partition', 'partition_ws63','pmp_cfg_ws63', 'nonos_malloc', 'nonos_malloc_port',
'update_common', 'update_local', 'update_local_ws63', 'lzma_22.00', 'update_storage', 'update_common_ws63', 'update_ab_ws63', 'factory_ws63',
'efuse', 'hal_efuse_v151', 'efuse_port', 'soc_port',
- 'pwm', 'hal_pwm', 'pwm_port', # ADD
+ # 'pwm', 'hal_pwm', 'pwm_port', # ADD
],
'ram_component_set': ['uart', "time_set", "cpu", "pinctrl", "watchdog", "security_unified",'pmp_set'],
'os': 'non-os',
@@ -288,7 +288,7 @@ target = {
},
'ws63-liteos-app-iot': {
'base_target_name': 'target_ws63_app_rom_template',
- 'liteos_kconfig': 'ws63_iot', #ekko add for remove indie upgrade
+ 'liteos_kconfig': 'ws63_iot', # EKKO add for remove indie upgrade
'os': 'liteos',
'defines': [
"USE_CMSIS_OS",
@@ -336,7 +336,7 @@ target = {
"CONFIG_USE_CUSTOMER_SVC_INFO", #EKKO ADD
"CONFIG_DHCPS_GW",
"_HSF_",
- "CONFIG_PWM_USING_V150", #EKKO ADD
+ "CONFIG_PWM_PRELOAD", # Enable PWM preload (period-boundary update)
# "ENABLE_BLE_SCAN" #open ble scan
],
'ram_component': [
@@ -379,11 +379,10 @@ target = {
'cjson',
'xo_trim_port',
'hilink',
- #'app_addr_map', #ekko remove for indie upgrade
- 'hilinkdevicesdk', #ekko add for remove indie upgrade
- 'hilinkota', #ekko add for remove indie upgrade
- 'hilinkbtsdk', #ekko add for remove indie upgrade
- #'hilinkquickcfg', #ekko add for remove indie upgrade
+ # 'app_addr_map', # ekko remove for remove indie upgrade
+ 'hilinkdevicesdk', # ekko add for remove indie upgrade
+ 'hilinkota', # ekko add for remove indie upgrade
+ 'hilinkbtsdk', # ekko add for remove indie upgrade
'huks_sdk',
'deviceauth',
'little_fs', 'littlefs_adapt_ws63',
diff --git a/docs/serial_control_protocol.md b/docs/serial_control_protocol.md
new file mode 100644
index 0000000..ef275a2
--- /dev/null
+++ b/docs/serial_control_protocol.md
@@ -0,0 +1,361 @@
+# 串口控制协议
+
+## 目录
+
+- [1. 指令格式](#1-指令格式)
+ - [1.1 串口参数](#11-串口参数)
+- [2. JSON 结构](#2-json-结构)
+ - [2.1 字段说明](#21-字段说明)
+ - [2.2 发送提示](#22-发送提示)
+ - [2.3 查询命令(AT+QUERY)](#23-查询命令atquery)
+- [3. 支持服务与字段(详解)](#3-支持服务与字段详解)
+ - [3.1 switch(开关)](#31-switch开关)
+ - [3.2 brightness(亮度)](#32-brightness亮度)
+ - [3.3 cct(色温)](#33-cct色温)
+ - [3.4 lightMode(场景模式)](#34-lightmode场景模式)
+ - [3.5 progressSwitch(渐变时长)](#35-progressswitch渐变时长)
+ - [3.6 colourMode(色温模式)](#36-colourmode色温模式)
+- [4. 约束](#4-约束)
+- [5. 错误码](#5-错误码)
+ - [5.1 NotControllable(112)用法建议](#51-notcontrollable112用法建议)
+- [6. 时序图示(Mermaid)](#6-时序图示mermaid)
+- [7. 示例](#7-示例)
+
+## 1. 指令格式
+
+- 下发:`AT+CTRL={JSON}\r\n`
+- 查询:`AT+QUERY={JSON}\r\n`
+- 回执:`OK,\r\n` 或 `ERROR,[,]\r\n`
+- 异步结果:`AT+RESP={JSON}\r\n`
+- 规则:
+ - 单行 JSON(内部换行请写成 `\n`)
+ - 行结束统一为 CRLF `\r\n`(Windows 兼容)
+ - 接收端应兼容仅 LF `\n`
+
+### 1.1 串口参数
+- 波特率:`9600`
+- 数据位:`8`
+- 校验位:`None`
+- 停止位:`1`
+- 流控:`None`
+- 编码:`UTF-8`(无 BOM)
+- 建议:行缓冲读取,按 CRLF `\r\n` 作为帧结束。
+
+## 2. JSON 结构
+
+- 单服务控制(必须携带 id):
+ - 下发:`{"id": , "sid":"", "data": {}}`
+ - 返回:`{"id": , "sid":"", "data": {}, "error": , "message": "<可选>"}`(`error=0` 表示成功)
+
+### 2.1 字段说明
+- `id`(number, u32>0,必填)
+ - 会话标识,用于将异步结果与请求一一对应、便于定位问题。
+ - 由发起方分配与维护,建议使用一个全局自增计数(溢出后回绕到 1)。
+ - 受控方不做去重与顺序检查,仅在 RESP 中原样回显。
+- `sid`(string,必填)
+ - 服务功能 ID。合法值:`switch`、`brightness`、`cct`、`lightMode`、`progressSwitch`、`colourMode`。
+ - 区分大小写;不在集合内的值视为不支持服务。
+- `data`(object,必填)
+ - 具体服务的数据负载。各服务的字段与范围见“支持服务与字段(详解)”。
+ - 缺字段或类型不符为业务错误,RESP `error=105`(`message` 可携带原因)。
+- `error`(number, u32,RESP 必带)
+ - 业务执行结果码:`0` 成功;非 0 失败。常见值见“错误码”。
+- `message`(string,可选,RESP 可带)
+ - 人类可读的错误或提示信息,用于调试。
+
+### 2.2 发送提示
+- 多次控制:请按需多次发送 `AT+CTRL=...`,每次使用不同的 `id`。
+- ACK 超时与重发建议:
+ - 发送后等待 `OK,`,超时建议 `200–500 ms`。
+ - 未收到 ACK 则按原 `id` 与完全相同的 JSON 重发,重发 `2–3 次`,间隔 `200–300 ms`。
+ - 注意:设备不做去重,重复下发可能重复执行;建议尽量使用幂等设置(如重复设置相同亮度)。
+- 结果等待与超时:
+ - 收到 `OK,` 后等待 `AT+RESP`,建议超时阈值 `1–2 s`(视业务而定)。
+ - 超时未收到可按失败处理并在上层重试(使用新的 `id`)。
+- 换行约定:所有发送与回执均以 CRLF `\r\n` 结束;示例为单行展示,实际发送需包含 CRLF。
+
+### 2.3 查询命令(AT+QUERY)
+- 作用:查询指定 `sid` 的当前状态(只读,不改变设备状态)。
+- 下发:`AT+QUERY={"id": , "sid":""}`\r\n
+- 回执:`OK,`\r\n
+- 异步结果:`AT+RESP={"id": , "sid":"", "data": {}, "error": , "message": "<可选>"}`\r\n
+- 说明:
+ - `data` 与“支持服务与字段(详解)”中各 `sid` 的状态格式一致(等同于 Get 接口的输出)。
+ - 若 `sid` 不支持,返回 `ERROR,104,UnsupportedSid`(协议级错误)。
+
+## 3. 支持服务与字段(详解)
+
+### 3.1 switch(开关)
+- 功能:控制灯具开/关。
+- 下发:`{"id":,"sid":"switch","data":{"on":0|1}}`
+- 返回:`{"id":,"sid":"switch","data":{"on":0|1},"error":,"message":"<可选>"}`
+- 参数:`on` 为 int,取值 `0` 关、`1` 开。
+- 行为:当处于“离家模式”(mode=7)时,收到 `on=1` 会先退出离家模式再开灯。
+- 示例:
+ - 开灯
+ - 【发起方发送】`AT+CTRL={"id":101,"sid":"switch","data":{"on":1}}`
+ - 【受控方返回】`OK,101` 与 `AT+RESP={"id":101,"sid":"switch","data":{"on":1},"error":0}`
+ - 关灯
+ - 【发起方发送】`AT+CTRL={"id":102,"sid":"switch","data":{"on":0}}`
+ - 【受控方返回】`OK,102` 与 `AT+RESP={"id":102,"sid":"switch","data":{"on":0},"error":0}`
+
+### 3.2 brightness(亮度)
+- 功能:设置亮度百分比。
+- 下发:`{"id":,"sid":"brightness","data":{"brightness":0..100}}`
+- 返回:`{"id":,"sid":"brightness","data":{"brightness":<0..100>},"error":,"message":"<可选>"}`
+- 参数:`brightness` 为 int,范围 `0..100`;超出范围按边界钳制。
+- 示例:
+ - 设为 60%:`AT+CTRL={"id":201,"sid":"brightness","data":{"brightness":60}}`
+ - 最小值:`AT+CTRL={"id":202,"sid":"brightness","data":{"brightness":0}}`
+ - 最大值:`AT+CTRL={"id":203,"sid":"brightness","data":{"brightness":100}}`
+
+### 3.3 cct(色温)
+- 功能:设置色温(单位 K)。
+- 下发:`{"id":,"sid":"cct","data":{"colorTemperature":2700..6000}}`
+- 返回:`{"id":,"sid":"cct","data":{"colorTemperature":<2700..6000>},"error":,"message":"<可选>"}`
+- 参数:`colorTemperature` 为 int,范围 `2700..6000`;超出范围按边界钳制。
+- 示例:
+ - 暖色 3000K:`AT+CTRL={"id":301,"sid":"cct","data":{"colorTemperature":3000}}`
+ - 中性 4000K:`AT+CTRL={"id":302,"sid":"cct","data":{"colorTemperature":4000}}`
+ - 冷色 6000K:`AT+CTRL={"id":303,"sid":"cct","data":{"colorTemperature":6000}}`
+
+### 3.4 lightMode(场景模式)
+- 功能:按预设场景设置亮度与色温,或进入离家模式。
+- 下发:`{"id":,"sid":"lightMode","data":{"mode":0..7}}`
+- 返回:`{"id":,"sid":"lightMode","data":{"mode":<0..7>},"error":,"message":"<可选>"}`
+- 参数:`mode` 为 int:
+ - 0 customer(自定义模式)
+ - 1 relax (休闲模式)(约 50%,4000K)
+ - 2 movie(观影模式)(约 10%,3000K)
+ - 3 dining(用餐模式)(约 100%,4000K)
+ - 4 home(回家模式)(约 80%,3500K)
+ - 5 winter(冬天模式)(约 100%,2700K)
+ - 6 summer(夏天模式)(约 100%,6000K)
+ - 7 leave(离家模式)(直接关灯)
+- 示例:
+ - 观影模式:`AT+CTRL={"id":401,"sid":"lightMode","data":{"mode":2}}`
+ - 离家模式:`AT+CTRL={"id":402,"sid":"lightMode","data":{"mode":7}}`
+ - 回家模式:`AT+CTRL={"id":403,"sid":"lightMode","data":{"mode":4}}`
+
+### 3.5 progressSwitch(渐变时长)
+- 功能:设置亮度/色温变化的平滑过渡时间(秒)。
+- 下发:`{"id":,"sid":"progressSwitch","data":{"fadeTime":0..30}}`
+- 返回:`{"id":,"sid":"progressSwitch","data":{"fadeTime":<0..30>},"error":,"message":"<可选>"}`
+- 参数:`fadeTime` 为 int,范围 `0..30` 秒;`0` 表示尽快变化。
+- 示例:
+ - 设为 5 秒:`AT+CTRL={"id":501,"sid":"progressSwitch","data":{"fadeTime":5}}`
+ - 立即变化:`AT+CTRL={"id":502,"sid":"progressSwitch","data":{"fadeTime":0}}`
+
+### 3.6 colourMode(色温模式)
+- 功能:设置色温工作模式。
+- 下发:`{"id":,"sid":"colourMode","data":{"mode":0|1}}`
+- 返回:`{"id":,"sid":"colourMode","data":{"mode":0|1},"error":,"message":"<可选>"}`
+- 参数:`mode` 为 int:`0` 单色温、`1` 双色温。
+- 行为:单色温(0)下,设备固定到预设色温(6000K);双色温(1)下,使用/保持当前色温。
+- 示例:
+ - 单色温:`AT+CTRL={"id":601,"sid":"colourMode","data":{"mode":0}}`
+ - 双色温:`AT+CTRL={"id":602,"sid":"colourMode","data":{"mode":1}}`
+
+## 4. 约束
+- `{JSON}` 最大长度:≤ 1024 字节(不含前缀与行尾)。
+- 单行承载,不允许真实换行;内部换行使用 `\n` 字符串。
+- 行结束采用 CRLF `\r\n`;接收端应兼容仅 LF `\n`。
+- `id` 必须存在且为 u32>0;缺失/类型不符即返回 `ERROR,105,TypeError`。
+
+## 5. 错误码
+- `100` BadPrefix(未以 `AT+CTRL=` 开头)
+- `101` MalformedJSON(JSON 语法错误)
+- `102` EmptyJSON(空 JSON)
+- `103` PayloadTooLong(负载超长)
+- `104` UnsupportedSid(不支持的 `sid`)
+- `105` TypeError(字段缺失或类型不符)
+- `106` Busy(设备忙)
+- `107` ApplyTimeout(内部执行超时)
+- `112` NotControllable(非受控状态:设备处于不可被控制的模式,例如升级/维护/工厂测试/安全锁定等)
+- `111` RateLimited(限频)
+
+### 5.1 NotControllable(112)用法建议
+- 触发场景(示例):
+ - 升级进行中(OTA/独立升级/固件校验)
+ - 维护/自检/烧录/工厂测试模式
+ - 安全锁定/童锁/设备被上级网关临时锁定
+ - 热保护/过温降额/低电量保护等安全策略生效
+ - 正在配网/关键迁移流程,不允许外部控制
+- 返回规范:
+ - 收到控制后先回 ACK:`OK,`
+ - 业务结束后返回:`AT+RESP={"id":,"sid":"","data":{...},"error":112,"message":"<原因>"}`
+- `message` 建议取值(便于前端统一展示与日志聚合):
+ - `upgrading`(升级中)
+ - `maintenance`(维护/自检)
+ - `factory_test`(工厂测试)
+ - `locked`(安全/家长锁定)
+ - `thermal_protect`(热保护)
+ - `low_power`(低电量保护)
+ - `net_config`(正在配网)
+- 查询建议:
+ - `AT+QUERY` 通常仍应返回当前状态并 `error=0`;若状态不可读,再返回 `error=112` 与合适的 `message`。
+
+## 6. 时序图示(Mermaid)
+
+1) 多次控制(均成功,异步返回 `error=0`)
+```mermaid
+sequenceDiagram
+ participant 发起方
+ participant 受控方
+
+ 发起方->>受控方: AT+CTRL={"id":7001,"sid":"switch","data":{"on":1}}\r\n
+ 受控方-->>发起方: OK,7001\r\n
+ note over 受控方: 执行开关控制
+ 受控方-->>发起方: AT+RESP={"id":7001,"sid":"switch","data":{"on":1},"error":0}\r\n
+
+ 发起方->>受控方: AT+CTRL={"id":7201,"sid":"lightMode","data":{"mode":2}}\r\n
+ 受控方-->>发起方: OK,7201\r\n
+ note over 受控方: 执行场景模式切换
+ 受控方-->>发起方: AT+RESP={"id":7201,"sid":"lightMode","data":{"mode":2},"error":0}\r\n
+
+ 发起方->>受控方: AT+CTRL={"id":7301,"sid":"progressSwitch","data":{"fadeTime":5}}\r\n
+ 受控方-->>发起方: OK,7301\r\n
+ note over 受控方: 设置渐变时长
+ 受控方-->>发起方: AT+RESP={"id":7301,"sid":"progressSwitch","data":{"fadeTime":5},"error":0}\r\n
+```
+
+2) 协议级错误(JSON 语法错误,直接 `ERROR`,不产生 RESP)
+```mermaid
+sequenceDiagram
+ participant 发起方
+ participant 受控方
+
+ 发起方->>受控方: AT+CTRL={"sid":"switch","data":{"on":1}
+ 受控方-->>发起方: ERROR,101,MalformedJSON
+ note over 受控方: 帧被丢弃,无 AT+RESP
+```
+
+3) 业务错误(收到并受理,但参数类型错误)
+```mermaid
+sequenceDiagram
+ participant 发起方
+ participant 受控方
+
+ 发起方->>受控方: AT+CTRL={"id":7501,"sid":"brightness","data":{"brightness":"sixty"}}\r\n
+ 受控方-->>发起方: OK,7501\r\n
+ note over 受控方: 参数校验失败(类型错误)
+ 受控方-->>发起方: AT+RESP={"id":7501,"sid":"brightness","data":{"brightness":50},"error":105,"message":"TypeError"}\r\n
+```
+
+4) 查询状态(OK + RESP)
+```mermaid
+sequenceDiagram
+ participant 发起方
+ participant 受控方
+
+ 发起方->>受控方: AT+QUERY={"id":7101,"sid":"brightness"}\r\n
+ 受控方-->>发起方: OK,7101\r\n
+ note over 受控方: 读取并打包当前亮度状态
+ 受控方-->>发起方: AT+RESP={"id":7101,"sid":"brightness","data":{"brightness":60},"error":0}\r\n
+```
+
+## 7. 示例
+
+1) 开关:打开
+【发起方发送】
+```
+AT+CTRL={"id":7001,"sid":"switch","data":{"on":1}}
+```
+【受控方返回】
+```
+OK,7001
+```
+【受控方返回】
+```
+AT+RESP={"id":7001,"sid":"switch","data":{"on":1},"error":0}
+```
+
+2) 查询当前亮度
+【发起方发送】
+```
+AT+QUERY={"id":7101,"sid":"brightness"}
+```
+【受控方返回】
+```
+OK,7101
+```
+【受控方返回】
+```
+AT+RESP={"id":7101,"sid":"brightness","data":{"brightness":60},"error":0}
+```
+
+3) 场景模式:movie
+【发起方发送】
+```
+AT+CTRL={"id":7201,"sid":"lightMode","data":{"mode":2}}
+```
+【受控方返回】
+```
+OK,7201
+```
+【受控方返回】
+```
+AT+RESP={"id":7201,"sid":"lightMode","data":{"mode":2},"error":0}
+```
+
+4) 渐变时长:5 秒
+【发起方发送】
+```
+AT+CTRL={"id":7301,"sid":"progressSwitch","data":{"fadeTime":5}}
+```
+【受控方返回】
+```
+OK,7301
+```
+【受控方返回】
+```
+AT+RESP={"id":7301,"sid":"progressSwitch","data":{"fadeTime":5},"error":0}
+```
+
+5) 色温模式:单色温
+【发起方发送】
+```
+AT+CTRL={"id":7401,"sid":"colourMode","data":{"mode":0}}
+```
+【受控方返回】
+```
+OK,7401
+```
+【受控方返回】
+```
+AT+RESP={"id":7401,"sid":"colourMode","data":{"mode":0},"error":0}
+```
+
+6) 业务失败(类型错误)
+【发起方发送】
+```
+AT+CTRL={"id":7501,"sid":"brightness","data":{"brightness":"sixty"}}
+```
+【受控方返回】
+```
+OK,7501
+```
+【受控方返回】
+```
+AT+RESP={"id":7501,"sid":"brightness","data":{"brightness":50},"error":105,"message":"TypeError"}
+```
+
+7) 非法 JSON(协议级错误)
+【发起方发送】
+```
+AT+CTRL={"sid":"switch","data":{"on":1}
+```
+【受控方返回】
+```
+ERROR,101,MalformedJSON
+```
+
+8) 不支持的服务(协议级错误)
+【发起方发送】
+```
+AT+CTRL={"id":7601,"sid":"foo","data":{"bar":1}}
+```
+【受控方返回】
+```
+ERROR,104,UnsupportedSid
+```
diff --git a/docs/serial_control_protocol.pdf b/docs/serial_control_protocol.pdf
new file mode 100755
index 0000000..03b18dc
Binary files /dev/null and b/docs/serial_control_protocol.pdf differ
diff --git a/indie_build.py b/indie_build.py
index 86ad443..9a0b974 100755
--- a/indie_build.py
+++ b/indie_build.py
@@ -124,6 +124,7 @@ def all_build():
os.makedirs(temp_dir)
build_update_package(os.path.join(info.upg_output, "update.fwpkg"), temp_dir, info.upg_output)
+
print("gen package.zip")
file_dir = os.path.dirname(os.path.abspath(__file__))
os.system("cd " + file_dir + " && python3 package.py")
diff --git a/output/LPT262_hilink-SR_Switch-20251026-1.0.6.fwpkg b/output/LPT262_hilink-SR_Switch-20251026-1.0.6.fwpkg
new file mode 100644
index 0000000..7cc87b4
Binary files /dev/null and b/output/LPT262_hilink-SR_Switch-20251026-1.0.6.fwpkg differ
diff --git a/output/package(SR_Switch-LPT262_hilink-20251026-1.0.6).zip b/output/package(SR_Switch-LPT262_hilink-20251026-1.0.6).zip
new file mode 100644
index 0000000..3f7a8e7
Binary files /dev/null and b/output/package(SR_Switch-LPT262_hilink-20251026-1.0.6).zip differ
diff --git a/ws63_check_json_analysis.md b/ws63_check_json_analysis.md
new file mode 100644
index 0000000..4b6bfbc
--- /dev/null
+++ b/ws63_check_json_analysis.md
@@ -0,0 +1,440 @@
+# WS63 Check.json 文件分析完整文档
+
+## 概述
+
+本文档详细分析了 `ws63-liteos-hilink-check.json` 文件的生成机制、校验内容和对应关系。该文件是WS63项目独立升级功能的核心组件,用于验证HiLink固件与App-IoT固件之间的接口兼容性。
+
+## 1. JSON文件基本信息
+
+**文件路径**: `./output/ws63/acore/ws63-liteos-hilink/ws63-liteos-hilink-check.json`
+
+**文件内容结构**:
+```json
+{
+ "ver": 1,
+ "app": "3A23309AAF0B692188B9C56755C084522354143382C5309A2D3258C3E6C834A500B53089C7A65C43392D51DFEF32BBC125B613C6B37656F59E142F0D713AD6115955749E72C53C3BA8CD96D2C69CB534231411DEAE5C4F1782DA2760BB04E0199813CAC4CBA339BEBF3D734FBF0955235DD160C0387CA4AD28BFC8766508F627D0B46BE48319EAC371921D27D806C9F3464BF4DFBAE09ADB95232386B021EEFBD3FAD2C6B405A1E9C13BB0420CAB5EF02D3D543090162EB8E51C2E1D10F3EE4EE5FE71A0BA8DF1E95E4A36694908DDB16E08F54B606E13CACB530F71320CC9DF6C3DCB70DC6E54BDA7B3C1720E7ECCB54E88950CFC3D4D700224AB40D9E568A89571387053E9BB3D77889DAA102DB1FC4CE38751F2E6A0BD27B0EC51B8EA015CE0E475ADF3E3CDB49580E84E228803A691F39D958D3F28B0E4D53C670A27B5AB436D11F83A8AAEB6538628D32F674C398B6CF1C295BAB9499E19EA993B11D07524E025EF6FF88F42331C3BE36689468DAF74C6B811187E2D7953251B9228B8A8C32422F97C0122332BB295C110F36291A845CD2FA2D6BC34E37B7CBE23083067AE8AF9346DEEEFCC168D2D4658A94AB5049858C11E8BE4672F492DE9B4046E4B0EEEA5E3D6FE8809743B2B6111718F2038742D7C48EE81BBD5D485373D34C70868622D3233179ADED3E8C5026A2217F6938E85AA7A6754CE869A8127656D364C00F05E95FE7738AD05E79CACA11368FAE6717C71C469FC934FF221953E9F7CA301D52266EA04E8184A6D5AF66621F90139D0642D0350FA3F28ED49CF23AC20D03710992FBE7E3DBCEBD737385AE906D8D885A6118F2416A45FFA93EC3483EDADE5864419C451689382274A6DEC6FD6734D3975199C9FFB561202FEAB34F195D595E791C43315669E430FB9E7288EF87BC4498A4DF1A93918FA7C7805F7131CCF092F762F28C0A502EC955661D19C624CD0B61E88F81F9D57108A971D268273CEABEE8013FF69661C1A29BBD995111C6A64314013FBA647F77B736AE8E330F3D7157E6C3774AFBCC38D643C7108363127CB03B902C6D32C202A73EE7099A65902A14959BA60D70D055A89A6C3E489489F355E418A02EF8A543D8DF826C59AD8FABD1564AF4FEE6224FCA67974F6F63E17D3036A50120E5449669A4D792E919F88C4BBEEC64E542216D35ED1DE5A21434FC521776D37F5C50257B639AA3F47D1CC1888A19961CD6F5D7C9BEF30D5EACE785DB24268E360581533F98458376DD1E770BF3612B6D1F9C62395F48BEDE23AE1514E24C79360CE44291140AFEC5576503E6EBBC1D453DC9ED772F6AA506112D26C5B806EC4E0EAEC6A98F6F1683AC86494FA565B7CE2A0540F45AC6A8A556CDEE96B315EF45ED456EF46F1E5C234ABF92B121CCE688D2163BDF57FB6098B4742FBC504AC5E03230ADF90428D53F024F9C20964CA8AEA8A9042D1CEF0A2BA9C88A011C1004A9B8F7F9EBEDA365056947E9426D868829904D70DA74B7276D93829D151333F3506E83032A8CF68630BD5D0A39237FDF0BADD131AB77B6092987F07139588081D140EB2A0CA25BF9267FBC809457528A7C5DFA1729552A8D76B3362B9915E84795CD770EB84A3AE73DE78F04D37E8FC2F53E2F72853D57F170FC2551F7CBBB9B63D119AC4775120418F3865792FEFAAFF69038BFD3AA3C2C476B26DFB2B48F3B3904203C394782FE1C40F718001C31504539827DDC80900966524DCE965006F86EBDA9C46226BC1DA2387E2AE9565DFEE621F0DA936298371D1AD83860B4E607BB473E4103ADF872D1A3CA9EB171CF73077B4AFC2D7FC3737FAE5337290D8116CE0826F347C621502BA313EEF20F1F67D00A7EB1BB555DE7B0FCDD05C747D7615136B35079DA4BF9A6EED5F0C5448B8364FB03476275BD823C8C7F3CBCC1D0BD41C5B49538D65C00C85F9C8D50201EDA6266D7A2A375141F7F5E69E1AD06932C3A6C044EAE908D43657EA22C5FA797FE8D04592541477B362753A05",
+ "hilink": "BEC62B3A1B90717BABD8C9AD15D3BE1560977111A022C59CEF399A97E8B1D1D2D981EE972F4C881D0D3D30D8165FA46BEB1F07B4B8F1AECEA4335DFC7388E1234641EDD1AF31DFEDB616EBF0A9900778C03C4467D3CBCD6540F51D66CBE0FF998506BA06448D8BEB6CDA8E9E79BE4C8BF15449A4DEFEB22F342B09F03683E17D699DA475D08A2F079EDA59B99A96CD0E468B089224120EE96B86A8BB4B250B35E0E8B8A1E77FE8A13F50CF8B018FA5A91475DDA932141DAF1F5C4D9C5D7F8DC8E3CB582D0DB0EA8823396BF6BC0A30D68B968BEE77AB6014036385A68BB35701D274404A9BFA24348E7321F63FEA98B7"
+}
+```
+
+## 2. 文件生成机制
+
+### 2.1 生成触发条件
+
+**触发时机**: 在构建过程的 `build_post` 阶段(构建完成后)
+
+**配置条件**: 编译配置中必须包含 `CONFIG_SUPPORT_HILINK_INDIE_UPGRADE`
+- 当前项目状态:该配置**已被注释**(config.py:334行)
+- 因此只有HiLink固件生成了check.json,App-IoT固件未生成
+
+### 2.2 生成调用链
+
+```
+构建系统 (build.py)
+ ↓
+build_post 钩子
+ ↓
+entry.py:153 → dump_indie_upg_check_file()
+ ↓
+indie_upgrade_utils.py:324 → 生成JSON文件
+```
+
+### 2.3 核心生成文件
+
+**主要脚本文件**:
+- `build/config/target_config/ws63/script/entry.py:153` - 构建钩子调用点
+- `build/script/utils/indie_upgrade_utils.py:324` - JSON文件生成函数
+- `build/script/utils/indie_upgrade_utils.py:292-320` - 接口校验码生成核心逻辑
+
+## 3. 校验内容详解
+
+### 3.1 JSON字段含义
+
+| 字段 | 含义 | 数据格式 |
+|------|------|----------|
+| `ver` | 校验文件版本号 | 整数,当前为1 |
+| `app` | App侧接口校验码串联 | CRC32十六进制字符串 |
+| `hilink` | HiLink侧接口校验码串联 | CRC32十六进制字符串 |
+
+### 3.2 校验码生成原理
+
+1. **接口函数扫描**: 通过正则表达式扫描源文件中的函数原型
+ ```python
+ rgl = r"((?:const )?(?:unsigned )?(?:struct )?(?:enum )?\w+[ \*]*)" + \
+ r"(\w+)[\s\n]*" + \
+ r"(\()" + \
+ r"([\s\*,\w\[\]]*?)" + \
+ r"(\))" + \
+ r"\s*\{"
+ ```
+
+2. **原型标准化**: 去除参数名,保留参数类型,生成标准化函数原型字符串
+
+3. **CRC32计算**: 对每个函数原型字符串计算CRC32校验码
+ ```python
+ checksum = "{:08X}".format(zlib.crc32(prototype.encode("utf8")))
+ ```
+
+4. **校验码串联**: 将所有接口的8位十六进制CRC32码按顺序串联
+
+### 3.3 校验码对应的编译文件
+
+| JSON字段 | 编译目标 | 二进制文件 | 签名文件 |
+|----------|----------|------------|----------|
+| `"app"` | `ws63-liteos-app-iot` | `output/ws63/acore/ws63-liteos-app-iot/ws63-liteos-app-iot.bin` | `ws63-liteos-app-iot-sign.bin` |
+| `"hilink"` | `ws63-liteos-hilink` | `output/ws63/acore/ws63-liteos-hilink/ws63-liteos-hilink.bin` | `ws63-liteos-hilink-sign.bin` |
+
+## 4. 接口映射文件体系
+
+### 4.1 App侧接口配置
+
+**源文件路径**: `application/samples/wifi/hilink_indie_upgrade/address_mapping/hilinksdk/app_uapi/`
+
+**主要接口文件**:
+- `uapi_hilink_kv_adapter.c` - KV存储适配器接口
+- `uapi_hilink_mem_adapter.c` - 内存管理适配器接口
+- `uapi_hilink_socket_adapter.c` - Socket网络适配器接口
+- `uapi_hilink_stdio_adapter.c` - 标准IO适配器接口
+- `uapi_hilink_thread_adapter.c` - 线程管理适配器接口
+- `uapi_hilink_time_adapter.c` - 时间管理适配器接口
+- `uapi_hilink_network_adapter.c` - 网络适配器接口
+- `uapi_hilink_device.c` - 设备管理接口
+- `uapi_hichain.c` - 设备认证接口
+- `uapi_hilink_ble_adapter.c` - BLE适配器接口
+- 等共52个接口适配文件
+
+**生成的映射表**: `application/samples/wifi/hilink_indie_upgrade/address_mapping/application/app_function_mapping.c`
+
+### 4.2 HiLink侧接口配置
+
+**源文件路径**: `application/samples/wifi/hilink_indie_upgrade/address_mapping/application/hilink_uapi/`
+
+**主要接口文件**:
+- `uapi_hilink.c` - HiLink核心接口
+- `uapi_hilink_log_manage.c` - 日志管理接口
+- `uapi_hilink_device_ext.c` - 设备扩展接口
+- `uapi_ble_cfg_net_api.c` - BLE配网接口
+- `uapi_hilink_bt_function.c` - 蓝牙功能接口
+- `uapi_hilink_network_adapter.c` - 网络适配器接口
+- `uapi_hilink_socket_adapter.c` - Socket适配器接口
+- `uapi_hilink_custom.c` - 自定义功能接口
+- `uapi_hilink_sle_api.c` - SLE接口
+- `uapi_hilink_quick_netcfg_api.c` - 快速配网接口
+
+**生成的映射表**: `application/samples/wifi/hilink_indie_upgrade/address_mapping/hilinksdk/hilink_function_mapping.c`
+
+### 4.3 接口头文件映射
+
+**App侧头文件路径**:
+- `application/samples/wifi/ohos_connect/hilink_adapt/adapter/include/` - 适配器接口声明
+- `application/samples/wifi/ohos_connect/hilink_adapt/product/` - 产品相关接口
+- `application/samples/wifi/ohos_connect/hilink_adapt/include/` - 通用接口声明
+- `open_source/deviceauth/interfaces/innerkits/deviceauth_lite/` - 设备认证接口
+- `kernel/liteos/liteos_v208.5.0/Huawei_LiteOS/open_source/CMSIS/CMSIS/RTOS2/Include/` - RTOS接口
+- `open_source/cjson/cjson/` - JSON库接口
+- `open_source/mbedtls/mbedtls_v3.1.0/include/` - 加密库接口
+
+**HiLink侧头文件路径**:
+- `application/samples/wifi/ohos_connect/hilink_adapt/include/` - HiLink核心接口声明
+- `application/samples/wifi/ohos_connect/hilink_adapt/product/` - 产品相关接口
+- `application/samples/wifi/ohos_connect/hilink_adapt/adapter/include/` - 适配器接口声明
+
+## 5. 校验机制详解
+
+### 5.1 接口兼容性检查函数
+
+**函数位置**: `build/script/utils/indie_upgrade_utils.py:353-370`
+
+**检查逻辑**:
+```python
+def check_indie_upg_match(hilink_check_file, app_check_file):
+ # 读取两个check.json文件
+ f = open(hilink_check_file, "r", encoding="utf-8")
+ hilink_check = json.loads(f.read())
+ f.close()
+ f = open(app_check_file, "r", encoding="utf-8")
+ app_check = json.loads(f.read())
+ f.close()
+
+ # 版本号检查
+ if hilink_check["ver"] != 1 or app_check["ver"] != 1:
+ print("check file ver[h:%d,a:%d] not match" % (hilink_check["ver"], app_check["ver"]))
+ return False
+
+ # HiLink侧接口向后兼容检查
+ if not hilink_check["hilink"].startswith(app_check["hilink"]):
+ prt_not_match_info("hilink", hilink_check["hilink"], app_check["hilink"], True)
+ return False
+
+ # App侧接口向后兼容检查
+ if not app_check["app"].startswith(hilink_check["app"]):
+ prt_not_match_info("app", app_check["app"], hilink_check["app"], True)
+ return False
+
+ return True
+```
+
+### 5.2 校验失败信息输出
+
+**函数位置**: `indie_upgrade_utils.py:330-350`
+
+校验失败时会输出具体的不匹配接口信息:
+- 显示接口序号和对应的CRC32校验码
+- 帮助定位具体是哪个接口发生了变更
+- 每个CRC32码长度为8个十六进制字符
+
+### 5.3 升级包构建时的校验
+
+**调用位置**: `build/config/target_config/ws63/build_ws63_update.py:74`
+
+```python
+if not check_indie_upg_match(info.hilink_check, info.app_iot_check):
+ print("indie upg hilink and app not match")
+ return False
+```
+
+在生成升级包时会自动进行兼容性检查,如果接口不兼容,构建过程会失败。
+
+## 6. 独立升级工作流程
+
+### 6.1 独立升级概述
+
+独立升级允许在不更新App-IoT固件的情况下,单独升级HiLink SDK固件。这种机制可以:
+- 快速修复HiLink SDK的bug
+- 更新云端协议和功能
+- 减少升级包大小和升级时间
+- 降低升级风险
+
+### 6.2 配置开启流程
+
+根据 `indie_upg.md` 文档,开启独立升级需要:
+
+1. **修改配置** (`build/config/target_config/ws63/config.py`):
+ - 删除 `'liteos_kconfig': 'ws63_iot'`
+ - 在 `'defines'` 中增加 `CONFIG_SUPPORT_HILINK_INDIE_UPGRADE`
+ - 在 `'ram_component'` 中增加 `'app_addr_map'`
+ - 在 `'ram_component'` 中删除 `'hilinkdevicesdk'`、`'hilinkota'`、`'hilinkbtsdk'`、`'hilinkquickcfg'`
+
+2. **分别编译两个固件**:
+ ```bash
+ # 先编译HiLink固件
+ python3 build.py -c ws63-liteos-hilink
+
+ # 再编译App-IoT固件
+ python3 build.py -c ws63-liteos-app-iot
+
+ # 生成升级包
+ python3 build/config/target_config/ws63/build_ws63_update.py --pkt=app_iot
+ ```
+
+3. **使用简化编译工具**:
+ ```bash
+ # 完整编译
+ python3 indie_build.py all
+
+ # 仅编译SDK(用于独立升级)
+ python3 indie_build.py sdk
+ ```
+
+### 6.3 独立升级流程
+
+1. **准备已认证的App-IoT固件**:
+ - `ws63-liteos-app-iot-sign.bin`
+ - `ws63-liteos-app-iot-check.json`
+
+2. **更新HiLink SDK库文件**:
+ - 替换 `application/samples/wifi/libhilink/` 中的库文件
+
+3. **执行独立编译**:
+ ```bash
+ python3 indie_build.py sdk
+ ```
+
+4. **接口兼容性校验**:
+ - 自动比较新HiLink固件与已认证App-IoT固件的接口
+ - 如果接口不匹配,构建失败
+ - 校验通过后生成完整升级包
+
+### 6.4 约束条件
+
+1. **分区兼容性**: 非独立升级版本与独立升级版本不可交叉升级
+2. **接口兼容性**: 模组App程序不变时,HiLink接口不能发生变更
+3. **版本号格式**:
+ - 非独立升级:`1.0.0`
+ - 独立升级:`1.0.0_14.2.0.304` (拼接SDK版本号)
+
+## 7. 新增接口适配指南
+
+### 7.1 接口调用机制
+
+独立升级模式下,模组App和HiLink分别编译成两个固件:
+- 各自维护接口地址表
+- 通过查表机制获取对方接口函数指针
+- 实现跨固件的函数调用
+
+### 7.2 新增HiLink接口步骤
+
+**示例接口原型**:
+```c
+retType TestFuncName(type1 param1, type2 param2, type3 param3);
+```
+
+1. **接口声明** (`application/samples/wifi/ohos_connect/hilink_adapt/include/hilink_test.h`):
+ ```c
+ retType TestFuncName(type1 param1, type2 param2, type3 param3);
+ ```
+
+2. **查表适配实现** (`application/samples/wifi/hilink_indie_upgrade/address_mapping/application/hilink_uapi/uapi_hilink_test.c`):
+ ```c
+ retType TestFuncName(type1 param1, type2 param2, type3 param3)
+ {
+ hilink_call3(HILINK_CALL_TEST_FUNC_NAME, TestFuncName, retType, type1, param1, type2, param2, type3, param3);
+ return (retType)0;
+ }
+ ```
+
+3. **添加到编译系统** (`application/samples/wifi/hilink_indie_upgrade/address_mapping/application/CMakeLists.txt`):
+ ```cmake
+ uapi_hilink_test.c
+ ```
+
+4. **配置脚本识别** (`build/script/utils/indie_upgrade_utils.py`):
+ ```python
+ default_config["hilink"]["src_file"] += ("uapi_hilink_test.c",)
+ default_config["hilink"]["mapping_header"]["application/samples/wifi/ohos_connect/hilink_adapt/include/"] += ("hilink_test.h",)
+ ```
+
+5. **白名单配置**(可选):
+ ```python
+ default_config["hilink"]["white_list"] += ("TestFuncName",)
+ ```
+
+### 7.3 宏说明
+
+**查表宏定义**:
+- `hilink_call0` / `hilink_call0_ret_void` - 无参数函数
+- `hilink_call1` / `hilink_call1_ret_void` - 1个参数函数
+- `hilink_call2` / `hilink_call2_ret_void` - 2个参数函数
+- `hilink_call3` / `hilink_call3_ret_void` - 3个参数函数
+- `hilink_callx` / `hilink_callx_ret_void` - x个参数函数
+
+**参数说明**:
+1. 枚举值(如 `HILINK_CALL_TEST_FUNC_NAME`)
+2. 函数名
+3. 返回值类型
+4. 参数类型和参数名交替列出
+
+## 8. 相关文件清单
+
+### 8.1 核心脚本文件
+
+| 文件路径 | 功能描述 |
+|----------|----------|
+| `build/script/utils/indie_upgrade_utils.py` | 独立升级工具核心逻辑 |
+| `build/config/target_config/ws63/script/entry.py` | 构建钩子入口 |
+| `build/config/target_config/ws63/build_ws63_update.py` | 升级包构建脚本 |
+| `build/config/target_config/ws63/config.py` | 编译配置文件 |
+| `indie_build.py` | 独立升级编译工具 |
+| `package.py` | 升级包生成工具 |
+
+### 8.2 接口映射相关文件
+
+| 目录/文件 | 描述 |
+|-----------|------|
+| `application/samples/wifi/hilink_indie_upgrade/address_mapping/` | 接口映射根目录 |
+| `application/samples/wifi/hilink_indie_upgrade/address_mapping/include/func_call_list.h` | 函数调用枚举定义(自动生成) |
+| `application/samples/wifi/hilink_indie_upgrade/address_mapping/application/` | App侧接口适配 |
+| `application/samples/wifi/hilink_indie_upgrade/address_mapping/hilinksdk/` | HiLink侧接口适配 |
+| `application/samples/wifi/ohos_connect/hilink_adapt/` | 接口声明头文件目录 |
+
+### 8.3 输出文件
+
+| 文件路径 | 描述 |
+|----------|------|
+| `output/ws63/acore/ws63-liteos-hilink/ws63-liteos-hilink-check.json` | HiLink固件接口校验文件 |
+| `output/ws63/acore/ws63-liteos-app-iot/ws63-liteos-app-iot-check.json` | App-IoT固件接口校验文件(需开启独立升级) |
+| `output/ws63/acore/ws63-liteos-hilink/ws63-liteos-hilink.bin` | HiLink固件二进制文件 |
+| `output/ws63/acore/ws63-liteos-hilink/ws63-liteos-hilink-sign.bin` | HiLink固件签名文件 |
+| `output/ws63/acore/ws63-liteos-app-iot/ws63-liteos-app-iot.bin` | App-IoT固件二进制文件 |
+| `output/ws63/acore/ws63-liteos-app-iot/ws63-liteos-app-iot-sign.bin` | App-IoT固件签名文件 |
+| `output/ws63/fwpkg/ws63-liteos-app-iot/ws63-liteos-app-iot_all.fwpkg` | 完整烧录包 |
+| `output/ws63/upgrade/update.fwpkg` | 升级包 |
+| `output/ws63/ws63-liteos_all.zip` | 完整产物压缩包 |
+
+## 9. 当前项目状态
+
+### 9.1 独立升级配置状态
+
+**当前状态**: 独立升级功能**已关闭**
+
+**证据**:
+- `config.py:334` 行:`"CONFIG_SUPPORT_HILINK_INDIE_UPGRADE"` 被注释
+- `config.py:291` 行:`'liteos_kconfig': 'ws63_iot'` 仍然存在
+- 只有HiLink固件生成了check.json文件
+- App-IoT固件目录下没有对应的check.json文件
+
+### 9.2 编译产物状态
+
+**已生成的文件**:
+- ✅ `ws63-liteos-hilink.bin` (278K)
+- ✅ `ws63-liteos-hilink-sign.bin` (279K)
+- ✅ `ws63-liteos-hilink-check.json` (3.4K)
+- ✅ `ws63-liteos-app-iot.bin` (1.7M)
+- ✅ `ws63-liteos-app-iot-sign.bin` (1.7M)
+- ❌ `ws63-liteos-app-iot-check.json` (未生成,因为独立升级未开启)
+
+## 10. 故障排查指南
+
+### 10.1 check.json文件未生成
+
+**可能原因**:
+1. `CONFIG_SUPPORT_HILINK_INDIE_UPGRADE` 未在配置中启用
+2. 构建过程中 `build_post` 钩子未执行
+3. 接口映射文件生成失败
+
+**排查步骤**:
+1. 检查 `config.py` 中的配置项
+2. 查看构建日志中是否有 "create indie upg mapping files succ" 消息
+3. 检查接口源文件和头文件是否存在语法错误
+
+### 10.2 接口兼容性校验失败
+
+**错误信息示例**:
+```
+indie upg hilink and app not match
+hilink checksum not match
+func 5 [A1B2C3D4:E5F6A7B8] not match
+```
+
+**排查步骤**:
+1. 确定是哪个接口发生了变更(根据func序号)
+2. 检查接口原型是否发生改变
+3. 检查参数类型、顺序、返回值类型
+4. 如果是合理的接口升级,需要重新生成App-IoT的check.json
+
+### 10.3 接口映射表生成失败
+
+**可能原因**:
+1. 源文件中函数原型格式不规范
+2. 头文件中接口声明与源文件实现不匹配
+3. 正则表达式匹配失败
+
+**排查步骤**:
+1. 检查函数原型是否符合标准C语法
+2. 确保头文件声明与源文件实现一致
+3. 查看构建日志中的正则匹配错误信息
+
+## 11. 总结
+
+`ws63-liteos-hilink-check.json` 文件是WS63项目独立升级功能的核心组件,通过CRC32校验码机制确保固件间接口兼容性。虽然当前项目未启用独立升级功能,但完整的技术框架已经就绪,可以通过简单的配置修改来启用该功能。
+
+该机制的核心价值在于:
+- **风险控制**: 通过接口校验防止不兼容升级
+- **灵活部署**: 支持HiLink SDK的独立快速升级
+- **开发效率**: 减少完整固件的编译和测试周期
+- **维护便利**: 清晰的接口约定和自动化校验流程
+
+---
+**文档创建时间**: 2025-09-10
+**项目版本**: SR_Light_Hilink_14.2.1.312_20250714
+**分析对象**: output/ws63/acore/ws63-liteos-hilink/ws63-liteos-hilink-check.json
\ No newline at end of file