在调试驱动程序时, 经常要设置主控器寄存器参数或者运行时读取寄存器值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=, loop;
void __iomem *vaddr;
char rw; if(sscanf(buf, "%c %x %x", &rw, &addr, &val) == ) {
vaddr = ioremap(addr, PAGE_SIZE);
if(rw == 'W' || rw == 'w') {
writel(val, vaddr);
count = ;
} else if(rw == 'R' || rw == 'r') {
count = (val+) & ~;
} count = count > PAGE_SIZE ? PAGE_SIZE : count;
printk("\n");
for(loop=; loop<count; loop+=) {
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, , 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");

最新文章

  1. 基于Cat的分布式调用追踪
  2. appium的几点总结
  3. 字符串匹配算法 - KMP
  4. CSS常用背景图片定位方法
  5. TCP的连接控制
  6. Unity3d Android Http 开发中的坑(吐槽
  7. Python 学习笔记01
  8. MVC应用程序中,怎样控制与复制相同的功能
  9. [推荐]Zookeeper大型分布式系统的可靠协调系统知识介绍
  10. yum安装mariadb
  11. shell常用代码
  12. 配置duilib
  13. [hadoop源代码解读] 【SequenceFile】
  14. Unity的Profiler性能分析
  15. 修改vim/terminal配色
  16. Oracle参数设置之set与reset的实际案例
  17. AutoDesk Forge 获取令牌认证
  18. linux下在用户空间访问I/O端口的ioperm和iopl函数
  19. [LeetCode] Max Chunks To Make Sorted 可排序的最大块数
  20. Python——错误笔记

热门文章

  1. BZOJ_3589_动态树_容斥原理+树链剖分
  2. BZOJ_2724_[Violet 6]蒲公英_分块
  3. vue iview UPload,但文件上传是,clearFiles的使用方法
  4. linux清除全屏快捷键(Ctrl+L)
  5. js 的 骚操作
  6. nodejs操作redis总结
  7. 「Continuous_integration, CI」为什么要持续集成?
  8. 前端笔记之NodeJS(四)MongoDB数据库&amp;Mongoose&amp;自制接口&amp;MVC架构思想|实战
  9. WPF TextBox 正则验证 大于等于0 小于等于1 的两位小数
  10. 浅谈java线程池实现