《Linux设备驱动开发详解:基于最新的Linux 4.0内核》19. Linux电源管理系统架构和驱动
- 格式:pdf
- 大小:1.22 MB
- 文档页数:35
Linux操作系统的内核设计分析Linux操作系统作为开源操作系统的代表,已经在各个领域得到了广泛应用。
而Linux操作系统的内核则是这个系统之所以能够运转的关键所在。
本文将就Linux操作系统的内核设计进行分析,并探讨其优劣之处。
一、Linux内核设计的基础Linux内核的设计基础主要包括以下几个方面:1. 开放源码Linux内核采用的是GPL协议,这意味着它是一个开放源码的项目。
这为世界各地的开发人员提供了极大的便利,方便他们进行开发和修改。
同时,这也确保了Linux内核的透明度,并且鼓励开发者贡献代码的同时,深度参与到Linux开源社区的构建和升级中。
2. 模块化Linux内核的构造采用的是模块化设计。
这种设计方式将内核代码分成独立的模块,每个模块都可以独立编译、加载和卸载。
采用模块化的设计,能够使得开发人员能够更加细致地打包、编译、并部署只包含他们需要的模块的系统。
3. 多任务Linux内核是一个基于多任务设计的系统。
这意味着它能够使得多个程序同时运行,并能够平滑高效地进行任务的切换。
这给开发人员提供了各种各样的自由,使得他们能够更加高效地进行开发。
4. 支持众多处理器架构Linux内核的支持范围非常广泛,它可以适配众多处理器架构。
这意味着一个制造商可以使用不同的处理器架构去生产设备,并且这些设备都能够安装和运行Linux操作系统。
5. 外层调用接口Linux内核支持开放式的外层调用接口。
这使得用户层可以很容易地调用Linux 内核执行某个任务。
这些用户层应用包括网上购物网站、应用程序和各种驱动程序。
6. 子系统Linux内核的子系统主要包括进程管理、内存管理、I/O管理和网络管理等。
二、Linux内核的优点Linux内核具有以下主要优点:1. 开源性Linux内核本身是一个开源的、由社区驱动的项目。
这意味着在它的附加组件和周边产品中,广大的开发者社区都可以为用户提供帮助和支持。
2. 安全性相比其他闭源操作系统,Linux内核在安全性方面更具优势。
标签:无标签如何编写Linux设备驱动程序Linux是Unix操作系统的一种变种,在Linux下编写驱动程序的原理和思想完全类似于其他的Unix系统,但它dos或window环境下的驱动程序有很大的区别。
在Linux环境下设计驱动程序,思想简洁,操作方便,功能也很强大,但是支持函数少,只能依赖kernel中的函数,有些常用的操作要自己来编写,而且调试也不方便。
以下的一些文字主要来源于khg,johnsonm的Write linux device driver,Brennan's Guide to Inline Assembly,The Linux A-Z,还有清华BBS上的有关device driver 的一些资料。
一、Linux device driver 的概念系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。
设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。
设备驱动程序是内核的一部分,它完成以下的功能: 1。
对设备初始化和释放。
2。
把数据从内核传送到硬件和从硬件读取数据。
3。
读取应用程序传送给设备文件的数据和回送应用程序请求的数据。
4。
检测和处理设备出现的错误。
在Linux操作系统下有三类主要的设备文件类型,一是字符设备,二是块设备,三是网络设备。
字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际的I/O操作。
块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待。
已经提到,用户进程是通过设备文件来与实际的硬件打交道。
每个设备文件都都有其文件属性(c/b),表示是字符设备还是块设备?另外每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分他们。
linux驱动开发知识点总结Linux驱动开发是指在Linux操作系统下开发和编写设备驱动程序的过程。
Linux作为一种开源操作系统,具有广泛的应用领域,因此对于驱动开发的需求也非常重要。
本文将从驱动程序的概念、驱动开发的基本步骤、常用的驱动类型以及驱动开发的注意事项等方面进行总结。
一、驱动程序的概念驱动程序是指控制计算机硬件和软件之间通信和交互的程序。
在Linux系统中,驱动程序负责与硬件设备进行交互,实现对硬件的控制和管理。
二、驱动开发的基本步骤1. 确定驱动的类型:驱动程序可以分为字符设备驱动、块设备驱动和网络设备驱动等。
根据具体的硬件设备类型和需求,选择合适的驱动类型。
2. 编写设备注册函数:设备注册函数用于向系统注册设备,使系统能够识别和管理该设备。
3. 实现设备的打开、关闭和读写操作:根据设备的具体功能和使用方式,编写设备的打开、关闭和读写操作函数。
4. 实现设备的中断处理:如果设备需要进行中断处理,可以编写中断处理函数来处理设备的中断请求。
5. 编写设备的控制函数:根据设备的需求,编写相应的控制函数来实现对设备的控制和配置。
6. 编译和安装驱动程序:将编写好的驱动程序进行编译,并将生成的驱动模块安装到系统中。
三、常用的驱动类型1. 字符设备驱动:用于控制字符设备,如串口、打印机等。
字符设备驱动以字符流的方式进行数据传输。
2. 块设备驱动:用于控制块设备,如硬盘、U盘等。
块设备驱动以块为单位进行数据传输。
3. 网络设备驱动:用于控制网络设备,如网卡。
网络设备驱动实现了数据包的收发和网络协议的处理。
4. 触摸屏驱动:用于控制触摸屏设备,实现触摸操作的识别和处理。
5. 显示驱动:用于控制显示设备,实现图像的显示和刷新。
四、驱动开发的注意事项1. 熟悉硬件设备的规格和寄存器的使用方法,了解硬件设备的工作原理。
2. 确保驱动程序的稳定性和可靠性,避免出现系统崩溃或死机等问题。
3. 对于需要频繁访问的设备,要考虑性能问题,尽量减少对硬件的访问次数。
一、设备驱动程序概述自Linux在中国发展以来,得到了许多公司的青睐。
在国内的玩家也越来越多了,但目前还是停留在玩的水平上,很少有玩家对Linux的系统进行研究。
因为它的开放,我们可以随时拿来“把玩”。
这也是Linux一个无可比拟的优势,这样我们可以修改后再加入到里面。
但很少有专门的书籍讲到Linux驱动程序的开发,像上海这样的大城市也很少有讲Linux驱动开发的资料,唉,谁让这个是人家的东西呢,我们还是得跟着人家跑。
我现在讲的这些驱动开发的细节,并不特定哪个版本的内核,这只是大体的思路与步骤。
因为大家都知道Linux 2.6.x 与Linux 2.4.x是有不少改动的。
所以,具体的大家可以去参考Linux Device Driver 2.4 和Linux Device Driver 2.6这几本书。
这是我们学习开发驱动必不可少的东西。
好了,下面就开始学习吧。
根据设备的行为,我们可以把设备分为字符设备和块设备,还有网络设备。
字符设备是以字节为单位进行顺序读写,数据缓冲系统对它们的访问不提供缓存。
而块设备则是允许随机访问与读写,每次读写的数据量都是数据块长度的整数倍,并且访问还会经过缓冲区缓存系统才能实现。
与Unix版本不同的是:Linux的内核允许不是数据块长度整数倍的数据量被读取,用官方的语言就是:但这种不同只是纯粹学术方面的东西。
大多数设备驱动程序都要通过文件系统来进行访问的,但网络设备是不同的。
/dev子目录里都是关于设备的特殊文件,但看起来它们与普通的目录没有什么两样。
如下:$ ls -l /dev...brw-rw--- 1 root disk 22, 1 May 5 1998 hdc1crw-rw--- 1 root daemon 6 0 May 5 1998 lp0与普通文件有所不同是开头的“C” 和“B”,即char 和block的意思,即字符设备和块设备。
再后面的“22,1” 和“6,0”即设备的主设备号和次设备号,主设备号表明它是哪一种设备,这与你在Windows里添加硬件时看到的那些是一个意思。
linux驱动开发通俗讲解Linux驱动开发是一门涉及操作系统和硬件交互的技术,它主要负责管理和控制硬件设备的操作。
比如,键盘、鼠标、打印机等设备,都需要相应的驱动程序来与操作系统进行通信。
在Linux系统中,驱动程序主要由内核提供,它们以模块的形式存在。
当我们插入一个新的设备时,操作系统会自动加载相应的驱动模块,并将其与设备进行绑定。
这样,设备就能被操作系统识别和使用了。
驱动开发涉及到硬件和软件两个方面。
首先,我们需要了解硬件设备的工作原理和通信协议。
有了这些基础知识,我们才能更好地理解设备的工作方式,并编写相应的驱动程序。
我们需要熟悉Linux内核的工作机制和API接口。
内核提供了一系列函数和数据结构,用于驱动程序与操作系统进行交互。
我们可以使用这些接口来访问设备的寄存器、发送控制命令、接收数据等。
在编写驱动程序时,我们需要按照一定的规范和流程进行。
首先,我们需要注册设备驱动程序,告诉操作系统我们要控制哪个设备。
然后,我们需要实现一系列的回调函数,用于处理设备的各种事件和操作。
这些回调函数会在相应的时机被内核调用。
在编写驱动程序时,我们还需要考虑设备的并发访问和错误处理。
由于设备可能同时被多个进程或线程访问,我们需要使用互斥锁等机制来保护共享资源,避免冲突和竞争条件的发生。
同时,我们还需要处理各种可能发生的错误和异常情况,保证系统的稳定性和可靠性。
驱动开发是一项需要耐心和细心的工作。
在编写驱动程序时,我们需要仔细阅读设备的文档和规格说明,了解其特性和限制。
我们还需要进行大量的测试和调试工作,确保驱动程序的正确性和稳定性。
总的来说,Linux驱动开发是一项非常重要的技术,它为我们提供了与硬件设备交互的能力。
通过编写驱动程序,我们可以更好地利用设备的功能,提升系统的性能和稳定性。
希望通过本文的介绍,读者能够对Linux驱动开发有一个初步的了解,并对其重要性有所认识。
Linux系统设备驱动程序概述1.1 Linux设备驱动程序分类Linux设备驱动程序在Linux的内核源代码中占有很大的比例,源代码的长度日益增加,主要是驱动程序的增加。
在Linux内核的不断升级过程中,驱动程序的结构还是相对稳定。
在2.0.xx到2.2.xx的变动里,驱动程序的编写做了一些改变,但是从2.0.xx的驱动到2.2.xx的移植只需做少量的工作。
Linux系统的设备分为字符设备(char device),块设备(block device)和网络设备(network device)三种。
字符设备是指存取时没有缓存的设备。
块设备的读写都有缓存来支持,并且块设备必须能够随机存取(random access),字符设备则没有这个要求。
典型的字符设备包括鼠标,键盘,串行口等。
块设备主要包括硬盘软盘设备,CD-ROM等。
一个文件系统要安装进入操作系统必须在块设备上。
网络设备在Linux里做专门的处理。
Linux的网络系统主要是基于BSD unix的socket机制。
在系统和驱动程序之间定义有专门的数据结构(sk_buff)进行数据的传递。
系统里支持对发送数据和接收数据的缓存,提供流量控制机制,提供对多协议的支持。
1.2编写驱动程序的一些基本概念无论是什么操作系统的驱动程序,都有一些通用的概念。
操作系统提供给驱动程序的支持也大致相同。
下面简单介绍一下网络设备驱动程序的一些基本要求。
1.2.1发送和接收这是一个网络设备最基本的功能。
一块网卡所做的无非就是收发工作。
所以驱动程序里要告诉系统你的发送函数在哪里,系统在有数据要发送时就会调用你的发送程序。
还有驱动程序由于是直接操纵硬件的,所以网络硬件有数据收到最先能得到这个数据的也就是驱动程序,它负责把这些原始数据进行必要的处理然后送给系统。
这里,操作系统必须要提供两个机制,一个是找到驱动程序的发送函数,一个是驱动程序把收到的数据送给系统。
1.2.2中断中断在现代计算机结构中有重要的地位。
Linux底层驱动开发入门指南手把手教你如何入门Linux底层驱动开发入门指南Linux底层驱动开发是一个重要而有挑战性的领域。
本文将为你提供一份手把手的入门指南,帮助你了解和掌握Linux底层驱动开发的基本知识和技巧。
一、概述Linux是一个开源的操作系统内核,底层驱动是其核心组成部分之一。
底层驱动的作用是将硬件设备与操作系统进行有效的交互。
对于想要深入了解Linux内核并进行驱动开发的人来说,掌握底层驱动开发是必不可少的。
二、准备工作在开始底层驱动开发之前,你需要完成以下准备工作:1. 安装Linux操作系统:选择适合你的计算机架构的Linux发行版,并完成安装。
2. 学习C语言编程:底层驱动通常使用C语言进行开发,因此你需要掌握C语言的基本语法。
3. 熟悉Linux内核:深入了解Linux内核的运行机制和结构,包括进程管理、内存管理等方面的知识。
三、驱动模型Linux内核采用了一种统一的驱动模型,称为设备驱动模型(Device Driver Model)。
这种模型将所有设备抽象为“设备”,并通过设备树(Device Tree)进行管理和描述。
四、编写第一个驱动程序以下是一个简单的示例,帮助你入门Linux底层驱动开发:```c#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>static int __init hello_init(void) {printk(KERN_INFO "Hello, Linux driver!\n");return 0;}static void __exit hello_exit(void) {printk(KERN_INFO "Goodbye, Linux driver!\n");}module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Your Name");MODULE_DESCRIPTION("A simple Linux driver");```五、注册和注销驱动在上面的示例中,通过module_init()和module_exit()函数分别指定了驱动的初始化和退出函数。
LINUX设备驱动开发详解概述LINUX设备驱动开发是一项非常重要的任务,它使得硬件设备能够与操作系统进行有效地交互。
本文将详细介绍LINUX设备驱动开发的基本概念、流程和常用工具,帮助读者了解设备驱动开发的要点和技巧。
设备驱动的基本概念设备驱动是连接硬件设备和操作系统的桥梁,它负责处理硬件设备的输入和输出,并提供相应的接口供操作系统调用。
设备驱动一般由设备驱动程序和设备配置信息组成。
设备驱动程序是编写解决设备驱动的代码,它负责完成设备初始化、IO操作、中断处理、设备状态管理等任务。
设备驱动程序一般由C语言编写,使用Linux内核提供的API函数进行开发。
设备配置信息是定义硬件设备的相关参数和寄存器配置的文件,它告诉操作系统如何与硬件设备进行交互。
设备配置信息一般以设备树或者直接编码在设备驱动程序中。
设备驱动的开发流程设备驱动的开发流程包括设备初始化、设备注册、设备操作函数编写和设备驱动注册等几个主要步骤。
下面将详细介绍这些步骤。
设备初始化设备初始化是设备驱动开发的第一步,它包括硬件初始化和内存分配两个主要任务。
硬件初始化是对硬件设备进行基本的初始化工作,包括寄存器配置、中断初始化等。
通过操作设备的寄存器,将设备设置为所需的状态。
内存分配是为设备驱动程序分配内存空间以便于执行。
在设备初始化阶段,通常需要为设备驱动程序分配一块连续的物理内存空间。
设备注册设备注册是将设备驱动程序与设备对象进行关联的过程,它使得操作系统能够正确地管理设备。
设备注册包括设备号分配、设备文件创建等操作。
设备号是设备在系统中的唯一标识符,通过设备号可以找到设备对象对应的设备驱动程序。
设备号分配通常由操作系统负责,设备驱动程序通过注册函数来获取设备号。
设备文件是用户通过应用程序访问设备的接口,它是操作系统中的一个特殊文件。
设备文件的创建需要通过设备号和驱动程序的注册函数来完成。
设备操作函数编写设备操作函数是设备驱动程序的核心部分,它包括设备打开、设备关闭、读和写等操作。
Linux开发入门必读书单推荐给每个新手的经典书籍Linux是一种操作系统,被广泛用于服务器和嵌入式设备中。
对于想要从事Linux开发的新手们来说,选择一本合适的书籍是非常重要的。
本文将为大家推荐几本经典的Linux开发入门书籍,帮助新手们快速了解并掌握Linux开发技能。
1. 《鸟哥的Linux私房菜》-作者:鸟哥这本书被誉为Linux界的经典之作,是Linux爱好者的必读书籍。
作者通过通俗易懂的语言,深入浅出地介绍了Linux的基本概念、常用命令以及系统管理等内容。
适合初学者入门学习,帮助他们构建Linux的基础知识框架。
2. 《Linux Shell脚本攻略》-作者:志刚、殷蓝天Shell脚本是Linux开发中非常重要的一环,可以自动化完成一些重复性的工作。
这本书从简单入门到深入应用,详细介绍了Shell脚本的基本语法、文件处理、正则表达式等内容,同时还提供了大量实例供读者练习和参考。
3. 《深入理解Linux内核》-作者:谢希仁对于想要从事Linux内核开发的初学者来说,这本书是一本非常重要的参考资料。
作者以清晰的语言和丰富的实例,剖析了Linux内核的各个组成部分,包括进程管理、内存管理、文件系统等。
读者通过学习这本书可以深入理解Linux内核的工作原理,为进一步深入研究打下基础。
4. 《Linux设备驱动开发详解:基于最新的Linux 4.0内核》-作者:周立功这本书适合想要从事Linux设备驱动开发的新手们阅读。
作者通过详细的讲解和实例演示,帮助读者了解Linux设备驱动的基本原理、开发流程和调试技巧。
对于想要深入研究Linux设备驱动的读者来说,这本书是一本难得的宝藏。
5. 《Linux网络编程》-作者:Richard Stevens, Bill Fenner, Andrew M. Rudoff对于想要从事网络编程的开发人员来说,这本书是必读的经典之作。
作者通过深入浅出的方式,介绍了Linux系统的网络编程接口、套接字编程、多线程编程等内容。
以下电子书来源于宋宝华《Linux设备驱动开发详解:基于最新的Linux 4.0内核》第19章《Linux电源管理系统架构和驱动》本章导读Linux在消费电子领域的应用已经铺天盖地,而对于消费电子产品而言,省电是一个重要的议题。
本章将介绍Linux设备树(Device Tree)的起源、结构和因为设备树而引起的驱动和BSP 变更。
19.1节阐述了Linux电源管理的总体架构。
19.2~19.8节分别论述了CPUFreq、CPUIdle、CPU热插拔以及底层的基础设施Regulator、OPP以及电源管理的调试工具PowerTop。
19.9节讲解了系统Suspend to RAM的过程以及设备驱动如何提供对Suspend to RAM的支持。
19.10节讲解了设备驱动的Runtime suspend。
本章是相对《Linux设备驱动开发详解(第2版)》全新的一章内容,也是Linux设备驱动工程师必备的知识体系。
第十九章Linux电源管理系统架构和驱动1.Linux电源管理全局架构Linux电源管理非常复杂,牵扯到系统级的待机、频率电压变换、系统空闲时的处理以及每个设备驱动对于系统待机的支持和每个设备的运行时电源管理,可以说和系统中的每个设备驱动都息息相关。
对于消费电子产品来说,电源管理相当重要。
因此,这部分工作往往在开发周期中占据相当大的比重,图19.1呈现了Linux内核电源管理的整体架构。
大体可以归纳为如下几类:1.CPU在运行时根据系统负载进行动态电压和频率变换的CPUFreq2.CPU在系统空闲时根据空闲的情况进行低功耗模式的CPUIdle3.多核系统下CPU的热插拔支持4.系统和设备对于延迟的特别需求而提出申请的PM QoS,它会作用于CPUIdle的具体策略5.设备驱动针对系统Suspend to RAM/Disk的一系列入口函数6.SoC进入suspend状态、SDRAM自刷新的入口7.设备的runtime(运行时)动态电源管理,根据使用情况动态开关设备8.底层的时钟、稳压器、频率/电压表(OPP模块完成)支撑,各驱动子系统都可能用到图19.1 Linux电源管理系统架构2.CPUFreq驱动CPUFreq子系统位于drivers/cpufreq目录,负责进行运行过程中CPU频率和电压的动态调整,即DVFS(Dynamic Voltage Frequency Scaling,动态电压频率调整)。
运行时进行CPU 电压和频率调整的原因是:CMOS电路中的功耗与电压的平方成正比、与频率成正比(),因此降低电压和频率可降低功耗。
CPUFreq的核心层位于drivers/cpufreq/cpufreq.c,它为各个SoC的CPUFreq驱动的实现提供了一套统一的接口,并实现了一套notifier的机制,可以在CPUFreq的policy和频率改变的时候向其他模块发出通知。
另外,在CPU运行频率发生变化的时候,内核的loops_per_jiffy常数也会发生相应变化。
1.1 SoC的CPUFreq驱动实现具体的每个SoC的CPUFreq驱动实例只需要实现电压、频率表,以及从硬件层面完成这些变化。
CPUFreq核心层提供了如下API供SoC注册自身的CPUFreq驱动:int cpufreq_register_driver(struct cpufreq_driver *driver_data);其参数为一个cpufreq_driver结构体指针,实际上,cpufreq_driver封装了一个具体的SoC 的CPUFreq驱动的主体,该结构体形如代码清单19.1。
代码清单19.1 cpufreq_driver结构体1 struct cpufreq_driver {2 struct module *owner;3 char name[CPUFREQ_NAME_LEN];4 u8 flags;56 /* needed by all drivers */7 int (*init) (struct cpufreq_policy *policy);8 int (*verify) (struct cpufreq_policy *policy);910 /* define one out of two */11 int (*setpolicy) (struct cpufreq_policy *policy);12 int (*target) (struct cpufreq_policy *policy,13 unsigned inttarget_freq,14 unsigned int relation);1516 /* should be defined, if possible */17 unsigned int (*get) (unsigned intcpu);1819 /* optional */20 unsigned int (*getavg) (struct cpufreq_policy *policy,21 unsigned intcpu);22 int (*bios_limit) (intcpu, unsigned int *limit);2324 int (*exit) (struct cpufreq_policy *policy);25 int (*suspend) (struct cpufreq_policy *policy);26 int (*resume) (struct cpufreq_policy *policy);27 structfreq_attr **attr;28 };其中的owner成员一般被设置为THIS_MODULE;name成员是CPUFreq驱动名字,如drivers/cpufreq/s5pv210-cpufreq.c设置name为"s5pv210",如drivers/cpufreq/omap-cpufreq.c 设置name为"omap";flags是一些暗示性的标志,譬如,若设置了CPUFREQ_CONST_LOOPS,则是告诉内核loops_per_jiffy不会因为CPU频率的变化而变化。
init()成员是一个per-CPU初始化函数指针,每当一个新的CPU被注册进系统的时候,该函数就被调用,该函数接受一个cpufreq_policy的指针参数,在init()成员函数中,可进行如下设置:policy->cpuinfo.min_freqpolicy->cpuinfo.max_freq该CPU支持的最小频率和最大频率(单位是kHz)。
policy->cpuinfo.transition_latencyCPU进行频率切换所需要的延迟(单位是纳秒)policy->curCPU当前频率policy->policypolicy->governorpolicy->minpolicy->max定义该CPU的缺省policy,以及缺省policy情况下该policy支持的最小、最大CPU频率。
verify()成员函数用于对用户的CPUFreq policy设置进行有效性验证和数据修正。
每次用户设定一个新policy时,该函数根据老的policy和新的policy,检验新policy设置的有效性并对无效设置进行必要的修正。
在该成员函数的具体实现中,常用到如下辅助函数:cpufreq_verify_within_limits(struct cpufreq_policy *policy, unsigned intmin_freq, unsigned intmax_freq);setpolicy()成员函数接受一个policy参数(包含policy->policy, policy->min和policy->max 等成员),实现了这个成员函数的CPU一般具备在一个范围(limit, 从policy->min到policy->max)里面自动调整频率的能力。
目前少数驱动如intel_pstate.c和longrun.c包含这样的成员函数。
而绝大多数CPU都不会实现此函数,一般实现target()成员函数,target()的参数直接就是一个指定的频率。
target()成员函数用于将频率调整到一个指定的值,接受3个参数:policy、target_freq 和relation。
target_freq是目标频率,实际驱动总是要设定真实的CPU频率到最接近于target_freq,并且设定的频率必须位于policy->min到policy->max之间。
在设定频率接近target_freq的情况下,relation若为CPUFREQ_REL_L,暗示设置的频率应该大于或等于target_freq;relation若为CPUFREQ_REL_H,暗示设置的频率应该小于或等于target_freq。
下表描述了setpolicy()和target()所针对的CPU以及调用方式上的区别:由于芯片内部PLL和分频器的关系,ARM SoC一般不具备独立调整频率的能力,往往SoC 的CPUFreq驱动会提供一个频率表,在该表的范围内进行变更,所以一般实现target()成员函数。
CPUFreq核心层提供了一组频率表相关的辅助API。
int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy,struct cpufreq_frequency_table *table);它是cpufreq_driver的init()成员函数的助手,用于将policy->min和policy->max设置为与cpuinfo.min_freq和cpuinfo.max_freq相同的值。
int cpufreq_frequency_table_verify(struct cpufreq_policy *policy,struct cpufreq_frequency_table *table);它是cpufreq_driver的verify()成员函数的助手,确保至少1个有效的CPU频率位于policy->min到policy->max范围内。
int cpufreq_frequency_table_target(struct cpufreq_policy *policy,struct cpufreq_frequency_table *table,unsigned int target_freq,unsigned int relation,unsigned int *index);它是cpufreq_driver的target()成员函数的助手,返回需要设定的频率在频率表中的索引。