zoukankan      html  css  js  c++  java
  • 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
    ", *(unsigned int *)register_address);
    
            return 0;
    }
    
    static void __exit hello_exit(void)
    {
            printk(KERN_ALERT "Bye man, I have been unload.
    ");
    }
    
    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 AUDIO_REG_BASE  (0x80028780000)
    #define MAP_SIZE    0x80000
    
    static int dev_fd;
    int main(int argc, char **argv)
    {
    
        dev_fd = open("/dev/mem", O_RDWR | O_NDELAY);
    
        if (dev_fd < 0)
        {
            printf("open(/dev/mem) failed.");
            return 0;
        }
    
        unsigned char *map_base=(unsigned char * )mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, AUDIO_REG_BASE );
        if (map_base == MAP_FAILED)
            return -1;
    
        printf("%x 
    ", *(volatile unsigned int *)(map_base));
    
        printf("%x 
    ", *(volatile unsigned int *)(map_base+0x38)); //打印该寄存器地址的value
    
    #if 1 // LINE IN
        printf("%x 
    ", *(volatile unsigned int *)(map_base+0x30));
    
        *(volatile unsigned int *)(map_base + 0x30) = 0x208121bc; //修改该寄存器地址的value
        usleep(1000000);
        *(volatile unsigned int *)(map_base + 0x30) &= ~(0x1<<16); //修改该寄存器地址的value
        usleep(1000000);
    
        printf("%x 
    ", *(volatile unsigned int *)(map_base+0x30));
    #endif
    
        if(dev_fd)
            close(dev_fd);
    
        munmap(map_base,MAP_SIZE);//解除映射关系
    
        return 0;
    }
  • 相关阅读:
    [LeetCode] 56. Merge Intervals 解题思路
    [LeetCode] 128. Longest Consecutive Sequence 解题思路
    [LeetCode] Subsets I (78) & II (90) 解题思路,即全组合算法
    linux安装PHP7以及扩展
    php安装composer
    细说PHP中strlen和mb_strlen的区别
    mysql一些简单操作
    mysql数据库使用Navicat时向Navicat导入sql文件时某字段过大时的处理
    JS中||的某些用法
    PHP验证身份信息
  • 原文地址:https://www.cnblogs.com/libra13179/p/13809241.html
Copyright © 2011-2022 走看看