power/battery: fake gauge support for rpmsg communication

realize a fake gauge to support powermanger

Signed-off-by: yezhonghui <yezhonghui@xiaomi.com>
This commit is contained in:
yezhonghui
2024-12-23 15:23:38 +08:00
committed by Alan C. Assis
parent dba108ae5c
commit db7f292709
7 changed files with 384 additions and 0 deletions
@@ -0,0 +1,67 @@
===============
Battery Gauge
===============
Battery gauge driver for NuttX that measurement battery data (voltage,
current, capacity, temperature, and charging status) for charger and
healthd in production.
Fake Gauge
==========
A fake battery gauge driver for NuttX that simulates battery data (voltage,
current, capacity, temperature, and charging status) for testing and
development purposes. it provides mock battery data without requiring physical
battery hardware.It generates random values within predefined ranges and
updates them periodically, making it useful for:
- Testing battery monitoring applications
- Developing power management features
- Debugging battery-related logic without real hardware
Features
========
The Fake gauge simulates key battery parameters.
Voltage (mV):
- Voltage ranges: 4000mV to 4200mV
Current (mA):
- Current ranges: -100mA to 500mA
- Current resolution: 1mA
Capacity (%):
- Capacity ranges: 0% to 100%
- Capacity resolution: 1%
Temperature (0.1°C):
- Temperature resolution: 0.1°C
Charging Status:
- Charging
- Discharging
- Not charging
Periodic data updates (default: 5 seconds)
Compatible with NuttX battery gauge framework.
Usage
=====
File Information
- Path: drivers/power/battery/battery_fakegauge.c
- License: Apache License 2.0
Dependencies
- NuttX operating system
- NuttX battery gauge framework (nuttx/power/battery_gauge.h)
- NuttX work queue for periodic updates
Configuration
- Enable the fake gauge driver in the NuttX configuration file (CONFIG_BATTERY_FAKEGAUGE=y)
- Configure the update interval in seconds (CONFIG_BATTERY_FAKEGAUGE_UPDATE_INTERVAL)
This driver is intended for development and testing only, not for production use with
real batteries.
@@ -6,3 +6,4 @@ Power-related Drivers
:caption: Supported Drivers
pm/index.rst
battery/fakegauge.rst
+4
View File
@@ -92,4 +92,8 @@ if(CONFIG_GOLDFISH_BATTERY)
list(APPEND SRCS goldfish_battery.c)
endif()
if(CONFIG_BATTERY_FAKE_GAUGE)
list(APPEND SRCS battery_fakegauge.c)
endif()
target_sources(drivers PRIVATE ${SRCS})
+7
View File
@@ -160,4 +160,11 @@ config GOLDFISH_BATTERY
---help---
The GOLDFISH_BATTERY are battery charger for emulate batteries.
config BATTERY_FAKE_GAUGE
bool "Battery fake gauge support"
default n
depends on BATTERY_GAUGE
---help---
The BATTERY FAKE are battery charger for emulate gauge.
endmenu
+4
View File
@@ -90,5 +90,9 @@ ifeq ($(CONFIG_GOLDFISH_BATTERY),y)
CSRCS += goldfish_battery.c
endif
ifeq ($(CONFIG_BATTERY_FAKE_GAUGE),y)
CSRCS += battery_fakegauge.c
endif
DEPPATH += --dep-path power/battery
VPATH += power/battery
+286
View File
@@ -0,0 +1,286 @@
/****************************************************************************
* drivers/power/battery/battery_fakegauge.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/arch.h>
#include <nuttx/wqueue.h>
#include <nuttx/clock.h>
#include <nuttx/kmalloc.h>
#include <nuttx/nuttx.h>
#include <nuttx/power/battery_gauge.h>
#include <nuttx/power/battery_ioctl.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define BATTERY_FAKE_VOLTAGE_MAX (4200)
#define BATTERY_FAKE_VOLTAGE_MIN (4000)
#define BATTERY_FAKE_CURRENT_MAX (500)
#define BATTERY_FAKE_CURRENT_MIN (100)
#define BATTERY_FAKE_CAPACITY_MAX (100)
#define BATTERY_FAKE_CAPACITY_MIN (60) // we dont want too lower
#define BATTERY_FAKE_TEMP_MAX (420)
#define BATTERY_FAKE_TEMP_MIN (220)
#define BATTERY_FAKE_WORK_DELAY MSEC2TICK(5000)
#define BATTERY_FAKE_GAUGE "/dev/charge/fakegauge"
/****************************************************************************
* Private type
****************************************************************************/
struct battery_fake_data_s
{
uint32_t present;
uint32_t voltage;
uint32_t capacity;
uint32_t current;
uint32_t temperature;
uint32_t status;
};
struct battery_fake_gauge_s
{
struct battery_gauge_dev_s battery;
struct battery_fake_data_s data;
struct work_s poll_work;
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int battery_fake_present(FAR struct battery_gauge_dev_s *dev,
FAR bool *status);
static int battery_fake_state(FAR struct battery_gauge_dev_s *dev,
FAR int *status);
static int battery_fake_voltage(FAR struct battery_gauge_dev_s *dev,
FAR int *value);
static int battery_fake_capacity(FAR struct battery_gauge_dev_s *dev,
FAR int *value);
static int battery_fake_current(FAR struct battery_gauge_dev_s *dev,
FAR int *value);
static int battery_fake_temperature(FAR struct battery_gauge_dev_s *dev,
FAR int *value);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct battery_gauge_operations_s g_battery_fake_ops =
{
battery_fake_state,
battery_fake_present,
battery_fake_voltage,
battery_fake_capacity,
battery_fake_current,
battery_fake_temperature,
NULL,
};
/****************************************************************************
* Private Functions
****************************************************************************/
static int battery_fake_present(FAR struct battery_gauge_dev_s *dev,
FAR bool *status)
{
/* fake gauge is always keep present */
*status = true;
return OK;
}
static int battery_fake_state(FAR struct battery_gauge_dev_s *dev,
FAR int *status)
{
FAR struct battery_fake_gauge_s *priv =
container_of(dev, struct battery_fake_gauge_s, battery);
*status = priv->data.status;
return OK;
}
static int battery_fake_voltage(FAR struct battery_gauge_dev_s *dev,
FAR int *value)
{
FAR struct battery_fake_gauge_s *priv =
container_of(dev, struct battery_fake_gauge_s, battery);
*value = priv->data.voltage;
return OK;
}
static int battery_fake_capacity(FAR struct battery_gauge_dev_s *dev,
FAR int *value)
{
FAR struct battery_fake_gauge_s *priv =
container_of(dev, struct battery_fake_gauge_s, battery);
*value = priv->data.capacity;
return OK;
}
static int battery_fake_current(FAR struct battery_gauge_dev_s *dev,
FAR int *value)
{
FAR struct battery_fake_gauge_s *priv =
container_of(dev, struct battery_fake_gauge_s, battery);
*value = priv->data.current;
return OK;
}
static int battery_fake_temperature(FAR struct battery_gauge_dev_s *dev,
FAR int *value)
{
FAR struct battery_fake_gauge_s *priv =
container_of(dev, struct battery_fake_gauge_s, battery);
*value = priv->data.temperature;
return OK;
}
static void battery_fake_data_init(FAR struct battery_fake_data_s *data)
{
data->status = BATTERY_CHARGING;
data->capacity = BATTERY_FAKE_CAPACITY_MIN;
data->temperature = BATTERY_FAKE_TEMP_MIN;
data->voltage = BATTERY_FAKE_VOLTAGE_MIN;
data->current = BATTERY_FAKE_CURRENT_MIN;
data->present = true;
}
static int battery_fake_data_charged(FAR struct battery_fake_gauge_s *priv)
{
FAR struct battery_fake_data_s *data = &priv->data;
int capacity;
int voltage;
int current;
int temp;
int ret;
/* capacity */
capacity = BATTERY_FAKE_CAPACITY_MIN +
rand() % (BATTERY_FAKE_CAPACITY_MAX - BATTERY_FAKE_CAPACITY_MIN + 1);
data->capacity = capacity;
/* voltage */
voltage = BATTERY_FAKE_VOLTAGE_MIN +
rand() % (BATTERY_FAKE_VOLTAGE_MAX - BATTERY_FAKE_VOLTAGE_MIN + 1);
data->voltage = voltage;
/* current */
current = BATTERY_FAKE_CURRENT_MIN +
rand() % (BATTERY_FAKE_CURRENT_MAX - BATTERY_FAKE_CURRENT_MIN + 1);
data->current = current;
/* temperature */
temp = BATTERY_FAKE_TEMP_MIN +
rand() % (BATTERY_FAKE_TEMP_MAX - BATTERY_FAKE_TEMP_MIN + 1);
data->temperature = temp;
if (data->capacity > 10 && data->capacity < 95)
{
data->status = BATTERY_CHARGING;
}
else if (data->capacity >= 100)
{
data->status = BATTERY_DISCHARGING;
data->current = 0;
}
else if (data->capacity >= 95 && data->capacity < 100)
{
data->status = BATTERY_FULL;
}
else
{
data->status = BATTERY_UNKNOWN;
}
ret = battery_gauge_changed(&priv->battery, BATTERY_STATE_CHANGED |
BATTERY_VOLTAGE_CHANGED |
BATTERY_CURRENT_CHANGED |
BATTERY_CAPACITY_CHANGED |
BATTERY_TEMPERATURE_CHANGED);
if (ret < 0)
{
baterr("battery fake gauge changed failed %d\n", ret);
}
return ret;
}
static void battery_fake_work(FAR void *arg)
{
FAR struct battery_fake_gauge_s *priv =
(FAR struct battery_fake_gauge_s *)arg;
battery_fake_data_charged(priv);
work_queue(LPWORK, &priv->poll_work, battery_fake_work, priv,
BATTERY_FAKE_WORK_DELAY);
}
/****************************************************************************
* Public Functions
****************************************************************************/
int battery_fake_gauge_register()
{
int ret;
FAR struct battery_fake_gauge_s *priv;
priv = kmm_zalloc(sizeof(struct battery_fake_gauge_s));
if (NULL == priv)
{
baterr(" no enough memory\n");
return -ENOMEM;
}
battery_fake_data_init(&priv->data);
priv->battery.ops = &g_battery_fake_ops;
ret = battery_gauge_register(BATTERY_FAKE_GAUGE, &priv->battery);
if (ret < 0)
{
baterr("battery_gauge_register %s failed\n", BATTERY_FAKE_GAUGE);
kmm_free(priv);
return ret;
}
work_queue(LPWORK, &priv->poll_work, battery_fake_work, priv,
BATTERY_FAKE_WORK_DELAY);
batinfo("battery fake gauge register successfully\n");
return 0;
}
+15
View File
@@ -277,6 +277,21 @@ FAR struct battery_gauge_dev_s *max1704x_initialize(
int goldfish_battery_register(FAR void *regs, int irq);
#endif
#if defined(CONFIG_BATTERY_FAKE_GAUGE)
/****************************************************************************
* Name: battery_fake_gauge_register
* Description:
* Register a emulate battery to the upper-half gauge driver.
*
* Returned Value:
* Zero on success or a negated errno value on failure.
*
*
****************************************************************************/
int battery_fake_gauge_register(void);
#endif
#undef EXTERN
#ifdef __cplusplus
}