开辟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("\n");
        for(loop=0; loop<count; loop+=4) {
            val = readl(vaddr + loop);
            printk("[0x%08x] = 0x%08x\n", addr + loop, val);
        }

        iounmap(vaddr);
    } else {
        printk("\nUsage: echo [R - Read/W - write]  [Physical Address] "
            " [Value(Write)/Count(Read)]  > /sys/vedic/mem\n"
            "Eg: echo R 0x8008000 0x10 > /sys/vedic/mem\n"
            "    echo w 0x8008000 0x12345678 > /sys/vedic/mem\n");
        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");

 

posted @ 2019-04-22 16:07  Vedic  阅读(675)  评论(0编辑  收藏  举报