293 lines
7.9 KiB
C
293 lines
7.9 KiB
C
/*
|
||
* 自然写智能点阵笔嵌入式固件软件 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;
|
||
}
|