嵌入式 Linux应用程序如何读取(修改)芯片寄存器的值

原创 2013年12月02日 14:54:47

这一问题来自项目中一个实际的需求:
我需要在Linux启动之后,确认我指定的芯片寄存器是否与我在uboot的配置一致。

举个例子:
寄存器地址:0x20000010负责对DDR2的时序配置,该寄存器是在uboot中设置,现在我想在Linux运行后,读出改寄存器的值,再来检查该寄存器是否与uboot的配置一致。

Linux应用程序运行的是虚拟空间,有没有什么机制可以是完成我提到的这一需求。若行,还请附些测试代码。
谢谢!

这个需要用mmap()函数将寄存器物理地址映射为用户空间的虚拟地址,即将寄存器的那段内存映射到用户空间,函数介绍如下:


  1. void*mmap(void* addr, size_t len, intprot,int flags, intfd, off_t offset);

该函数映射文件描述符 fd 指定文件的 [offset, offset + len] 物理内存区至调用进程的 [addr,addr + len]的用户空间虚拟内存区,通常用于内存共享或者用户空间程序控制硬件设备,函数的返回值为最后文件映射到用户空间的地址,进程可直接操作该地址。下面是测试代码(仅供参考):


  1. #define DDR2_REG_BASE (0x20000000)
  2. #define MAP_SIZE4096UL
  3. #define MAP_MASK(MAP_SIZE- 1)

  4. static unsignedint pTestRegBase;
  5. static intdev_fd;

  6. dev_fd = open("/dev/mem",O_RDWR |O_NDELAY);

  7. if (dev_fd <</SPAN> 0) {
  8. LOGE("open(/dev/mem) failed.");
  9. return;
  10. }

  11. pTestRegBase = (void*)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, DDR2_REG_BASE &~MAP_MASK);

  12. if (MAP_FAILED == pTestRegBase) {
  13. printf("mmap failed.fd(%d), addr(0x%x), size(%d)\n", dev_fd, DDR2_REG_BASE, MAP_SIZE);
  14. } else{
  15. unsigned intreg_value =*((volatile unsignedint *)(pTestRegBase + 10));
  16. printf("reg_value =0xx\n", reg_value);
  17. munmap((void*)pTestRegBase, MAP_SIZE);
  18. }

  19. pTestRegBase = 0;

  20. if(dev_fd)
  21. close(dev_fd);

这里将DDR2_REG_BASE开始大小为1个page的物理地址映射到了用户空间,然后就可以用pTestRegBase作为起始地址操作寄存器了。

 
  • 0支持
    赞一个!可以看到我的开发板指定位置寄存器的值了。
    追问一下:
    我在我ubuntu主机(intel x86)上使用运行你给代码,会出现错误:
    ajaxhe@bbs:~/program/c$ sudo ./a.out
    mmap failed. fd(3), addr(0x20000000), size(4096)
    但将15行的程序修改为:
    pTestRegBase = (void *)mmap(NULL, MAP_SIZE, PROT_READ | PROT_WRITE,MAP_SHARED, dev_fd, 0);
    运行时正常,这里问题出再哪里呢?是不是因为0x20000000~0x20000000+4096在ubuntu的机器上没有地址映射的缘故呢?
  • 0支持
    @ajaxhex86架构寄存器地址我不怎么清楚,像arm架构的处理器寄存器一般都是在高端地址如0xF0000000以上,你可以在程序中把errno值打印出来看看是什么原因引起的。

1、首先写一个内核模块,在该内核模块中设置一个变量,用来存储该寄存器的值。
2、在内核模块中创建一个对应的proc,用来向用户空间输出该寄存器的值。
3、在用户空间直接cat之前创建的proc文件。

需要以内核模块的方式运行

晕,不说详细点,就扣分阿....

写个内核模块
使用ioremap()
映射到user地址空间

看看这里的咚咚

asm/io.h

写个驱动,在驱动里面去读你的寄存器就可以了。
这里有个实例,你可以下载试试:read_register_kmod.tar(下载地址:http://sdrv.ms/ZM8gFi)。

Linux在应用层读写寄存器的方法

可以通过操作/dev/mem设备文件,以及mmap函数,将寄存器的地址映射到用户空间,直接在应用层对寄存器进行操作,示例如下:...
  • liukang325
  • liukang325
  • 2014年05月22日 16:39
  • 8736

linux驱动实践(四)--linux下读写寄存器

arm裸机下读写寄存器很容易,各个寄存器和内存的地址是单一地址空间,他们是用相同的指令进行读写操作的.而在linux下就要复杂很多,因为linux支持多个体系架构的CPU。比如arm和x86就不一样,...
  • dndxhej
  • dndxhej
  • 2012年12月23日 23:22
  • 14350

linux中readl()和writel()函数---用于读写寄存器

 readX/writeX() are used to access memory mapped devices. On some  * architectures the memory ma...
  • mynameislinduan
  • mynameislinduan
  • 2014年12月18日 18:47
  • 3820

Linux调试备忘录1-- Linux kernel启动后,如何在用户命令行查看和修改寄存器值

Linux kernel启动后,如何在用户命令行查看和修改寄存器值? 我们知道Linux kernel启动后,由于memory map的管理,我们是无法...
  • swallow71701
  • swallow71701
  • 2014年04月17日 15:53
  • 1222

linux 内核中 查看寄存器的值

#include u32 temp; temp=__raw_readl(S5PV210_GPJ0_BASE);; printk(KERN_ALERT "before READ_GPJ0CON=0...
  • qq_25687403
  • qq_25687403
  • 2015年05月29日 15:49
  • 1217

嵌入式linux和uboot中关于读写寄存器的函数(__raw_writel, writel等)

uboot中是这么定义的: u-boot_2.3.5/arch/arm/include/asm/io.h /*  * Generic virtual read/write.  Note th...
  • duanlove
  • duanlove
  • 2012年07月26日 17:40
  • 3154

嵌入式 Linux应用程序如何读取(修改)芯片寄存器的值 -学习路上

这一问题来自项目中一个实际的需求: 我需要在Linux启动之后,确认我指定的芯片寄存器是否与我在uboot的配置一致。 举个例子: 寄存器地址:0x20000010负责对DDR2的时序配置,...
  • summer_fhb
  • summer_fhb
  • 2016年12月04日 17:37
  • 1114

嵌入式 Linux应用程序如何读取(修改)芯片寄存器的值

这一问题来自项目中一个实际的需求: 我需要在Linux启动之后,确认我指定的芯片寄存器是否与我在uboot的配置一致。 举个例子: 寄存器地址:0x20000010负责对DDR2的时序配置,该寄存器是...
  • skdkjxy
  • skdkjxy
  • 2013年12月02日 14:54
  • 1754

linux+arm 网卡故障调试:ethtool&phy寄存器读写

两个工具一个是ethtool工具,一个是源码编译的可以读phy寄存器的工具phyreg。两者结合使用,事半功倍。 ethtool 可以查看和设置网卡的工作状态,比如查看设置网卡的链接 自协商,10...
  • vc66vcc
  • vc66vcc
  • 2017年01月17日 14:13
  • 1328

嵌入式 Linux NFS方式下应用程序的实现 .pdf

  • 2014年03月20日 15:00
  • 117KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:嵌入式 Linux应用程序如何读取(修改)芯片寄存器的值
举报原因:
原因补充:

(最多只允许输入30个字)