Linux 操作系统读写寄存器

2018年11月14日 570 次阅读 2 条评论 3 人点赞

今天与大家分享如何在 Linux 操作系统中读写寄存器,当然对于熟悉嵌入式系统的人来讲早就烂熟如心,但是还是写出来方便交流与提示后来者。

Linux 内核中操作寄存器

其实对于 Linux 内核中操作寄存器是一件特别简单的事情,首先你需要知道你要操作寄存器的地址,有可能是网卡状态寄存器,有可能是门铃寄存器等等,不管是什么寄存器他都是在内存中映射出来的一段地址。

#include <linux/module.h>
#include <linux/init.h>
#include <linux/io.h>

static int __init hello_init(void)
{
        /* ioremap 由物理地址转换为虚拟地址 */
        unsigned long register_address = (unsigned long)ioremap(0x800286020c4, 4);
        /* 操作该寄存器 */
        *(unsigned int *)register_address = 0x1000;
        /* 读取该寄存器 */
        pr_err("*register_address = %x\n", *(unsigned int *)register_address);

        return 0;
}

static void __exit hello_exit(void)
{
        printk(KERN_ALERT "Bye man, I have been unload.\n");
}

module_init(hello_init);
module_exit(hello_exit);
MODULE_AUTHOR("Jackie Liu <liuyun01@kylinos.cn>");
MODULE_LICENSE("GPL");

Linux 应用层操作寄存器

应用层操作寄存器首先需要将内核映射到核外空间,内核已经提供了一个 /dev/mem 的文件接口,这个文件相当于整个系统内存所在,将该文件打开然后指定需要映射的内存的位置即可。需要注意的是,一般 mmap 映射的是一段内存地址空间,譬如一段 PCIe 寄存器空间等等,而不是一个单独的寄存器地址。

#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

int main(int argc, char **argv)
{
        int dev_fd = open("/dev/mem", O_RDWR | O_NDELAY);
        if (dev_fd < 0) {
                printf("open(/dev/mem) failed.");
                return 0;
        }

        void *map_base = mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, 0x80028780000);
        if (map_base == MAP_FAILED)
                return -1;

        printf("%x \n", *(volatile unsigned int *)(map_base));

        close(dev_fd);
        munmap(map_base,MAP_SIZE);

        return 0;
}
标签:
最后编辑:2018年11月14日

文章评论(2)

  • shan

    建议对 mmap 和 ioremap 的操作上都加 volatile ,防止缓存。

    2019年1月11日
    • Jackie Liu

      注意对 Volatile 的使用是个好习惯,但是这里可以不必使用,因为不存在多次代码对其进行修改,他只会被赋值一次。而且,一般对 Volatile 的使用需要在多个 Thread 时才需要注意。

      2019年1月11日