4、CPU与内存节点调整:CPU频率、核心数、内存布局、DMA内存区域的配置
设备树里CPU和内存节点的调整,说白了你就是在告诉内核:「我的硬件长这样,你按这个来跑」。调对了,性能蹭蹭涨;调错了,系统可能连起都起不来。
我个人习惯,拿到一块新板子,第一件事就是先看这两块节点。CPU节点决定了你能用几个核、跑多快;内存节点决定了系统怎么用这片RAM。嗯,咱们一个一个来拆。
4.1 CPU节点:频率与核心数的精确控制
CPU节点在设备树里通常长这样:
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a72";
reg = <0x0>;
operating-points = <
1200000 1100000
1000000 1000000
800000 900000
>;
clock-latency = <300000>;
};
cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a72";
reg = <0x1>;
operating-points = <
1200000 1100000
1000000 1000000
800000 900000
>;
clock-latency = <300000>;
};
};
这里有个关键点——operating-points。每一行第一个数字是频率(kHz),第二个是电压(mV)。你想想看,如果你把频率写高了但电压没跟上,CPU就会不稳定。我在项目中遇到过,有人把频率从1.2GHz改到1.5GHz,电压没动,结果跑压力测试时系统随机死机。查了两天才发现是OPP表配错了。
核心数的控制更直接。如果你只想用4核中的2核,直接把另外两个cpu节点删掉或status设为"disabled"就行:
cpu@2 {
status = "disabled";
};
我曾经为了省电,在某个IoT项目里只开了2个核,剩下2个核在需要时才通过cpu-hotplug动态唤醒。效果不错,待机功耗降了30%。
4.2 内存节点:布局与大小
内存节点决定了内核能看到多少RAM,以及这些RAM怎么分布。基础写法:
memory@80000000 {
device_type = "memory";
reg = <0x0 0x80000000 0x0 0x80000000>;
};
这里reg的前两个数字是起始地址,后两个是大小。上面这个例子表示:从0x80000000开始,共2GB内存。
如果你的板子有多个内存区域,比如DDR和SRAM混用,可以这样写:
memory@80000000 {
device_type = "memory";
reg = <0x0 0x80000000 0x0 0x40000000>; /* 1GB DDR */
};
memory@c0000000 {
device_type = "memory";
reg = <0x0 0xc0000000 0x0 0x10000000>; /* 256MB SRAM */
};
mem=来临时限制内存大小,不用反复改设备树。比如mem=512M,方便你测试内存不足时的行为。
我有个教训:某次项目里,内存节点地址写错了,导致内核只认到一半的RAM。系统能跑,但跑着跑着就OOM。查了三天,最后发现是reg里的地址偏移算错了。嗯,这种低级错误最坑人。
4.3 DMA内存区域:性能的关键
DMA内存区域,说白了就是给外设直接访问用的内存池。配置好了,数据搬运不经过CPU,性能翻倍;配不好,DMA和CPU抢内存,反而更慢。
设备树里用reserved-memory来预留DMA区域:
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
dma_pool: dma@a0000000 {
compatible = "shared-dma-pool";
reg = <0x0 0xa0000000 0x0 0x10000000>;
no-map;
};
};
这里no-map;表示这块内存不映射到内核的页表,完全给DMA用。为什么这么做?因为DMA需要连续的物理内存,而内核的虚拟内存映射会打碎物理连续性。你想想看,如果DMA要搬运一个大块数据,结果物理地址东一块西一块,那还怎么搞?
然后在外设节点里引用这块区域:
ethernet@40000000 {
compatible = "vendor,eth";
reg = <0x0 0x40000000 0x0 0x1000>;
memory-region = <&dma_pool>;
};
我曾经在一个视频处理项目里,DMA区域只给了4MB,结果4K视频流一进来,DMA缓冲区频繁溢出,画面卡成PPT。后来改成32MB,问题立刻解决。
4.4 知识体系总览
下面这张图把CPU和内存节点的调整逻辑串起来了:
4.5 实战避坑清单
最后,我把自己踩过的坑整理成一张表,你调设备树时对照着检查:
| 节点类型 | 常见错误 | 后果 | 检查方法 |
|---|---|---|---|
| CPU | OPP表电压不足 | 高频死机 | 跑stress测试,监控电压 |
| CPU | 核心数写错 | 部分核无法使用 | cat /proc/cpuinfo |
| 内存 | reg地址偏移算错 | 内存容量不对 | free -m 对比硬件规格 |
| DMA | 预留区域太小 | DMA溢出、丢数据 | dmesg | grep dma |
| DMA | 忘了加no-map | 内核和DMA冲突 | 检查/proc/iomem |
嗯,CPU和内存节点的调整,说白了就是让内核知道你的硬件到底长什么样。别小看这几行配置,我见过太多系统因为这里写错,性能直接腰斩。你调设备树时,多花10分钟检查这些节点,后面能省下几天的调试时间。