zoukankan      html  css  js  c++  java
  • 开辟sys节点用户层直接操作物理地址(比/dev/mem方便)

      在调试驱动程序时, 经常要设置主控器寄存器参数或者运行时读取寄存器值debug问题, 每次修改驱动读取寄存器值都要编译一次驱动再insmod, 十分不方便, 哪怕驱动提供一个节点

    如dev/mem给应用程序读取, 还要编写应用程序open(), mmap(), read(),  write()  听着都头大, 我在/sys开辟vedic目录, 里面放着各种方便debug的节点, 其中就有个可以直接操作物理地址的节点“mem”,

      在用户空间直接echo操作物理地址, 包括寄存器和内存地址, 非常方便:

    /* 读取0x87800000 物理地址值 */
    / # echo R 0x87800000 0x4 > /sys/vedic/mem
    [0x87800000] = 0x12341234
    
    /* 写0x87800000 物理地址 */
    / # echo w 0x87800000 0x55555555 > /sys/vedic/mem
    [0x87800000] = 0x55555555
    
    
    错误会提示要求格式:
    / # echo R 0x87800000 > /sys/vedic/mem
    Usage: echo [R - Read/W - write]  [Physical Address]  [Value(Write)/Count(Read)]  > /sys/vedic/mem
    Eg: echo R 0x8008000 0x10 > /sys/vedic/mem
        echo w 0x8008000 0x12345678 > /sys/vedic/mem

      具体代码如下:

    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/device.h>
    #include <linux/kernel.h>
    #include <linux/io.h>
    #include <linux/sysfs.h>
    #include <linux/delay.h>
    
    struct kobject *vedic_kobj = NULL;
    
    static ssize_t mem_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t n)
    {
        unsigned int addr, val, count=0, loop;
        void __iomem *vaddr;
        char rw;
    
        if(sscanf(buf, "%c %x %x", &rw, &addr, &val) == 3) {
            vaddr = ioremap(addr, PAGE_SIZE);
            if(rw == 'W' || rw == 'w') {
                writel(val, vaddr);
                count = 4;
            } else if(rw == 'R' || rw == 'r') {
                count = (val+3) & ~3;
            }
    
            count = count > PAGE_SIZE ? PAGE_SIZE : count;
            printk("
    ");
            for(loop=0; loop<count; loop+=4) {
                val = readl(vaddr + loop);
                printk("[0x%08x] = 0x%08x
    ", addr + loop, val);
            }
    
            iounmap(vaddr);
        } else {
            printk("
    Usage: echo [R - Read/W - write]  [Physical Address] "
                " [Value(Write)/Count(Read)]  > /sys/vedic/mem
    "
                "Eg: echo R 0x8008000 0x10 > /sys/vedic/mem
    "
                "    echo w 0x8008000 0x12345678 > /sys/vedic/mem
    ");
            n = -EINVAL;
        }
    
        return n;
    }
    
    
    static DEVICE_ATTR(mem, 0644, NULL, mem_store);
    
    
    static struct attribute *vedic_attrs[] = {
        &dev_attr_mem.attr,
        NULL,
    };
    
    static struct attribute_group vedic_attr_group = {
        .attrs = vedic_attrs,
    };
    
    static int __init sys_vedic_init(void)
    {
        vedic_kobj = kobject_create_and_add("vedic", NULL);
        if (!vedic_kobj)
            return -ENOMEM;
        return sysfs_create_group(vedic_kobj, &vedic_attr_group);
    }
    
    static void __exit sys_vedic__exit(void)
    {
        if (vedic_kobj)
            sysfs_remove_group(vedic_kobj, &vedic_attr_group);
    }
    
    module_init(sys_vedic_init);
    module_exit(sys_vedic__exit);
    
    MODULE_AUTHOR("Vedic <FZKmxcz@163.com>");
    MODULE_LICENSE("GPL");
  • 相关阅读:
    Sudoku Solver [LeetCode]
    Populating Next Right Pointers in Each Node [LeetCode]
    Binary Tree Level Order Traversal [LeetCode]
    Clone Graph [LeetCode]
    Merge k Sorted Lists [LeetCode]
    Combinations [LeetCode]
    021 面向对象 一
    给图片加点料
    质数
    ex10 找出藏在字符串中的“密码”
  • 原文地址:https://www.cnblogs.com/vedic/p/10750763.html
Copyright © 2011-2022 走看看