linux opp怎么使用
Posted Zephyr
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux opp怎么使用相关的知识,希望对你有一定的参考价值。
简介Operating Performance Points (OPP)
SoC是高度集成的,不是SoC中的所有模块需要一直以最高的频率运作。来为了便于实现这一点,SoC中的子模块被分组到不同的域中,允许一些域运行在较低的电压和频率,而其他域运行在更高的电压/频率对。
由频率和电压对组成的离散元组的集合称为工作性能点(opp)。
例如:让我们考虑一个支持以下功能的MPU设备:
300MHz,最小电压1V,
800MHz,最小电压1.2V,
最低电压1.3V时1GHz,
我们可以用Hz, uV元组来表示这三个opp:
300000000, 1000000
800000000, 1200000
1000000000, 1300000
OPP API接口
OPP库提供了一组辅助函数来组织和查询OPP信息。库位于drivers/opp/
目录中,头文件位于include/linux/pm_opp.h
中。可以通过从电源管理菜单CONFIG菜单启用CONFIG_pm_opp来启用opp库。某些SoC,如Texas Instrument的OMAP框架,允许在不需要cpufreq的情况下选择性地在某个OPP启动。
OPP层期望每个域由一个唯一的设备指针来表示。SoC框架在OPP层为每个设备注册一组初始OPP。这个列表的长度一般比较小,通常每个设备大约5个。这个初始列表包含一组 OPP,框架希望系统默认情况下能够安全地启用这些 OPP。
通常使用opp的方式有以下几步:
a. 用户为设备(比如CPU)配置/注册一些默认的opp信息。
b. Soc会根据具体的运行情况,通过opp层去改变/查询设备的opp信息。
(users) -> registers a set of default OPPs -> (library)
SoC framework -> modifies on required cases certain OPPs -> OPP layer ->queries to search/retrieve information
使用OPP的场景
随着系统继续运行,SoC框架可能会根据各种外部因素选择在每个设备上提供某些 OPP 或不提供 OPP。
示例用法:热管理或其他特殊情况,SoC框架可能选择禁用更高频率的OPP以安全地继续操作,直到该OPP可以在可能的情况下重新启用。
警告
:如果设备调用了dev_pm_opp_enable/deisable
函数,则OPP库的用户应使用get_opp_count
刷新其可用性计数,在进行这些操作的情况下,需要注意刷新cpufreq表。
如何使用OPP
OPP列表初始化
迭代调用dev_ pm_opp_ dd
函数为每个设备添加 OPP列表。每个设备的opp个数最好小于5个。
OPP是用频率和电压定义的。一旦完成添加,OPP被认为是可用的,可以用dev_pm_opp_enable/disable函数来控制其可用性。OPP库内部用dev_pm_opp
结构体存储并管理这些信息。
注意:不要在中断上下文中使用此函数。
例如,多次调用dev_pm_opp_add为mpu_dev添加多个opp。
soc_pm_init()
/* Do things */
r = dev_pm_opp_add(mpu_dev, 1000000, 900000);
if (!r)
pr_err("%s: unable to register mpu opp(%d)\\n", r);
goto no_cpufreq;
/* Do cpufreq things */
no_cpufreq:
/* Do remaining things */
OPP查询获取函数
cpufreq等高层框架对频率进行操作,为了将频率映射到相应的OPP,OPP库提供了便利的函数来搜索OPP库内部管理的OPP链表。这些搜索函数如果找到匹配的OPP,将返回指向该OPP的指针,否则返回错误。这些错误预计由标准的错误检查,如IS_ERR()来处理,并由调用者采取适当的行动。
这些函数的调用者应在使用完OPP后调用dev_pm_opp_put()。否则,OPP的内存将永远不会被释放,并导致内存泄露。
函数 | 作用 |
---|---|
dev_pm_opp_find_freq_ceil, dev_pm_opp_find_freq_floor | 查找某个频率附近的最高频率,或者最低频率 |
dev_pm_opp_find_freq_exact | 此功能对于启用默认情况下不可用的OPP特别有用 |
cpufreq_driver->target的简化实现:
soc_cpufreq_target(..)
/* Do stuff like policy checks etc. */
/* Find the best frequency match for the req */
opp = dev_pm_opp_find_freq_ceil(dev, &freq);
dev_pm_opp_put(opp);
if (!IS_ERR(opp))
soc_switch_to_freq_voltage(freq);
else
/* do something when we can\'t satisfy the req */
/* do other stuff */
OPP可用性控制功能
dev_pm_opp_enable
:使OPP可用。示例:假设只有当SoC温度低于某个阈值时,1GHz OPP才可用
if (cur_temp < temp_low_thresh)
/* Enable 1GHz if it was disabled */
opp = dev_pm_opp_find_freq_exact(dev, 1000000000, false);
dev_pm_opp_put(opp);
/* just error check */
if (!IS_ERR(opp))
ret = dev_pm_opp_enable(dev, 1000000000);
else
goto try_something_else;
dev_pm_opp_disable
: OPP不可用于。示例: 如果温度超过阈值,则禁用1GHz OPP。
if (cur_temp > temp_high_thresh)
/* Disable 1GHz if it was enabled */
opp = dev_pm_opp_find_freq_exact(dev, 1000000000, true);
dev_pm_opp_put(opp);
/* just error check */
if (!IS_ERR(opp))
ret = dev_pm_opp_disable(dev, 1000000000);
else
goto try_something_else;
OPP数据检索功能
dev_pm_opp_get_voltage
:检索opp指针表示的电压。示例:在cpufreq转换到不同频率时,需要使用regulator框架将由OPP表示的电压来配置到pmic:
soc_switch_to_freq_voltage(freq)
/* do things */
opp = dev_pm_opp_find_freq_ceil(dev, &freq);
v = dev_pm_opp_get_voltage(opp);
dev_pm_opp_put(opp);
if (v)
regulator_set_voltage(.., v);
/* do other things */
dev_pm_opp_get_freq
:检索opp指针表示的频率。例如:假设SoC框架使用了几个辅助函数,我们可以传递opp指针,而不是做额外的参数来处理一些安静的数据参数:
soc_cpufreq_target(..)
/* do things.. */
max_freq = ULONG_MAX;
max_opp = dev_pm_opp_find_freq_floor(dev,&max_freq);
requested_opp = dev_pm_opp_find_freq_ceil(dev,&freq);
if (!IS_ERR(max_opp) && !IS_ERR(requested_opp))
r = soc_test_validity(max_opp, requested_opp);
dev_pm_opp_put(max_opp);
dev_pm_opp_put(requested_opp);
/* do other things */
soc_test_validity(..)
if(dev_pm_opp_get_voltage(max_opp) < dev_pm_opp_get_voltage(requested_opp))
return -EINVAL;
if(dev_pm_opp_get_freq(max_opp) < dev_pm_opp_get_freq(requested_opp))
return -EINVAL;
/* do things.. */
dev_pm_opp_get_opp_count
:检索设备的可用opp数量示例:假设SoC中的协同处理器需要知道表中的可用频率,主处理器可以通知如下:
soc_notify_coproc_available_frequencies()
/* Do things */
num_available = dev_pm_opp_get_opp_count(dev);
speeds = kzalloc(sizeof(u32) * num_available, GFP_KERNEL);
/* populate the table in increasing order */
freq = 0;
while (!IS_ERR(opp = dev_pm_opp_find_freq_ceil(dev, &freq)))
speeds[i] = freq;
freq++;
i++;
dev_pm_opp_put(opp);
soc_notify_coproc(AVAILABLE_FREQs, speeds, num_available);
/* Do other things */
OPP数据结构
通常,一个SoC包含多个可变电压域。每个域由一个设备指针描述。和OPP之间的关系可以按以下方式描述::
SoC
|- device 1
| |- opp 1 (availability, freq, voltage)
| |- opp 2 ..
... ...
| `- opp n ..
|- device 2
...
`- device m
OPP库维护着一个内部链表,SoC框架使用上文描述的各个函数来填充和访问。然而,描述真实OPP和域的结构体是OPP库自身的内部组成,以允许合适的抽象在不同系统中得到复用。
struct dev_pm_opp
OPP库的内部数据结构,用于表示一个OPP。除了频率、电压、可用性信息外,它还包含OPP库运行所需的内部统计信息。指向这个结构体的指针被提供给用户(比如SoC框架)使用,在与OPP层的交互中作为OPP的标识符。
警告:结构体dev_pm_opp的指针不应该由用户解析或修改。一个实例的默认值由dev_pm_opp_add填充,但OPP的可用性由dev_pm_opp_enable/disable函数修改。
struct device
这用于向OPP层标识一个域。设备的性质和它的实现是由OPP库的用户决定的,如SoC框架。
总体来说,以一个简化的视角看,对数据结构的操作可以描述为下面各图::
初始化和修改相关:
+-----+ /- dev_pm_opp_enable
dev_pm_opp_add --> | opp | <-------
| +-----+ \\- dev_pm_opp_disable
\\-------> domain_info(device)
查找函数:
/-- dev_pm_opp_find_freq_ceil ---\\ +-----+
domain_info<---- dev_pm_opp_find_freq_exact -----> | opp |
\\-- dev_pm_opp_find_freq_floor ---/ +-----+
检索函数:
+-----+ /- dev_pm_opp_get_voltage
| opp | <---
+-----+ \\- dev_pm_opp_get_freq
domain_info <- dev_pm_opp_get_opp_count
OPP的DTS配置
Ref
OBEX OPP 特定转账
【中文标题】OBEX OPP 特定转账【英文标题】:OBEX OPP Specific transfer 【发布时间】:2011-09-05 09:13:02 【问题描述】:我正在android中开发一个OBEX OPP客户端应用程序 电话。通过客户端应用程序 我将向非 Android 设备发送一个对象(它将充当 OPP 服务器)。我已经使用 API 创建了 RFCOMM 套接字连接
createRfcommSocketToServiceRecord(OPP_UUID);我已经使用了 UUID OBEX Push 即
私有静态最终 UUID OPP_UUID = UUID .fromString("00001105-0000-1000-8000-00805F9B34FB");
我观察到通过这个socket连接是成功的 我得到了要发送的套接字的输入和输出流 接收数据。但是当我发送数据时,数据收到了另一个 设备格式不正确。我的意思是在 接收器设备接收到的数据有错误。 BT 空气嗅探器 表示retrieved_opcode中的数据不存在。OBEX 响应代码是错误请求。
谁能指导我这有什么问题?或制作步骤 OBEX OPP 与未配对设备的连接。
您的宝贵意见将帮助我克服这个问题。
谢谢, 谢卡尔
【问题讨论】:
【参考方案1】:您应该可以配对设备,您也可以通过设备上的蓝牙设置进行配对,但您无法与它连接并像SPP通信那样直接发送数据。
OBEX是一个协议,有自己的头、包等。
Android 中没有可以通过编程方式使用的通过 OBEX 进行通信的 API。 (你可以连接到设备,但你只能读/写字节)。
您可以通过以下几种方式通过 obex 将文件发送到配对设备:
使用 ACTION_SEND 意图,将弹出一个菜单,其中包含可以处理您要发送的文件类型的应用程序,用户需要从中选择蓝牙,然后选择设备。
Intent share = new Intent(Intent.ACTION_SEND);
share.setType("image/jpeg");
share.putExtra(Intent.EXTRA_STREAM, Uri.parse(SDCardPath + "file.jpg"));
startActivity(Intent.createChooser(share, "Share Image"));
或者,如果您不希望应用程序中出现任何对话框,您也可以使用其他方法,检查以下问题,它有一个有效解决方案的更新:
Sending a File using Bluetooth OBEX Object Push Profile (OPP)
【讨论】:
以上是关于linux opp怎么使用的主要内容,如果未能解决你的问题,请参考以下文章