Linux内核dvfs之cpufreq配置

Linux内核dvfs之cpufreq配置,第1张

本文基于 RockPi 4A 单板 Linux4.4 内核介绍 OPP Table 。

内核中将频率、电压的相关配置放在 DTSI 文件中,这些配置信息组成的节点被称为 OPP Table(Operating Performance Points) 。

定义文件: arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi ,内容如下:

上面节点中的相关属性含义如下:

1、 opp-shared :表示 opp-table1 是小核的各 CPU 共用。

2、 rockchip,temp-hysteresis :迟滞参数,防止频繁进入高温或低温,单位:毫摄氏度。

3、 rockchip,low-temp :低温阈值。小于该值时,进入低温,大于‘该值+迟滞参数’时,恢复常温。

4、 rockchip,low-temp-min-volt :低温下最低电压,单位:微伏。

5、 nvmem-cells :从 eFUSE 中读取相关信息值(小核漏电流)。

6、 rockchip,pvtm-voltage-sel :min-pvtm(单位KHz)、max-pvtm(单位KHz)和 voltage-selector (用于匹配 opp 节点中 opp-microvolt-L* 属性的序列号)。例:pvtm值为:0 ~ 143500 使用 opp-microvolt-L0 ,143501 ~ 148500使用 opp-microvolt-L1

7、 rockchip,pvtm-freq :时钟频率(KHz),在获取 pvtm 的频率前,先设置 CPU 频率。

8、 rockchip,pvtm-volt :电压(微伏),在获取 pvtm 的频率前,先设置 CPU 电压。

9、 rockchip,pvtm-ch : PVTM 通道,格式<通道号 sel的序号>

10、 rockchip,pvtm-sample-time : PVTM 采样时间,单位:毫秒。

11、 rockchip,pvtm-number : PVTM 采样个数。

12、 rockchip,pvtm-error :允许采样数据之间的误差。

13、 rockchip,pvtm-ref-temp :参考温度。

14、 rockchip,pvtm-temp-prop : PVTM 随温度变化的比例系数,格式<小于参考温度的比例系数 大于参考温度的比例系数>。

15、 rockchip,thermal-zone :获取温度的 thermal-zone 。

16、 opp-microvolt-L* :电压(微伏),格式<target min max>

17、 clock-latency-ns :完成变频需要的时间,单位:纳秒。

在 RK3399 中,除了配置上述小核的 opp table 外,还设置了大核( cluster1_opp )、 gpu(gpu_opp_table) 等的相关值。查看命令如下:

注:

CPU PVTM(Process Voltage Temperature Monitor) 是一个位于 CPU 附近,能反应出不同芯片之间性能差异的模块,受工艺,电压和温度 的影响。

参考:

Documentation/devicetree/bindings/cpufreq/cpufreq-rockchip.txt

Documentation/devicetree/bindings/cpufreq/cpufreq-rockchip.txt

epoll_wait, epoll_pwait, epoll_pwait2 - 在epoll fd上等待I/O事件

events 指向了事件缓冲区,每当interest list中fd触发事件加入到ready list后,会将其返回到事件缓冲区中。最大返回 maxevents 个,因此 maxevent s至少大于0。返回的event顺序写入缓冲区。 timeout 参数指定epoll_wait将阻塞的毫秒数。

epoll_wait()将会一直阻塞直到:fd产生事件 / 被信号处理函数打断 / 超时。

时间测量将使用CLOCK_MONOTONIC (系统启动后到现在的时间,记录的是tick的总次数) 时钟,超时时间将向上舍入到系统时钟粒度,内核调度延迟可能让阻塞时间稍微超出。指定为-1时将无限期阻塞,指定为0时若没有可用事件则立即返回。

返回的epoll_event中,data字段与使用event_ctl(2)(EPOLL_CTL_ADD,EPOLL_CTL_MOD)传入的data一致。 (所以一般来说用fd足矣) ,而events字段是此fd触发的事件。

与epoll_wait自比,后者允许应用程序安全的等待(在调用epoll_wait(),设置自定义的信号掩码,并在epoll_wait()结束后恢复),直到文件描述等就绪或信号被捕获。

等价于:

sigmask指定为NULL时,epoll _pwait与epoll_wait相同。epoll_pwait2与epoll_pwait除timeout参数外完全相同,它指定timespec结构来执行纳秒级的等待。设为NULL时将一直等。

错误将返回-1,并设定errno;

超时将返回0

成功将返回触发I0事件的fd个数。

epoll_wait() 在 2.6 版中被添加到内核中。 从版本 2.3.2 开始,glibc 中提供了库支持。

epoll_pwait() 在内核 2.6.19 中被添加到 Linux。 从版本 2.6 开始,glibc 中提供了库支持。

epoll_pwait2() 在内核 5.11 中被添加到 Linux。

epoll_wait(), epoll_pwait(), and epoll_pwait2() are Linux-specific.

虽然一个线程在调用 epoll_wait() 时被阻塞,但另一个线程可能会向等待的 epoll 实例添加文件描述符。 如果新的文件描述符准备好,它将导致 epoll_wait() 调用解除阻塞。

如果在调用 epoll_wait() 时有超过 maxevents 个文件描述符准备就绪,那么连续的 epoll_wait() 调用将 循环遍历 准备好的文件描述符集。 此行为有助于避免饥饿情况,即进程未能注意到其他文件描述符已准备就绪,因为它专注于一组已知已准备就绪的文件描述符。循环遍历的意义就在于避免只访问固定位置的事件。

请注意,可以在 interest-list 当前为空的 epoll 实例上调用 epoll_wait() (或者其interest-list因为文件描述符被关闭或从另一个线程中的兴趣中删除而变为空)。 该调用将阻塞,直到在另一个线程中将某个文件描述符添加到interest-list并且该文件描述符准备就绪。

C library/kernel differences

原始的 epoll_pwait() 和 epoll_pwait2() 系统调用有第六个参数 size_t sigsetsize,它指定了 sigmask 参数的字节大小。 glibc epoll_pwait() 包装函数将此参数指定为固定值(等于 sizeof(sigset_t))。

在 2.6.37 之前的内核中,大于大约 LONG_MAX / HZ 毫秒的超时值被视为 -1(即无穷大)。 因此,例如,在 sizeof(long) 为 4 且内核 HZ 值为 1000 的系统上,这意味着大于 35.79 分钟的超时被视为无穷大

1.udelay()mdelay()ndelay()实现的原理本质上都是忙等待,ndelay和mdelay都是通过udelay衍生出来的,我们使用这些函数的实现往往会碰到编译器的警告implicit declaration of function'udelay',这往往是由于头文件的使用不当造成的。在include/asm-???/delay.h中定义了udelay(),而在include/linux/delay.h中定义了mdelay和ndelay. udelay一般适用于一个比较小的delay,如果你填的数大于2000,系统会认为你这个是一个错误的delay函数,因此如果需要2ms以上的delay需要使用mdelay函数。 2.由于这些delay函数本质上都是忙等待,对于长时间的忙等待意味这无谓的耗费着cpu的资源,因此对于毫秒级的延时,内核提供了msleep,ssleep等函数,这些函数将使得调用它的进程睡眠参数指定的时间。 应用层: #include <unistd.h> 1、unsigned int sleep(unsigned int seconds)秒级 2、int usleep(useconds_t usec) 微秒级:1/10^-6 #define _POSIX_C_SOURCE 199309 #include <time.h> 3、int nanosleep(const struct timespec *req, struct timespec *rem) struct timespec { time_t tv_sec /* seconds */ long tv_nsec /* nanoseconds */ } // The value of the nanoseconds field must be in the range 0 to 999999999. 内核层: include <linux/delay.h> 1、void ndelay(unsigned long nsecs)纳秒级:1/10^-10 2、void udelay(unsigned long usecs)微秒级: 1/10^-6 3、void mdelay(unsigned long msecs)毫秒级:1/10^-3 sleep_on(), interruptible_sleep_on()sleep_on_timeout(), interruptible_sleep_on_timeout()根据你的情况选用这些函数,注意: sleep *** 作在kernel必须小心、小心。。。 udelay()等函数是cpu忙等,没有传统意义上的sleep。这些函数相当于我们平时的阻塞读、写之类的语义,主要用于等外设完成某些 *** 作


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7382033.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-05
下一篇 2023-04-05

发表评论

登录后才能评论

评论列表(0条)

保存