fix(battery): detect TP4056 charging and full states on new board

This commit is contained in:
chenjintao
2026-10-23 16:23:39 +08:00
parent 415c75b0e6
commit 6116a67d5f
13 changed files with 617 additions and 249 deletions
+10 -7
View File
@@ -403,22 +403,25 @@ void platform_power_release_deep_sleep_holds(void);
esp_err_t platform_power_enter_deep_sleep(int charger_gpio, int button_gpio);
/* platform 只报告原始充电和电压质量,电量等级/SOC 语义由 domain 层计算。 */
typedef enum {
PLATFORM_BATTERY_CHARGE_UNKNOWN = 0,
PLATFORM_BATTERY_CHARGE_NOT_CHARGING,
PLATFORM_BATTERY_CHARGE_CHARGING,
} platform_battery_charge_state_t;
/* 板级数字输入原始电平;电平组合含义及去抖由 domain 唯一解释。 */
typedef struct {
int charge_level;
int full_level;
bool valid;
} platform_battery_charge_inputs_t;
/** 读取两路原始电平;无 ADC 访问,互斥等待最多100ms。 */
esp_err_t platform_battery_read_charge_inputs(platform_battery_charge_inputs_t *out_inputs);
typedef struct {
int adc_voltage_mv;
int voltage_mv;
platform_battery_charge_state_t charge_state;
bool voltage_valid;
bool high_load_active;
bool cooldown_active;
} platform_battery_sample_t;
/** 幂等初始化电池 ADC 和 TP4057 状态输入。 / Idempotently initialize battery sensing. */
/** 幂等初始化电池 ADC 和 TP4056 两路状态输入。 / Idempotently initialize battery sensing. */
esp_err_t platform_battery_init(void);
/**
@@ -41,6 +41,7 @@ static adc_oneshot_unit_handle_t s_adc_handle;
static adc_cali_handle_t s_cali_handle;
static adc_channel_t s_adc_channel;
static bool s_initialized;
static bool s_inputs_initialized;
static StaticSemaphore_t s_adc_lock_buffer;
static SemaphoreHandle_t s_adc_lock;
static portMUX_TYPE s_adc_lock_init_guard = portMUX_INITIALIZER_UNLOCKED;
@@ -123,6 +124,53 @@ static esp_err_t create_calibration(adc_unit_t unit, adc_channel_t channel)
return ESP_ERR_NOT_SUPPORTED;
}
/* 调用者持有 ADC/输入互斥锁;数字输入可独立初始化,不依赖 ADC 校准成功。 */
static esp_err_t configure_charge_inputs_locked(void)
{
if (s_inputs_initialized) {
return ESP_OK;
}
if (!GPIO_IS_VALID_GPIO(CONFIG_TQ_BATTERY_CHARGE_GPIO) ||
!GPIO_IS_VALID_GPIO(CONFIG_TQ_BATTERY_FULL_GPIO) ||
CONFIG_TQ_BATTERY_CHARGE_GPIO == CONFIG_TQ_BATTERY_FULL_GPIO ||
CONFIG_TQ_BATTERY_ADC_GPIO == CONFIG_TQ_BATTERY_CHARGE_GPIO ||
CONFIG_TQ_BATTERY_ADC_GPIO == CONFIG_TQ_BATTERY_FULL_GPIO) {
return ESP_ERR_INVALID_ARG;
}
gpio_config_t config = {
.pin_bit_mask = gpio_mask(CONFIG_TQ_BATTERY_CHARGE_GPIO) |
gpio_mask(CONFIG_TQ_BATTERY_FULL_GPIO),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE,
};
esp_err_t err = gpio_config(&config);
if (err == ESP_OK) {
s_inputs_initialized = true;
}
return err;
}
esp_err_t platform_battery_read_charge_inputs(platform_battery_charge_inputs_t *out_inputs)
{
if (out_inputs == NULL) {
return ESP_ERR_INVALID_ARG;
}
memset(out_inputs, 0, sizeof(*out_inputs));
if (!lock_adc()) {
return ESP_ERR_TIMEOUT;
}
esp_err_t err = configure_charge_inputs_locked();
if (err == ESP_OK) {
out_inputs->charge_level = gpio_get_level(CONFIG_TQ_BATTERY_CHARGE_GPIO);
out_inputs->full_level = gpio_get_level(CONFIG_TQ_BATTERY_FULL_GPIO);
out_inputs->valid = true;
}
unlock_adc();
return err;
}
esp_err_t platform_battery_init(void)
{
if (!lock_adc()) {
@@ -133,24 +181,10 @@ esp_err_t platform_battery_init(void)
return ESP_OK;
}
if (CONFIG_TQ_BATTERY_CHARGE_GPIO >= GPIO_NUM_MAX) {
esp_err_t input_err = configure_charge_inputs_locked();
if (input_err != ESP_OK) {
unlock_adc();
return ESP_ERR_INVALID_ARG;
}
if (CONFIG_TQ_BATTERY_CHARGE_GPIO >= 0) {
gpio_config_t charge_config = {
.pin_bit_mask = gpio_mask(CONFIG_TQ_BATTERY_CHARGE_GPIO),
.mode = GPIO_MODE_INPUT,
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.intr_type = GPIO_INTR_DISABLE,
};
esp_err_t gpio_err = gpio_config(&charge_config);
if (gpio_err != ESP_OK) {
ESP_LOGE(TAG, "Configure charger status GPIO failed: %s", esp_err_to_name(gpio_err));
unlock_adc();
return gpio_err;
}
return input_err;
}
adc_unit_t unit = ADC_UNIT_1;
@@ -295,14 +329,6 @@ esp_err_t platform_battery_read_sample(platform_battery_sample_t *out_sample)
out_sample->voltage_mv <= BATTERY_VALID_MAX_MV;
snapshot_load_state(&out_sample->high_load_active, &out_sample->cooldown_active);
if (CONFIG_TQ_BATTERY_CHARGE_GPIO < 0) {
out_sample->charge_state = PLATFORM_BATTERY_CHARGE_UNKNOWN;
} else {
int level = gpio_get_level((gpio_num_t)CONFIG_TQ_BATTERY_CHARGE_GPIO);
out_sample->charge_state = level == CONFIG_TQ_BATTERY_CHARGE_ACTIVE_LEVEL
? PLATFORM_BATTERY_CHARGE_CHARGING
: PLATFORM_BATTERY_CHARGE_NOT_CHARGING;
}
unlock_adc();
return ESP_OK;
}
@@ -341,6 +367,14 @@ void platform_battery_load_end(platform_battery_load_source_t source)
#else
esp_err_t platform_battery_read_charge_inputs(platform_battery_charge_inputs_t *out_inputs)
{
if (out_inputs != NULL) {
memset(out_inputs, 0, sizeof(*out_inputs));
}
return ESP_ERR_NOT_SUPPORTED;
}
esp_err_t platform_battery_init(void)
{
return ESP_ERR_NOT_SUPPORTED;