0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

电源管理入门-7 DevFreq

yzcdx 来源:OS与AUTOSAR研究 2023-10-16 17:06 次阅读

上一小节介绍了CPU的调频,那么其他设备例如DDRUSB、SPI,还有很多子系统有自己的R核或者M核例如NPU、ISP等都需要调频,那必须OPP给安排上,然后调频就需要我们这里说的DevFreq框架。

1. 整体介绍

1.1 Devfreq基础概念

OPP:

复杂SoC由多个子模块协同工作组成,在运行中并非SoC中的所有模块都需要始终保持最高性能。为方便起见,将SoC中的子模块分组为域,从而允许某些域以较低的电压和频率运行,而其他域以较高的电压/频率对运行。对于这些设备支持的频率和电压对,我们称之为OPP(Operating Performance Point)。对于具有OPP功能的非CPU设备,本文称之为OPP device,需要通过devfreq进行动态的调频调压。

Devfreq:

devfreq:Generic Dynamic Voltage and Frequency Scaling (DVFS) Framework for Non-CPU Devices。是由三星电子MyungJoo Ham myungjoo.ham@samsung.com,提交到社区。原理和/deivers/cpufreq 非常近似。但是cpufreq驱动并不允许多个设备来注册,而且也不适合不同的设备具有不同的governor。devfreq则支持多个设备,并且允许每个设备有自己对应的governor。

如下图,devfreq framework是功耗子系统的一部分,与cpufreq,cpuidle,powermanager相互配合协作,达到节省系统功耗的目的。

0963d5ea-6bf9-11ee-939d-92fbcf53809c.png

1.2 devfreq框图

097fc4d0-6bf9-11ee-939d-92fbcf53809c.png整个devfreq framework中的三大部分组成:

  1. Devfreq core:devfreq framework的核心,一方面提供需要调频调压设备及governor的注册方法,通过devfreq_list及governor_list分别管理所有的调频调压设备及注册进系统的governor。另一方面,提供具体调频调压的处理逻辑,通过从governor获取目标频率,提供update_devfreq方法供governor调用,从而实现调频调压。
  2. Governor:具体的调频策略,需要devfreq framework提供的接口进行注册。内核中已经支持如下策略:
  • simple_ondemand:按需调整模式;根据系统负载,动态地调整频率、电压,平衡性能和功耗。
  • Performance:性能优先模式,将频率及电压调整到最大。
  • Powersave:功耗优先模式,将频率及电压调整到最小。
  • Userspace:用户指定模式,用户通过提供的文件节点,根据需要设置的频率及电压。
  • Passive:被动模式,使用设备指定方法做频率、电压调整,或跟随父devfreq设备的governor进行调整。
  1. Devfreq device driver:需要调频调压的设备驱动,需要通过devfreq framework提供的接口进行注册。会通过opp库提供的dts解析函数解析opp频率、电压对。在调频的时候,根据opp库提供频率、电压调整接口借助clk、regulator框架进行调频调压。在查询当前频率时,通过get_cur_freq查询当前的频率。

可以看到这里DevFreq和CPUFreq的套路基本一样。

1.3 sysfs用户接口

这里以DDR为例:/sys/devices/platform/dmc0/devfreq/devfreq0目录下面

099f188a-6bf9-11ee-939d-92fbcf53809c.png
  • available_frequencies: 可用的频率列表
  • available_governors:可用的governor
  • cur_freq:当前频率
  • governor: 当前governor
  • max_freq:最大频率
  • min_freq :最小频率
  • polling_interval:governor调度的时间间隔,单位是ms
  • target_freq:目标频率
  • trans_stat:状态调整表

代码实现在kernel/drivers/devfreq/devfreq.c中

static struct attribute *devfreq_attrs[] = {
        &dev_attr_governor.attr,
        &dev_attr_available_governors.attr,
        &dev_attr_cur_freq.attr,
        &dev_attr_available_frequencies.attr,
        &dev_attr_target_freq.attr,
        &dev_attr_polling_interval.attr,
        &dev_attr_min_freq.attr,
        &dev_attr_max_freq.attr,
        &dev_attr_trans_stat.attr,
        NULL,
};
ATTRIBUTE_GROUPS(devfreq);

2. Linux 关键数据结构和API实现

2.1 主要数据结构

09bdfebc-6bf9-11ee-939d-92fbcf53809c.png

devfreq数据结构和模块关系图

09d8ced6-6bf9-11ee-939d-92fbcf53809c.png

2.1.1 devfreq_dev_profile

devfreq profile结构体,是OPP device注册到devfreq framework的数据结构,主要包含OPP设备的频率相关信息和相关的回调函数,是devfreq framework和OPP device driver的交互接口。

struct devfreq_dev_profile {
    /*devfreq初始化频率*/
    unsigned long initial_freq;
    /*governor轮询的时间间隔,单位ms,0禁止*/
    unsigned int polling_ms;

    /*devfreq framework设置OPP device频率的回掉函数*/int (*target)(struct device *dev, unsigned long *freq, u32 flags);
    /*devfreq framework获取OPP device负载状态的回掉函数*/int (*get_dev_status)(struct device *dev, struct devfreq_dev_status *stat);
    /*devfreq framework获取OPP device当前频率的回掉函数*/int (*get_cur_freq)(struct device *dev, unsigned long *freq);
    /*devfreq framework退出时对OPP device的回掉函数*/void (*exit)(struct device *dev);

    /*OPP device支持的频率表*/
    unsigned long *freq_table;
    /*freq_table表的大小*/
    unsigned int max_state;
};

初始化使用:

static struct devfreq_dev_profile xxx_devfreq_dmc_profile = {
        .polling_ms        = 300,
        .target                = xxx_dmcfreq_target,
        .get_dev_status        = xxx_dmcfreq_get_dev_status,
        .get_cur_freq        = xxx_dmcfreq_get_cur_freq,
};

2.1.2 devfreq_governor

devfreq governor结构体,是governor注册到devfreq framework的数据结构,主要包含governor的相关属性和具体的函数实现。是devfreq framework和governor交互接口。

struct devfreq_governor {
    struct list_head node;

    /*该governor的名称*/const char name[DEVFREQ_NAME_LEN];
    /*governor是否可以切换的标志,若为1表示不可切换*/const unsigned int immutable;
    /*governor注册到devfreq framework的算法实现函数,返回调整后的频率*/int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
    /*governor注册到devfreq framework的event处理函数,处理start,stop,suspend,resume等event*/int (*event_handler)(struct devfreq *devfreq, unsigned int event, void *data);
};

例如使用simple_ondemand

static struct devfreq_governor devfreq_simple_ondemand = {
        .name = "simple_ondemand",
        .get_target_freq = devfreq_simple_ondemand_func,
        .event_handler = devfreq_simple_ondemand_handler,
};

2.1.3 devfreq

devfreq设备结构体,这个是devfreq设备的核心数据结构。将上述的OPP device driver的devfreq_dev_profile和governor的devfreq_governor连接到一起,并通过设备驱动模型中device类,为user 空间提供接口。

struct devfreq {
    struct list_head node;

    struct mutex lock;
    struct mutex event_lock;
    /*其class属于devfreq_class,父节点指向使用devfreq的device*/struct device dev;
    /*OPP device注册到devfreq framework的配置信息*/struct devfreq_dev_profile *profile;
    /*governor注册到devfreq framework的配置信息*/const struct devfreq_governor *governor;
    /*devfreq的governor的名字*/char governor_name[DEVFREQ_NAME_LEN];
    struct notifier_block nb;
    /*负载监控使用的delayed_work*/struct delayed_work work;

    unsigned long previous_freq;
    struct devfreq_dev_status last_status;
    /*OPP device传递给governor的私有数据*/void *data; /* private data for governors */

    ......
};

这个数据结构是生成的,没有初始化值。

2.2 devfreq初始化

三个模块:framework、governor、device相关的初始化,其中device靠后。

09f6d944-6bf9-11ee-939d-92fbcf53809c.png0a096f78-6bf9-11ee-939d-92fbcf53809c.png

2.2.1 Devfreq framework初始化

在drivers/devfreq/devfreq.c中,devfreq_init()函数

static int __init devfreq_init(void)
{
        devfreq_class = class_create(THIS_MODULE, "devfreq"); //创建devfreq设备类
        if (IS_ERR(devfreq_class)) {
                pr_err("%s: couldn't create class
", __FILE__);
                return PTR_ERR(devfreq_class);
        }
        //创建工作队列,用于负载监控work调用运行
        devfreq_wq = create_freezable_workqueue("devfreq_wq");
        if (!devfreq_wq) {
                class_destroy(devfreq_class);
                pr_err("%s: couldn't create workqueue
", __FILE__);
                return -ENOMEM;
        }
        //加入到subsys_initcall,系统启动时初始化
        devfreq_class->dev_groups = devfreq_groups;

        return 0;
}
subsys_initcall(devfreq_init);

devfreq_groups就是上面说的sysfs用户接口

ATTRIBUTE_GROUPS(devfreq);
#define ATTRIBUTE_GROUPS(_name)                                        
static const struct attribute_group _name##_group = {                
        .attrs = _name##_attrs,                                        
};

2.2.2 governors 初始化

系统中可支持多个governors,在系统启动时进行初始化,并注册到devfreq framework中, 后续OPP device创建devfreq设备,会根据governor名字从已经初始化好的governor 列表中,查找对应的governor实例。

0a24b4b8-6bf9-11ee-939d-92fbcf53809c.png下面以simple_ondemand为例子,看下初始化过程:在drivers/devfreq/governor_simpleondemand.c中

//填充governor的结构体,不同的governor,会有不同的实现。
static struct devfreq_governor devfreq_simple_ondemand = {
        .name = "simple_ondemand",
        .get_target_freq = devfreq_simple_ondemand_func,
        .event_handler = devfreq_simple_ondemand_handler,
};

static int __init devfreq_simple_ondemand_init(void)
{
        return devfreq_add_governor(&devfreq_simple_ondemand);
}

//加入到subsys_initcall,系统启动时初始化。
subsys_initcall(devfreq_simple_ondemand_init);

初始化将governor加入到devfreq framework的governor列表中。

devfreq_add_governor->list_add(&governor->node, &devfreq_governor_list);

2.2.3 OPP device初始化

这里我们就以DDR为例子 drivers/devfreq/dmc.c中,系统根据DTS描述添加对应驱动程序

static const struct of_device_id xxxdmc_devfreq_of_match[] = {
        { .compatible = "xxx-dmc" },
        { },
};
MODULE_DEVICE_TABLE(of, xxxdmc_devfreq_of_match);
static struct platform_driver xxx_dmcfreq_driver = {
        .probe        = xxx_dmcfreq_probe,
        .driver = {
                .name        = "xxx-dmc-freq",
                .pm        = &xxx_dmcfreq_pm,
                .of_match_table = xxxdmc_devfreq_of_match,
        },
};
module_platform_driver(xxx_dmcfreq_driver);
xxx_dmcfreq_probe

匹配"xxx-dmc"会执行扫描函数xxx_dmcfreq_probe()

static int xxx_dmcfreq_probe(struct platform_device *pdev)
{
    //ctx是自定义的一个数据结构,用于存放各种DDR dvfs相关信息
    ctx = devm_kzalloc(dev, sizeof(struct xxx_dmcfreq), GFP_KERNEL);
    
    //找到clk信息
    struct device *dev = &pdev->dev;
    ctx->dmc_clk = devm_clk_get(dev, "dmc_clk");

    //负载计数启动
    ctx->edev = devfreq_event_get_edev_by_phandle(dev, 0);
    if (IS_ERR(ctx->edev))
            return -EPROBE_DEFER;
    ret = devfreq_event_enable_edev(ctx->edev);

    //给dev添加opp信息
    if (dev_pm_opp_of_add_table(dev)) {
            dev_err(dev, "Invalid operating-points in device tree.
");
            return -EINVAL;
    }

    ctx->rate = clk_get_rate(ctx->dmc_clk);

    opp = devfreq_recommended_opp(dev, &ctx->rate, 0);
    ctx->rate = dev_pm_opp_get_freq(opp);
    dev_pm_opp_put(opp);
    xxx_devfreq_dmc_profile.initial_freq = ctx->rate;

    ctx->devfreq = devm_devfreq_add_device(dev,
                                       &xxx_devfreq_dmc_profile,
                                       "simple_ondemand",
                                       &ctx->ondemand_data);

    //计算出最大最小值
    ctx->devfreq->min_freq = ULONG_MAX;
    ctx->devfreq->max_freq = 0;
    max_opps = dev_pm_opp_get_opp_count(dev);
    for (i = 0, rate = 0; i < max_opps; i++, rate++) {
            opp = dev_pm_opp_find_freq_ceil(dev, &rate);
            if (ctx->devfreq->min_freq > rate)
                    ctx->devfreq->min_freq = rate;
            if (ctx->devfreq->max_freq < rate)
                    ctx->devfreq->max_freq = rate;
    }

    devm_devfreq_register_opp_notifier(dev, ctx->devfreq);

    ctx->dev = dev;
    platform_set_drvdata(pdev, ctx);

    return 0;
}

pdev的名字是dmc0,对应dts中

    dmc_0: dmc0 {
                compatible = "xxx-dmc";
                devfreq-events = <&ddr_monitor0>;
                operating-points-v2 = <&dmc_opp_table>;
                clocks = <&dmc0_clk>;
                clock-names = "dmc_clk";
    };

其他信息都是在这里定义的。

struct xxx_dmcfreq {
        struct device *dev;
        struct devfreq *devfreq;
        struct devfreq_simple_ondemand_data ondemand_data;
        struct clk *dmc_clk;
        struct devfreq_event_dev *edev;
        struct mutex lock;

        unsigned long rate, target_rate;
};

devm_devfreq_add_device()函数会调用devfreq_add_device()进行注册devfreq

devfreq_add_device devfreq_add_device 创建devfreq设备的主要流程如下:

//devfreq device申请内存空间 初始化devfreq device结构体后,注册设备。
device_register(&devfreq->dev);

//根据传入的governor名字,从governor列表中,获取对应的governor实例。
governor = find_devfreq_governor(devfreq->governor_name);

//发送DEVFREQ_GOV_START到governor,开始管理OPP device的频率。
err = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_START, NULL);

##2.3 simple_ondemand调频

0a4155a0-6bf9-11ee-939d-92fbcf53809c.png
  • devfreq framework是大管家负责监控程序的运行,
  • governor提供管理算法,
  • OPP device提供自身的负载状态和频率设置的方法实现。
0a631a46-6bf9-11ee-939d-92fbcf53809c.png

exynos芯片,simple_ondemend策略调频调压流程图

2.3.1 governor启动监控

初始化的时候在上面2.2.3过程中,会调用devfreq_add_device()会给governor发DEVFREQ_GOV_START消息,simple_ondemand governor收到处理函数为:

static int devfreq_simple_ondemand_handler(struct devfreq *devfreq,
                                unsigned int event, void *data)
{
        switch (event) {
        case DEVFREQ_GOV_START:
                devfreq_monitor_start(devfreq);
                break;

devfreq_monitor_start()开始启动调度程序devfreq_monitor

void devfreq_monitor_start(struct devfreq *devfreq)
{
        INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor);
        if (devfreq->profile->polling_ms)
                queue_delayed_work(devfreq_wq, &devfreq->work,
                        msecs_to_jiffies(devfreq->profile->polling_ms));
}
EXPORT_SYMBOL(devfreq_monitor_start);

2.3.2 monitor轮询监控

devfreq_monitor每隔devfreq->profile->polling_ms时间,会调度监控程序工作。工作函数为update_devfreq()

int update_devfreq(struct devfreq *devfreq)
{
        //获取频率
        devfreq->governor->get_target_freq(devfreq, &freq);

        devfreq->profile->get_cur_freq(devfreq->dev.parent, &cur_freq);
      
        freqs.old = cur_freq;
        freqs.new = freq;
        devfreq_notify_transition(devfreq, &freqs, DEVFREQ_PRECHANGE);
        
        //设置频率
        devfreq->profile->target(devfreq->dev.parent, &freq, flags);

        freqs.new = freq;
        devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);
  }

这里获取频率和设置频率每次都执行,不比较频率是否相同,在设置处理的时候才比较。

2.3.3 governor计算频率

devfreq->governor->get_target_freq对应函数为:devfreq_simple_ondemand_func()

static int devfreq_simple_ondemand_func(struct devfreq *df,
                                        unsigned long *freq)
{
        //通过device回调函数,获取当前状态,然后计算新的频率
        err = devfreq_update_stats(df);
        
        //新频率的算法,根据阈值和当前负载计算
        a = stat->busy_time;
        a *= stat->current_frequency;
        b = div_u64(a, stat->total_time);
        b *= 100;
        b = div_u64(b, (dfso_upthreshold - dfso_downdifferential / 2));
        *freq = (unsigned long) b;
        if (df->min_freq && *freq < df->min_freq)
                *freq = df->min_freq;
        if (df->max_freq && *freq > df->max_freq)
                *freq = df->max_freq;
}

devfreq_update_stats会执行:df->profile->get_dev_status(df->dev.parent, &df->last_status); 见2.3.4分析

2.3.4 device获取和设置频率

static struct devfreq_dev_profile xxx_devfreq_dmc_profile = {
        .polling_ms        = 200,
        .target                = xxx_dmcfreq_target,
        .get_dev_status        = xxx_dmcfreq_get_dev_status,
        .get_cur_freq        = xxx_dmcfreq_get_cur_freq,
};

xxx_dmcfreq_get_dev_status()获取当前device负载信息,根据算法,返回调整频率。

        ret = devfreq_event_get_event(dmcfreq->edev, &edata);
        if (ret < 0)
                return ret;

        stat->current_frequency = dmcfreq->rate;
        stat->busy_time = edata.load_count;
        stat->total_time = edata.total_count;

获取运行状态信息,供monitor中devfreq_update_stats()函数使用

update_devfreq中最后会设置频率xxx_dmcfreq_target() xxx_dmcfreq_target()->clk_set_rate()->dmc_set_rate()->SMC指令 xxx_ddr在dtsi中定义

                xxx_ddr: xxx_ddr {
                        compatible = "xxx-ddr";
                        method = "smc";
                        fid = <0x82000008>;
                        test_cmd = <0x00000000>;
                        get_channels_cmd = <0x00000001>;
                        set_cmd = <0x00000010>;
                        get_cmd = <0x00000011>;
                };

执行这个smc指令后返回值为2,是channel的最大值,用于校验。

注册完了之后,clk会获取rate调用dmc_recalc_rate()函数,发送smc命令0x82000008 0x00000011 0 获取了rate值为4266000 这里利用ATF把这个寄存器设置给封装了。

3. ATF相关软件标准流程

为什么操作的动作要放在ATF里面?

  • 为了安全,进入安全世界才能操作,普通应用app进不去
  • 为了进入AON(Always ON)一直运行的非DDR区域运行,例如SRAM

0x82000008 SMC可以查询ARM的SMC手册

0a6835da-6bf9-11ee-939d-92fbcf53809c.png

可以参考atf中rk的实现,ddr_get_rate()函数 在plat/rockchip/common/rockchip_sip_svc.c中

/* Define a runtime service descriptor for fast SMC calls */
DECLARE_RT_SVC(
rockchip_sip_svc,
OEN_SIP_START,
OEN_SIP_END,
SMC_TYPE_FAST,
NULL,
sip_smc_handler
);

sip_smc_handler--》rockchip_plat_sip_handler--》ddr_smc_handler

uint32_t ddr_smc_handler(uint64_t arg0, uint64_t arg1,
 uint64_t id, uint64_t arg2)
{
switch (id) {
case DRAM_SET_RATE:
return ddr_set_rate((uint32_t)arg0);
case DRAM_ROUND_RATE:
return ddr_round_rate((uint32_t)arg0);
case DRAM_GET_RATE:
return ddr_get_rate();
case DRAM_SET_ODT_PD:
dram_set_odt_pd(arg0, arg1, arg2);
break;
default:
break;
}

return 0;
}

这里对于DDR的调频代码需要放到AON区域,系统中除了DDR还有SRAM,DDR调频的代码不能放到DDR里面,或者使用硬件DMC实现。

DMC调频 是用软件来升频或者降频,软件是运行在SOC的system controller上的,常常是Cortex-M CPU,调频的时候DMC不会阻止CPU transfers,DMC自己有buffer,可以继续接收,只是不会发给DDR,这些对CPU是透明的,但如果buffer满了的话,CPU自然就发不了了,调频之后可能需要ddr calibration,我们也都是通过DMC驱动程序来完成的,只是在做这些操作的时候并不会让系统停下来。

后记

学习ARMV8,RK也就是rockchip是不错的板子选择,还记得以前买过萤火虫的rk板卡,所有软硬件资料都很全,还挺不错的。这里的电源管理也算是驱动,学习驱动还是能有个板子调下,主要区分是32位还是64位,目前的大型SoC基本都是ARMv8的64位,甚至ARMv9了。


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 电源管理
    +关注

    关注

    115

    文章

    6180

    浏览量

    144457
  • sram
    +关注

    关注

    6

    文章

    767

    浏览量

    114678
  • DDR
    DDR
    +关注

    关注

    11

    文章

    712

    浏览量

    65318

原文标题:电源管理入门-7 DevFreq

文章出处:【微信号:OS与AUTOSAR研究,微信公众号:OS与AUTOSAR研究】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    电源管理入门-关机重启基础知识详解

    当我们接触电源管理的时候,最简单的流程就是关机重启,但是仔细分析其涉及的所有源代码就会发现,关机重启虽然简单
    发表于 09-19 11:41 2623次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>-关机重启基础知识详解

    电源管理入门-什么是OPP?怎么用?

    在SoC内,某些domain可以运行在较低的频率和电压下,而其他domain可以运行在较高的频率和电压下,某个domain所支持的对的集合被称为Operating Performance Point,缩写OPP。
    的头像 发表于 11-16 16:49 2000次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>-什么是OPP?怎么用?

    电源管理入门-Regulator驱动是什么?Regulator的作用是什么?

    Regulator是Linux系统中电源管理的基础设施之一,用于稳压电源管理,是各种驱动子系统中设置 电压的标准接口。
    的头像 发表于 11-16 16:51 1w次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>-Regulator驱动是什么?Regulator的作用是什么?

    电源管理入门:Thermal热管理

    管理指的是在电子设备或系统中通过各种方式控制其温度来保证其正常工作或延长寿命的过程。其中包括散热设计、温度监测、温度控制等方面。热管理的重要性越来越凸显,尤其在高性能计算、人工智能等领域的应用中更为重要。
    的头像 发表于 11-29 10:09 4855次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>:Thermal热<b class='flag-5'>管理</b>

    电源管理入门:驱动Runtime PM管理

    Runtime PM管理也就是设备驱动里面的电源管理,即设备驱动结构体里面的struct dev_pm_ops,只控制设备自己的电源。这样可以在设备不需要工作的时候可以进入到低功耗状态
    的头像 发表于 11-29 10:13 3029次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>:驱动Runtime PM<b class='flag-5'>管理</b>

    电源管理入门:Power supply子系统

    对于便携设备来说,电源管理更加的重要,因为电池电量有限,容易电量焦虑。除了省电管理外,还需要对电池进行监控管理和充放电管理,这样保护好电池和
    的头像 发表于 11-29 10:15 4182次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>:Power supply子系统

    电源管理入门:Power Domain管理

    SoC中通常有很多IP,按逻辑可以把几个相关功能的IP划为一个电源域。一个电源域内的IP,通常按相同的方式由同一个硬件模块PMIC供电,电压一样并且电源管理例如休眠唤醒一致。
    的头像 发表于 11-29 10:16 3397次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>:Power Domain<b class='flag-5'>管理</b>

    电源管理入门-芯片设计中的电源管理介绍

    SCP直接控制SoC的电源和时钟,而AP通过硬件和软件接口协同管理
    的头像 发表于 12-06 09:16 3271次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>-芯片设计中的<b class='flag-5'>电源</b><b class='flag-5'>管理</b>介绍

    电源管理入门:Hypervisor中的电源管理

    很多时候听说Hypervisor,但是对底层软件技术不了解的人感觉挺神秘。本篇文章简单介绍下Hypervisor的基本概念,另外介绍下电源管理在Hypervisor之上多OS间怎么应用。
    的头像 发表于 12-06 09:27 1452次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>:Hypervisor中的<b class='flag-5'>电源</b><b class='flag-5'>管理</b>

    NI视觉助手入门教程完全版

    本帖最后由 Z52352389 于 2016-3-7 22:44 编辑 NI视觉助手入门教程完全版,图像处理入门
    发表于 12-20 22:58

    防火墙原理入门

    防火墙原理入门 防火墙能增强机构内部网络的安全性。防火墙系统决定了哪些内部服务可以被外界访问;外界的哪些人可以访问内部的服务以及哪
    发表于 08-01 10:21 1022次阅读
    防火墙原<b class='flag-5'>理入门</b>

    数字信号处理入门指南

    数字信号处理入门指南什么是DSP? 数字信号处理器(DSP)采集已被数字化的现实世界的声音、音频、视频、温度、压力或位置等信号,并从数学的角度对其进
    发表于 09-15 08:55 1345次阅读
    数字信号处<b class='flag-5'>理入门</b>指南

    单片机原理及应用ppt入门课程

    微机原理入门课程ppt,比较简单,适合新手。。
    发表于 01-12 17:52 0次下载

    电源管理入门之CPU热插拔详解

    之前介绍了电源的开机和关机重启,本小节开始介绍省电的技术,其中最暴力的省电方法就是直接拔核hotplug处理,就像需要10个人干活都要吃饭,但是现在活少了最节省的方法就是砍掉几个人,有点像裁员啊。
    的头像 发表于 10-16 15:28 5290次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>之CPU热插拔详解

    电源管理入门-6 CPUFreq

    仅仅降低时钟频率并不节约能量,因为时钟频率的降低会带来任务执行时间的增加。调节电压需要以相同的比例调节频率以满足信号传播延迟要求。然而不管是电压调节还是频率调节,都会造成系统性能的损失,并增加系统的响应延迟。
    的头像 发表于 10-16 17:07 2505次阅读
    <b class='flag-5'>电源</b><b class='flag-5'>管理入门</b>-6 CPUFreq