Linux 内核调试工具devmem介绍¶
在调试驱动和内核过程中,进场会遇到一些问题,这里介绍一个内核调试工具devmem,很可能已经很多用上了。
1. devmem初识¶
devmem 是一个 Linux 命令行工具,用于在用户空间直接访问系统内存。这个工具允许开发者读取或写入特定物理地址上的内存内容,通常用于嵌入式系统的调试和开发过程中。
比如说在开发过程中,配置了某个寄存器的值,但是这个时候你无法判定这个寄存器的值是多少,想要去获取,可能需要写一个驱动,在驱动中去映射寄存器地址,转为虚拟地址就可以访问。但是这样很麻烦,但是有这个devmem,就可以直接通过devmem去读取寄存器的值,只是作为一个命令去操作非常方便。
devmem 命令格式:
Usage: devmem ADDRESS [WIDTH [VALUE]]
Read/write from physical address
ADDRESS Address to act upon
WIDTH Width (8/16/...)
VALUE Data to be written
ADDRESS : 物理地址
WIDTH:位宽
VALUE:值
2. Devmem 在内核中配置¶
内核配置文件打开
CONFIG_DEVMEM = y

图2.1 内核配置menuconfig
devmem 命令确实依赖于 Linux 系统中的 /dev/mem 设备文件。
devmem 使用了mmap系统调用,将物理内存映射到用户空间的虚拟地址空间。这样,物理内存的某个范围就可以像访问普通内存一样通过指针进行访问。
3. 应用层使用devmem¶
根据前面知识:
devmem 使用了mmap系统调用;
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#define BASE_ADDRESS 0x12345678 // 替换为你要访问的基地址
#define REGISTER_OFFSET 0x04 // 替换为你要访问的寄存器相对于基地址的偏移量
int main() {
int mem_fd;
void *mapped_base, *mapped_dev_base;
off_t dev_base = BASE_ADDRESS;
// 打开 /dev/mem 设备文件
mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
if (mem_fd == -1) {
perror("Error opening /dev/mem");
return EXIT_FAILURE;
}
// 映射物理地址到用户空间
mapped_base = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, dev_base & ~(getpagesize() - 1));
if (mapped_base == (void *)-1) {
perror("Error mapping /dev/mem into user space");
close(mem_fd);
return EXIT_FAILURE;
}
// 计算相对于映射基地址的偏移量
mapped_dev_base = mapped_base + (dev_base & (getpagesize() - 1));
// 读取寄存器的值
unsigned int reg_value = *((volatile unsigned int *)(mapped_dev_base + REGISTER_OFFSET));
printf("Current value of the register: 0x%08X\n", reg_value);
// 写入新的值到寄存器
unsigned int new_value = 0xABCD;
*((volatile unsigned int *)(mapped_dev_base + REGISTER_OFFSET)) = new_value;
printf("New value written to the register: 0x%08X\n", new_value);
// 解除映射并关闭文件
if (munmap(mapped_base, getpagesize()) == -1) {
perror("Error unmapping /dev/mem");
}
close(mem_fd);
return EXIT_SUCCESS;
}
4. 实际应用举例¶
4.1 设备驱动配置调试,对寄存器的查询¶
在配置驱动的过程中,对于SOC某些寄存器配置,想重新查询可以使用devmem
比如:笔者在使用配置SPI 寄存器后发现SPI 无时钟信号,发现pinctrl未起作用,这里就可以通过读取pin的寄存器的值进行判断是否有配置。

4.2 内存映射区域的调试:
对于一些外设,特定的内存映射区域用于与外设进行通信。通过 devmem,开发人员可以检查和修改这些内存映射区域的内容,以验证硬件状态或进行调试。
5. 结语¶
DEVMEM 是一个比较常用的工具,特别是在查询SOC寄存器值的有比较方便的作用,对于Linux 内核调试是一种工具的一种,后续还将分享一些其他工具。