software copyright

This commit is contained in:
jiahong
2026-03-22 15:24:40 +08:00
parent e303bb868a
commit 60f336e345
155 changed files with 127262 additions and 0 deletions
@@ -0,0 +1,292 @@
/*
* 自然写智能点阵笔嵌入式固件软件 V1.0
* power_manager.c - 电源管理模块
*
* 功能说明:
* 1. 低功耗状态机管理(Active/LightSleep/DeepSleep
* 2. 各外设电源域控制
* 3. 唤醒源配置与管理
* 4. 功耗统计与优化
*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "hal_gpio.h"
#include "hal_rtc.h"
/* ========== 电源域定义 ========== */
#define POWER_DOMAIN_CAMERA (1 << 0) /* 摄像头 */
#define POWER_DOMAIN_BLE (1 << 1) /* BLE模块 */
#define POWER_DOMAIN_FLASH (1 << 2) /* 外部Flash */
#define POWER_DOMAIN_SENSOR (1 << 3) /* 压力传感器 */
#define POWER_DOMAIN_LED (1 << 4) /* LED指示灯 */
#define POWER_DOMAIN_ALL 0xFF
/* ========== 唤醒源定义 ========== */
#define WAKEUP_SRC_PEN_TIP (1 << 0) /* 笔尖接触 */
#define WAKEUP_SRC_BUTTON (1 << 1) /* 按键 */
#define WAKEUP_SRC_CHARGER (1 << 2) /* 充电器插入 */
#define WAKEUP_SRC_RTC (1 << 3) /* RTC定时唤醒 */
#define WAKEUP_SRC_BLE (1 << 4) /* BLE连接事件 */
/* ========== 功耗模式参数 ========== */
/* 轻度睡眠时的CPU频率(MHz) */
#define LIGHT_SLEEP_FREQ_MHZ 16
/* 正常工作CPU频率(MHz */
#define ACTIVE_FREQ_MHZ 168
/* RTC唤醒间隔(秒) - 用于周期性电量检查 */
#define RTC_WAKEUP_INTERVAL_S 60
/* ========== 静态变量 ========== */
/* 当前活跃的电源域 */
static uint8_t s_active_domains = POWER_DOMAIN_ALL;
/* 当前唤醒源配置 */
static uint8_t s_wakeup_sources = 0;
/* 功耗统计 */
static uint32_t s_active_time_ms = 0;
static uint32_t s_sleep_time_ms = 0;
/* ========== 电源管理初始化 ========== */
/**
* 初始化电源管理模块
* 配置各电源域控制GPIO,设置默认唤醒源
*/
void power_manager_init(void) {
/* 配置电源控制GPIO */
hal_gpio_config_output(GPIO_CAMERA_POWER);
hal_gpio_config_output(GPIO_FLASH_POWER);
hal_gpio_config_output(GPIO_SENSOR_POWER);
hal_gpio_config_output(GPIO_LED_POWER);
/* 默认所有电源域开启 */
s_active_domains = POWER_DOMAIN_ALL;
/* 默认唤醒源:笔尖触摸 + 充电器 + 按键 */
s_wakeup_sources = WAKEUP_SRC_PEN_TIP | WAKEUP_SRC_CHARGER | WAKEUP_SRC_BUTTON;
/* 初始化功耗统计 */
s_active_time_ms = 0;
s_sleep_time_ms = 0;
}
/* ========== 电源域控制 ========== */
/**
* 使能指定电源域
* @param domain_mask 电源域掩码
*/
void power_domain_enable(uint8_t domain_mask) {
if (domain_mask & POWER_DOMAIN_CAMERA) {
hal_gpio_write(GPIO_CAMERA_POWER, 1);
}
if (domain_mask & POWER_DOMAIN_FLASH) {
hal_gpio_write(GPIO_FLASH_POWER, 1);
}
if (domain_mask & POWER_DOMAIN_SENSOR) {
hal_gpio_write(GPIO_SENSOR_POWER, 1);
}
if (domain_mask & POWER_DOMAIN_LED) {
hal_gpio_write(GPIO_LED_POWER, 1);
}
s_active_domains |= domain_mask;
}
/**
* 禁用指定电源域
* @param domain_mask 电源域掩码
*/
void power_domain_disable(uint8_t domain_mask) {
if (domain_mask & POWER_DOMAIN_CAMERA) {
hal_gpio_write(GPIO_CAMERA_POWER, 0);
}
if (domain_mask & POWER_DOMAIN_FLASH) {
hal_gpio_write(GPIO_FLASH_POWER, 0);
}
if (domain_mask & POWER_DOMAIN_SENSOR) {
hal_gpio_write(GPIO_SENSOR_POWER, 0);
}
if (domain_mask & POWER_DOMAIN_LED) {
hal_gpio_write(GPIO_LED_POWER, 0);
}
s_active_domains &= ~domain_mask;
}
/* ========== 低功耗状态转换 ========== */
/**
* 进入轻度睡眠模式
* - 降低CPU频率到16MHz
* - 关闭摄像头和传感器电源域
* - 保持BLE连接和Flash电源
* - 可由笔尖触摸或BLE事件唤醒
*/
void power_enter_light_sleep(void) {
/* 关闭不必要的电源域 */
power_domain_disable(POWER_DOMAIN_CAMERA | POWER_DOMAIN_SENSOR | POWER_DOMAIN_LED);
/* 降低CPU频率 */
SystemClock_SetFrequency(LIGHT_SLEEP_FREQ_MHZ);
/* 配置唤醒源 */
hal_gpio_set_wakeup(GPIO_PEN_TIP_PIN, GPIO_WAKEUP_RISING);
hal_gpio_set_wakeup(GPIO_BUTTON_PIN, GPIO_WAKEUP_FALLING);
/* 进入CPU SLEEP模式(WFI等待中断) */
__WFI();
/* 唤醒后恢复 */
SystemClock_SetFrequency(ACTIVE_FREQ_MHZ);
power_domain_enable(POWER_DOMAIN_SENSOR | POWER_DOMAIN_LED);
}
/**
* 进入深度睡眠模式
* - 关闭所有外设电源域
* - 断开BLE连接
* - MCU进入STOP/STANDBY模式
* - 仅保留RTC和GPIO唤醒
* - 唤醒后相当于系统复位重启
*/
void power_enter_deep_sleep(void) {
/* 保存关键数据到Flash */
save_power_state();
/* 关闭所有电源域 */
power_domain_disable(POWER_DOMAIN_ALL);
/* 配置RTC唤醒(定时检查电量) */
hal_rtc_set_alarm(RTC_WAKEUP_INTERVAL_S);
/* 配置GPIO唤醒源 */
hal_gpio_set_wakeup(GPIO_PEN_TIP_PIN, GPIO_WAKEUP_RISING);
hal_gpio_set_wakeup(GPIO_USB_DETECT_PIN, GPIO_WAKEUP_RISING);
hal_gpio_set_wakeup(GPIO_BUTTON_PIN, GPIO_WAKEUP_FALLING);
/* 进入STANDBY模式(最低功耗,唤醒后从头执行) */
hal_enter_standby_mode();
}
/* ========== 功耗状态保存/恢复 ========== */
/* Flash中保存电源状态的地址 */
#define POWER_STATE_FLASH_ADDR 0x0000F000
/* 电源状态保存结构 */
typedef struct {
uint32_t magic; /* 魔数 0xPWR55AA */
uint32_t total_active_ms; /* 累计活跃时长 */
uint32_t total_sleep_ms; /* 累计睡眠时长 */
uint32_t boot_count; /* 启动次数 */
uint32_t last_shutdown_reason; /* 上次关机原因 */
uint32_t checksum; /* CRC校验 */
} PowerStateFlash;
/**
* 保存电源状态到Flash
* 在进入深度睡眠前调用
*/
static void save_power_state(void) {
PowerStateFlash state;
state.magic = 0x50575200; /* "PWR\0" */
state.total_active_ms = s_active_time_ms;
state.total_sleep_ms = s_sleep_time_ms;
state.boot_count = 0; /* 将在恢复时递增 */
state.last_shutdown_reason = 0;
/* 计算校验和 */
uint32_t sum = 0;
const uint32_t *data = (const uint32_t *)&state;
uint8_t i;
for (i = 0; i < (sizeof(state) / 4) - 1; i++) {
sum ^= data[i];
}
state.checksum = sum;
/* 写入Flash */
hal_flash_erase_sector(POWER_STATE_FLASH_ADDR);
hal_flash_write(POWER_STATE_FLASH_ADDR, (const uint8_t *)&state, sizeof(state));
}
/**
* 从Flash恢复电源状态
* 在启动时调用
*/
void power_restore_state(void) {
PowerStateFlash state;
hal_flash_read(POWER_STATE_FLASH_ADDR, (uint8_t *)&state, sizeof(state));
if (state.magic != 0x50575200) {
/* 无有效的保存数据 */
return;
}
/* 验证校验和 */
uint32_t sum = 0;
const uint32_t *data = (const uint32_t *)&state;
uint8_t i;
for (i = 0; i < (sizeof(state) / 4) - 1; i++) {
sum ^= data[i];
}
if (sum != state.checksum) {
return; /* 数据损坏 */
}
/* 恢复功耗统计 */
s_active_time_ms = state.total_active_ms;
s_sleep_time_ms = state.total_sleep_ms;
}
/* ========== 功耗统计接口 ========== */
/**
* 更新活跃时间统计
* @param elapsed_ms 经过的毫秒数
*/
void power_update_active_time(uint32_t elapsed_ms) {
s_active_time_ms += elapsed_ms;
}
/**
* 更新睡眠时间统计
* @param elapsed_ms 经过的毫秒数
*/
void power_update_sleep_time(uint32_t elapsed_ms) {
s_sleep_time_ms += elapsed_ms;
}
/**
* 获取累计活跃时长(秒)
*/
uint32_t power_get_active_seconds(void) {
return s_active_time_ms / 1000;
}
/**
* 获取电源效率(活跃时间占比百分比)
*/
uint8_t power_get_efficiency(void) {
uint32_t total = s_active_time_ms + s_sleep_time_ms;
if (total == 0) return 100;
return (uint8_t)((uint64_t)s_active_time_ms * 100 / total);
}
/**
* 获取当前活跃的电源域掩码
*/
uint8_t power_get_active_domains(void) {
return s_active_domains;
}