当前位置: 首页 > news >正文

[单片机框架][device层] charger 电源管理

通过 DEVICE_INITCALL(“dev-chg”, charger_dev_init); 注册驱动,自动在main初始化中运行。
优点:耦合少,可移植性强,适用大团队模块化开发
缺点:抽象度高,小团队开发时间耗时久

  1. CPU在运行时根据系统负载进行动态电压和频率变换的CPUFreq

  2. CPU在系统空闲时根据空闲的情况进行低功耗模式的CPUIdle

  3. 多核系统下CPU的热插拔支持

  4. 系统和设备对于延迟的特别需求而提出申请的PM QoS,它会作用于CPUIdle的具体策略

  5. 设备驱动针对系统Suspend to RAM/Disk的一系列入口函数

  6. SoC进入suspend状态、SDRAM自刷新的入口

  7. 设备的runtime(运行时)动态电源管理,根据使用情况动态开关设备

  8. 底层的时钟、稳压器、频率/电压表(OPP模块完成)支撑,各驱动子系统都可能用到

模拟linux的电源管理
在这里插入图片描述

APP层使用方法:app – power – power_charger.c

#include "charger_dev.h"
#include "charger.h"
#include "power_charger.h"
static device_t* g_charger_dev = NULL;

int32_t charger_init(void){
    int32_t ret;
    g_charger_dev = device_find("dev-chg");
    if (g_charger_dev == NULL) {
        POWER_CHARGER_LOG_E("[power][charger]:device_find fail\r\n");
        return RETVAL(E_NULL);
    }

    ret = device_open(g_charger_dev, DEVICE_OFLAG_RDWR);
    if (ret != RETVAL(E_OK))
        POWER_CHARGER_LOG_E("[power][charger]:device_open fail\r\n");
    return ret;
}


int32_t charger_enable(uint32_t enable) {
    int32_t ret;
    charger_property_t prop;
    prop.charger_prop = CHARGER_ENABLE_CHARGING;
    prop.val = enable;
    ret = device_ioctl(g_charger_dev, CHARGER_DEV_SET_PROPERTY, &prop);
    if (ret != RETVAL(E_OK))
        POWER_CHARGER_LOG_E("[power][charger]:charger_enable fail\r\n");
    return ret;
}

int32_t charger_set_current(uint32_t current) {
    int32_t ret;
    charger_property_t prop;
    prop.charger_prop = CHARGER_SET_CHARGE_CURRENT;
    prop.val = current;
    ret = device_ioctl(g_charger_dev, CHARGER_DEV_SET_PROPERTY, &prop);
    if (ret != RETVAL(E_OK))
        POWER_CHARGER_LOG_E("[power][charger]:set_current fail\r\n");

    return ret;
}

int32_t charger_set_voltage(uint32_t voltage) {
    int32_t ret;
    charger_property_t prop;
    prop.charger_prop = CHARGER_SET_CHARGE_VOLTAGE;
    prop.val = voltage;
    ret = device_ioctl(g_charger_dev, CHARGER_DEV_SET_PROPERTY, &prop);
    if (ret != RETVAL(E_OK))
        POWER_CHARGER_LOG_E("[power][charger]:set_voltage fail\r\n");
    return ret;
}

int32_t charger_set_terminal_current(uint32_t current) {
    int32_t ret;
    charger_property_t prop;
    prop.charger_prop = CHARGER_SET_TERMINAL_CURRENT;
    prop.val = current;
    ret = device_ioctl(g_charger_dev, CHARGER_DEV_SET_PROPERTY, &prop);
    if (ret != RETVAL(E_OK))
        POWER_CHARGER_LOG_E("[power][charger]:set_terminal_current fail\r\n");
    return ret;
}

int32_t charger_set_watchdog(uint32_t value) {
    int32_t ret;
    charger_property_t prop;
    prop.charger_prop = CHARGER_SET_FEEDING_WATCHDOG;
    prop.val = value;

    ret = device_ioctl(g_charger_dev, CHARGER_DEV_SET_PROPERTY, &prop);
    if (ret != RETVAL(E_OK))
        POWER_CHARGER_LOG_E("[power][charger]:feeding watchdog fail\r\n");
    return ret;
}

int32_t charger_get_vbus_status(uint32_t* status) {
    int32_t ret;
    charger_property_t prop;
    prop.charger_prop = CHARGER_GET_VBUS_STATUS;
    ret = device_ioctl(g_charger_dev, CHARGER_DEV_GET_PROPERTY, &prop);
    if (ret != RETVAL(E_OK))
        POWER_CHARGER_LOG_E("[power][charger]:get_vbus_status fail\r\n");
    *status = prop.val;
    return ret;
}

int32_t charger_get_usb_status(void) {
    int32_t ret;
    charger_property_t prop;
    prop.charger_prop = CHARGER_GET_USB_STATUS;
    ret = device_ioctl(g_charger_dev, CHARGER_DEV_GET_PROPERTY, &prop);
    if (ret != RETVAL(E_OK))
        POWER_CHARGER_LOG_E("[power][charger]:get_usb_status fail\r\n");
    return ret;
}

int32_t charger_get_charger_status(uint32_t* status) {
    int32_t ret;
    charger_property_t prop;
    prop.charger_prop = CHARGER_GET_CHARGE_STATUS;
    ret = device_ioctl(g_charger_dev, CHARGER_DEV_GET_PROPERTY, &prop);
    if (ret != RETVAL(E_OK))
        POWER_CHARGER_LOG_E("[power][charger]:get_charger_status fail\r\n");
    *status = prop.val;
    return ret;
}

int32_t charger_register_callback(charger_event_cb_t cb) {
    int32_t ret;
    ret = device_ioctl(g_charger_dev, CHARGER_DEV_SET_CALLBACK, cb);
    if (ret != RETVAL(E_OK))
        POWER_CHARGER_LOG_E("[power][charger]:register_callback fail\r\n");
    return ret;
}

驱动初始化代码:

#include "typedefs.h"
#include "log.h"

#include "modules.h"

extern initcall_t __initcall_start;
extern initcall_t __initcall_end;

void modules_setup(void)
{
    initcall_t *call;

    for (call = &__initcall_start; call < &__initcall_end; call++)
    {
        // LOG_C("[modules]:%s init\r\n", call->name);
        call->initcall();
    }
}


/**
 * @brief  Main function.
 */
int main(void) {
    hardware_init();
    modules_setup(); // 将驱动、设备、app层依次初始化

    LOG_C("[main]:kernel start...\r\n");
    start_kernel();
    while (1) {
    }
}

驱动代码:

#include <string.h>

#include "typedefs.h"
#include "errorno.h"
#include "modules.h"
#include "log.h"

#include "charger_dev.h"

static char* charger_drv_match_ids[] = {
    "bq25601",
};

static int32_t charger_dev_open(device_t *dev)
{
    uint8_t i = 0;
    charger_driver_t *pdrv_charger;

    if (dev == NULL)
    {
        return RETVAL(E_NULL);
    }

    if (dev->dev_drv != NULL)
    {
        return RETVAL(E_OK);
    }

    for (i=0; i<ARRAY_SIZE(charger_drv_match_ids); i++)
    {
        pdrv_charger = charger_driver_find(charger_drv_match_ids[i]);
        if (pdrv_charger)
        {
            if (charger_driver_probe(pdrv_charger) == RETVAL(E_OK))
            {
                dev->dev_drv = (void*)pdrv_charger;
                charger_driver_init(pdrv_charger);
                return RETVAL(E_OK);
            }
        }
    }

    return RETVAL(E_FAIL);
}

static xssize_t charger_dev_read(device_t *dev, char *buffer, xsize_t size, xloff_t *pos)
{
    xssize_t ret = 0;
    ret = charger_driver_read_data((charger_driver_t*)dev->dev_drv, (charger_data_t*)buffer);
    if (ret != RETVAL(E_OK))
    {
        LOG_E("[charger_dev][charger_dev_read] charger dev read data failed!!!\r\n");
    }
    return ret;
}

static xssize_t charger_dev_write(device_t *dev, const char *buffer, xsize_t size, xloff_t *pos)
{
    xssize_t ret = 0;
    ret = charger_driver_write_data((charger_driver_t*)dev->dev_drv, (charger_data_t*)buffer);
    if (ret != RETVAL(E_OK))
    {
        LOG_E("[charger_dev][charger_dev_write] charger dev read write failed!!!\r\n");
    }
    return ret;
}

static int32_t charger_dev_ioctl(device_t *dev, uint32_t cmd, void *args)
{
    switch (cmd)
    {
        case CHARGER_DEV_GET_PROPERTY:
            return charger_driver_get_property((charger_driver_t*)dev->dev_drv, args);
        case CHARGER_DEV_SET_PROPERTY:
            return charger_driver_set_property((charger_driver_t*)dev->dev_drv, args);
        case CHARGER_DEV_SET_CALLBACK:
            return charger_driver_set_callback((charger_driver_t*)dev->dev_drv, args);
        default:
        break;
    }

    return RETVAL(E_OK);
}

const device_ops_t charger_dev_ops =
{
   /* (*open)  */ charger_dev_open,
   /* (*close) */ NULL,
   /* (*read)  */ charger_dev_read,
   /* (*write) */ charger_dev_write,
   /* (*ioctl) */ charger_dev_ioctl,
};

static void charger_dev_init(void)
{
    static device_t charger_dev;
    int32_t ret;

    memset(&charger_dev, 0, sizeof(device_t));
    charger_dev.type = DEVICE_CLASS_CHAR;
    charger_dev.dev_ops = &charger_dev_ops;

    ret = device_register(&charger_dev, "dev-chg", DEVICE_FLAG_WRONLY);
    if (ret < 0)
    {
        LOG_E("[charger_dev][init]:register failed ret=%d\r\n", ret);
    }
}

DEVICE_INITCALL("dev-chg", charger_dev_init);

#ifndef _CHARGER_DEV_H_
#define _CHARGER_DEV_H_

#include "../../object/device.h"
#include "charger.h"

#endif // _CHARGER_DEV_H_

相关文章:

  • [单片机框架][drivers层][bq25601] charger 电源管理
  • Java多线程--InheritableThreadLocal--使用/实例
  • java计算机毕业设计宿迁学院学生设计作品交流网站源代码+数据库+系统+lw文档
  • ByteTrack:通过关联每个检测框进行多对象跟踪
  • 新能源汽车行业资讯-2022-9-22
  • Ajax学习笔记(一)
  • 【【计算机组成原理】中央处理器(二)—— 指令执行过程
  • YOLOv5、v7改进之二十八:ICLR 2022涨点神器——即插即用的动态卷积ODConv
  • php警车管理系统设计与实现
  • 提高PHP编程效率的技巧
  • 安防单位怎么实施RPA新员工提升企业运作效率
  • 线程安全问题的原因和解决方案
  • zabbix配置邮件告警
  • 【Vue】Mixin 混入的基础语法(1)
  • JavaEE:synchronized关键字
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • ES6系统学习----从Apollo Client看解构赋值
  • If…else
  • iOS 颜色设置看我就够了
  • JavaScript创建对象的四种方式
  • PaddlePaddle-GitHub的正确打开姿势
  • TypeScript实现数据结构(一)栈,队列,链表
  • WordPress 获取当前文章下的所有附件/获取指定ID文章的附件(图片、文件、视频)...
  • 翻译 | 老司机带你秒懂内存管理 - 第一部(共三部)
  • 给Prometheus造假数据的方法
  • 跨域
  • 突破自己的技术思维
  • 线性表及其算法(java实现)
  • 一个SAP顾问在美国的这些年
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 移动互联网+智能运营体系搭建=你家有金矿啊!
  • # Apache SeaTunnel 究竟是什么?
  • # 数据结构
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • (6)添加vue-cookie
  • (C#)Windows Shell 外壳编程系列9 - QueryInfo 扩展提示
  • (非本人原创)史记·柴静列传(r4笔记第65天)
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (利用IDEA+Maven)定制属于自己的jar包
  • (最完美)小米手机6X的Usb调试模式在哪里打开的流程
  • .NET delegate 委托 、 Event 事件
  • .net2005怎么读string形的xml,不是xml文件。
  • .NET设计模式(8):适配器模式(Adapter Pattern)
  • :如何用SQL脚本保存存储过程返回的结果集
  • @Data注解的作用
  • @transactional 方法执行完再commit_当@Transactional遇到@CacheEvict,你的代码是不是有bug!...
  • @Validated和@Valid校验参数区别
  • [ 数据结构 - C++]红黑树RBTree
  • [ 云计算 | AWS ] 对比分析:Amazon SNS 与 SQS 消息服务的异同与选择
  • [Android View] 可绘制形状 (Shape Xml)
  • [Ariticle] 厚黑之道 一 小狐狸听故事
  • [c]统计数字
  • [C++提高编程](三):STL初识