大家好,我是Vincent。
大家都知道在linux中操作寄存器,都是驱动去做的。
但其实,驱动层、应用层和shell中都是可以操作寄存器的。
Linux驱动操作寄存器
首先在设备树里定义一个节点,例如:
uart0: serial@10010000 { compatible = "sifive,uart0"; reg = <0x0 0x10010000 0x0 0x1000>; status = "okay"; }
@
符号后面是寄存器的基地址,然后填写compatible
和reg
属性,status
属性设置为okay
。
reg属性中,第二参数为寄存器基址,与@符号后面的地址对应,第四个参数是映射的大小。
驱动中操作:
#define OFFSET 0x60 //某个寄存器的偏移地址 static int my_probe(struct platform_device *pdev) { struct resource *res; void __iomem *base; u32 regval; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, res); //寄存器读写 regval = readl(base + OFFSET);//读寄存器 regval |= (1 << 0);//赋值 writel(regval, base + OFFSET);//写寄存器 return 0; }
先调用platform_get_resource
获取IORESOURCE_MEM
资源,就是获取了设备树中的reg
属性,返回的resource
结构体中包含了起始地址和结束地址。然后调用devm_ioremap_resource
映射这个资源,就能得到一个虚拟地址。后续对该虚拟地址的操作,就等同于对寄存器物理地址的操作。
读写寄存器,可以调用readl
、writel
函数。先读取寄存器的值放到临时变量中,赋值后,再一次性写入。
应用层操作寄存器
驱动中操作寄存器,需要先进行映射将物理地址转为虚拟地址。
但如果想在应用层中操作寄存器,也是可以实现的。
应用层中只需打开/dev/mem
设备节点,然后用mmap
映射寄存器地址就可以访问了。
例如,应用层读取物理地址为0x40000000
的值:
#include <stdio.h> #include <stdlib.h> #include <time.h> #include <unistd.h> #include <fcntl.h> #include <unistd.h> #include <sys/mman.h> #define MAP_SIZE 0x80000 #define base 0x40000000 int main(int argc, char **argv) { int fd = open("/dev/mem",O_RDWR|O_NDELAY); if (fd < 0) { printf("open /dev/mem error!\n"); return -1; } void *map_base = mmap(NULL,MAP_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,fd,base); if (map_base == MAP_FAILED) return -1; printf("%x \n",*(volatile unsigned int*)(map_base)); close(fd); munmap(map_base,MAP_SIZE); return 0; }
注意,内核必须将CONFIG_STRICT_DEVMEM=y配置选项打开才有/dev/mem节点
shell中操作寄存器
shell
中操作寄存器可以使用devmem
命令.
devmem
命令其实就是上述应用层操作寄存器生成的可执行文件,只不过busybox已经帮我们实现了。
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
:位宽,32位、64位等等
VALUE
:要写入的值
例如,读取32位寄存器0x40200000
的值:
devmem 0x40200000 32
向32位寄存器0x40200000
写入0x12345678
devmem 0x40200000 32 0x12345678
end
关注我,回复【加群】,进入嵌入式技术交流群,一起交流学习~
猜你喜欢:
嵌入式Linux充电站
作者Vincent,分享一些嵌入式Linux、内核、RISC-V等知识。学习、沉淀、分享,才能有所获。
74篇原创内容
公众号
收录于合集 #Linux驱动
30个
上一篇当我用几道题考了一遍做Linux驱动的同事......下一篇嵌入式BSP工程师到底是干嘛的?
喜欢此内容的人还喜欢
那些只有芯片原厂才能做的驱动开发工作
嵌入式Linux充电站