点击上方“嵌入式Linux充电站”,选择“置顶/星标公众号”
福利干货,第一时间送达大家好,我是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
关注我,回复【加群】,进入嵌入式技术交流群,一起交流学习~
猜你喜欢: