导航:首页 > 编程系统 > linux读取寄存器

linux读取寄存器

发布时间:2024-08-09 17:03:02

❶ 请问在linux环境下中如何操作寄存器

在linux下控制硬件和在无操作系统下控制硬件的不同主要在于硬件的地址不一样,在linux下要使用va(虚拟地址),而在无操作系统下可以直接使用硬件的pa(物理地址)。
在linux-2.6.8.1/include/asm-arm/arch-s3c2410/map.h中定义了大部分硬件的物理地址和他们的虚拟地址。
现以gpio
F为例说明,gpio
的pa
基址(ba)为0x56000000,GPFCON
pa为0x56000050
即:可见偏移量为0x50,而我们在看看GPFCON
va
,vaba
:0xf0e0
0000,va:0xf0e0
0050,偏移量为0x50。我们只要知道了vaba,和他的偏移量,我们就能计算出va,从而,就可以对其进行操作了。

如何获取vaba:在linux-2.6.8.1/include/asm-arm/arch-s3c2410/map.h中有定义。
计算机中,分级分层的思想随处可见,这也是计算机上的一个基本的思想和思路。

在LINUX操作系统中分了三级,三级偏移,一级地址的ba为0xf0000000,偏移到第二级,0xf0e0
0000
(以GPIO为例),再次偏移到第三级,0xf0e0
0050
(以GPFCON为例)。现在,就可以在linux
下通过0xf0e0
0050来对GPFCON
寄存器来进行操作了。
源码中的实现过程如下:
#define
S3C2410_ADDR(x)
(0xF0000000+(x))//map.h
//linux下所有硬件一级地址vaba:0xF0000000
#define
S3C2410_VA_GPIO
S3C2410(0X00E00000)//map.h
//GPIO的偏移量0x00E00000,加上这个偏移量后,到了GPIO器件
#define
S3C2410_GPIOREG(x)
((x)+S3C2410_VA_GPIO)
#define
S3C2410_GPFCON
S3C2410_GPIOREG(0x50)//regs-gpio.h
//GPFCON寄存器的偏移量0x50,加上这个偏移量后,到了具体的寄存器,可以对硬件进行操作了
#define
S3C2410_GPFDAT
S3C2410_GPIOREG(0x54)//regs-gpio.h
#define
S3C2410_GPFUP
S3C2410_GPIOREG(0x58)//regs-gpio.h

❷ linux kernel 怎么读cpu写寄存器 inw

arm裸机下读写寄存器很容易,各个寄存器和内存的地址是单一地址空间,他们是用相同的指令进行读写操作的.而在linux下就要复杂很多,因为linux支持多个体系架构的CPU。比如arm和x86就不一样,具体的差别我暂时也说不上来,这个涉及到CPU体系的设计。目前我只关心:linux为了支持多个硬件体系,在IO访问上做了自己的接口。可以通过IO内存和IO端口这两种方式进行IO访问。在LED的例子上给出这两种方式的具体实现:
1.利用IO Port的方式:

[cpp] view plain
#include <linux/mole.h>
#include <linux/moleparam.h>
#include <linux/init.h>

#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/seq_file.h>
#include <linux/cdev.h>
#include <linux/ioport.h>

#include <mach/regs-gpio.h>
#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* _*_user */
#include <asm/io.h>

#define LED_NUM 4

struct led_dev
{
struct cdev dev;
unsigned port;
unsigned long offset;
};

struct led_dev led[4];
dev_t dev = 0;
static struct resource *led_resource;

int led_open(struct inode *inode, struct file *filp)
{
struct led_dev *led; /* device information */

led = container_of(inode->i_cdev, struct led_dev, dev);
filp->private_data = led; /* for other methods */

return 0; /* success */
}

int led_release(struct inode *inode, struct file *filp)
{
return 0;
}

ssize_t led_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
return 0;
}

ssize_t led_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
char data;
struct led_dev *led;
u32 value;
printk(KERN_INFO "debug by kal: led dev write\n");

led = (struct led_dev *)filp->private_data;
_from_user(&data,buf,count);
if(data == '0')
{
printk(KERN_INFO "debug by kal: led off\n");
value = inl((unsigned)(S3C2410_GPBDAT));
outl(value | 1<<led->offset,(unsigned)(S3C2410_GPBDAT));
//value = ioread32(led->base);
//iowrite32( value | 1<<led->offset, led->base);
}
else
{
printk(KERN_INFO "debug by kal: led on\n");
value = inl((unsigned)(S3C2410_GPBDAT));
outl(value & ~(1<<led->offset),(unsigned)(S3C2410_GPBDAT));
//value = ioread32(led->base);
//iowrite32( value & ~(1<<led->offset), led->base);
}
}

struct file_operations led_fops = {
.owner = THIS_MODULE,
.read = led_read,
.write = led_write,
//.ioctl = led_ioctl,
.open = led_open,
.release = led_release,
};

static int led_init(void)
{
int result, i;

result = alloc_chrdev_region(&dev, 0, LED_NUM,"LED");
if (result < 0) {
printk(KERN_WARNING "LED: can't get major %d\n", MAJOR(dev));
return result;
}
led_resource = request_region(0x56000014,0x4,"led");
if(led_resource == NULL)
{
printk(KERN_ERR " Unable to register LED I/O addresses\n");
return -1;
}
for(i = 0; i < LED_NUM; i++)
{
cdev_init( &led[i].dev, &led_fops);
//led[i].port = ioport_map(0x56000014,0x4);
//led[i].base = ioremap(0x56000014,0x4);
led[i].offset = i + 5; //leds GPB5\6\7\8
led[i].dev.owner = THIS_MODULE;
led[i].dev.ops = &led_fops;
result = cdev_add(&led[i].dev,MKDEV(MAJOR(dev),i),1);
if(result < 0)
{
printk(KERN_ERR "LED: can't add led%d\n",i);
return result;
}
}

return 0;
}

static void led_exit(void)
{
int i;
release_region(0x56000014,0x4);
for( i = 0; i < LED_NUM; i++)
{
//iounmap(led[i].base);

cdev_del(&led[i].dev);
}
unregister_chrdev_region(dev, LED_NUM);

}

mole_init(led_init);
mole_exit(led_exit);

MODULE_AUTHOR("Baikal");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Simple LED Driver");

2.利用IO Mem的方式:

[cpp] view plain
#include <linux/mole.h>
#include <linux/moleparam.h>
#include <linux/init.h>

#include <linux/kernel.h> /* printk() */
#include <linux/slab.h> /* kmalloc() */
#include <linux/fs.h> /* everything... */
#include <linux/errno.h> /* error codes */
#include <linux/types.h> /* size_t */
#include <linux/proc_fs.h>
#include <linux/fcntl.h> /* O_ACCMODE */
#include <linux/seq_file.h>
#include <linux/cdev.h>
#include <linux/ioport.h>

#include <asm/system.h> /* cli(), *_flags */
#include <asm/uaccess.h> /* _*_user */
#include <asm/io.h>

#define LED_NUM 4

struct led_dev
{
struct cdev dev;
void __iomem *base;
unsigned long offset;
};

struct led_dev led[4];
dev_t dev = 0;

int led_open(struct inode *inode, struct file *filp)
{
struct led_dev *led; /* device information */

led = container_of(inode->i_cdev, struct led_dev, dev);
filp->private_data = led; /* for other methods */

return 0; /* success */
}

int led_release(struct inode *inode, struct file *filp)
{
return 0;
}

ssize_t led_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
return 0;
}

ssize_t led_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
{
char data;
struct led_dev *led;
u32 value;
printk(KERN_INFO "debug by kal: led dev write\n");

led = (struct led_dev *)filp->private_data;
_from_user(&data,buf,count);
if(data == '0')
{
printk(KERN_INFO "debug by kal: led off\n");
value = ioread32(led->base);
iowrite32( value | 1<<led->offset, led->base);
}
else
{
printk(KERN_INFO "debug by kal: led on\n");
value = ioread32(led->base);
iowrite32( value & ~(1<<led->offset), led->base);
}
}

struct file_operations led_fops = {
.owner = THIS_MODULE,
.read = led_read,
.write = led_write,
//.ioctl = led_ioctl,
.open = led_open,
.release = led_release,
};

static int led_init(void)
{
int result, i;

result = alloc_chrdev_region(&dev, 0, LED_NUM,"LED");
if (result < 0) {
printk(KERN_WARNING "LED: can't get major %d\n", MAJOR(dev));
return result;
}

for(i = 0; i < LED_NUM; i++)
{
cdev_init( &led[i].dev, &led_fops);
request_mem_region(0x56000014,0x4,"led");
led[i].base = ioremap(0x56000014,0x4);
led[i].offset = i + 5; //leds GPB5\6\7\8
led[i].dev.owner = THIS_MODULE;
led[i].dev.ops = &led_fops;
result = cdev_add(&led[i].dev,MKDEV(MAJOR(dev),i),1);
if(result < 0)
{
printk(KERN_ERR "LED: can't add led%d\n",i);
return result;
}
}

return 0;
}

static void led_exit(void)
{
int i;
release_mem_region(0x56000014,0x4);
for( i = 0; i < LED_NUM; i++)
{
iounmap(led[i].base);

cdev_del(&led[i].dev);
}
unregister_chrdev_region(dev, LED_NUM);

}

mole_init(led_init);
mole_exit(led_exit);

MODULE_AUTHOR("Baikal");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Simple LED Driver");

❸ imx6q linux bsp中怎么读取一个寄存器的值

这一问题来自项目中一个实际的需求:
我需要在Linux启动之后,确认我指定的芯片寄存器是否与我在uboot的配置一致。
举个例子:
寄存器地址:0x20000010负责对DDR2的时序配置,该寄存器是在uboot中设置,现在我想在Linux运行后,读出改寄存器的值,再来检查该寄存器是否与uboot的配置一致。
Linux应用程序运行的是虚拟空间,有没有什么机制可以是完成我提到的这一需求。若行,还请附些测试代码
谢谢!
这个需要用mmap()函数将寄存器物理地址映射为用户空间的虚拟地址,即将寄存器的那段内存映射到用户空间,函数介绍如下:
void*
mmap(void
*
addr,
size_t
len,
int
prot,
int
flags,
int
fd,
off_t
offset);
该函数映射文件描述符
fd
指定文件的
[offset,
offset
+
len]
物理内存区至调用进程的
[addr,
addr
+
len]
的用户空间虚拟内存区,通常用于内存共享或者用户空间程序控制硬件设备,函数的返回值为最后文件映射到用户空间的地址,进程可直接操作该地址。下面是测试代码(仅供参考):
#define
DDR2_REG_BASE
(0x20000000)
#define
MAP_SIZE
4096UL
#define
MAP_MASK
(MAP_SIZE
-
1)
static
unsigned
int
pTestRegBase;
static
int
dev_fd;
dev_fd
=
open("/dev/mem",
O_RDWR
|
O_NDELAY);
if
(dev_fd
<</SPAN>
0)
{
LOGE("open(/dev/mem)
failed.");
return;
}
pTestRegBase
=
(void
*)mmap(NULL,
MAP_SIZE,
PROT_READ
|
PROT_WRITE,
MAP_SHARED,
dev_fd,DDR2_REG_BASE
&
~MAP_MASK);
if
(MAP_FAILED
==
pTestRegBase)
{
printf("mmap
failed.
fd(%d),
addr(0x%x),
size(%d)\n",
dev_fd,
DDR2_REG_BASE,
MAP_SIZE);
}
else
{
unsigned
int
reg_value
=
*((volatile
unsigned
int
*)(pTestRegBase
+
10));
printf("reg_value
=
0xx\n",
reg_value);
munmap((void*)pTestRegBase,
MAP_SIZE);
}
pTestRegBase
=
0;
if(dev_fd)
close(dev_fd);
这里将DDR2_REG_BASE开始大小为1个page的物理地址映射到了用户空间,然后就可以用pTestRegBase作为起始地址操作寄存器了。

❹ Linux下如何获取运行的进程中的寄存器的值

处理概要: 通过制定类型(int,char等)的指针变量,把rw的地址给这个指针。 通过指针操作,取得含有07位的数值,然后通过移位运算即可取得07位的值。 仅供参考。

❺ LINUX和WINDOWS中,如何查看PC寄存器里的内容

windows --> cmd --> debug --> r 可以看到。
linux 中用gdb应该可以看的,具体方式不太清楚,在emacs的gdb-many-windows中就可以看到。

❻ linux上有没有工具能看到内存和寄存器的值

用途说明 tail命令可以输出文件的尾部内容,默认情况下它显示文件的最后十行。回它常答用来动态监视文件的尾部内容的增长情况,比如用来监视日志文件的变化。与tail命令对应的是head命令,用来显示文件头部内容。

阅读全文

与linux读取寄存器相关的资料

热点内容
245倒角编程怎么计算 浏览:599
可以买生活用品的app有哪些 浏览:175
cad在c盘产生的文件夹 浏览:541
联想手机解锁工具 浏览:696
瑞银3887win10 浏览:833
学网络编程哪个好 浏览:805
手机vmos导入的文件在哪里 浏览:115
苹果手机可以把文件传到华为吗 浏览:63
海川化工下载的文件默认到哪里 浏览:343
学唱粤语歌app 浏览:975
qq游戏生死狙击玩不了 浏览:120
win10邮件不显示图片 浏览:922
口袋妖怪所有版本下载 浏览:504
我们身边都有哪些大数据例子 浏览:25
震旦adc307扫描的文件在哪里 浏览:999
图片打开变成文件 浏览:194
松下微单电脑传文件软件 浏览:574
苹果蓝牙键盘surface 浏览:170
mindmaplinux 浏览:733
oppo手机怎么连接电脑传输数据 浏览:624

友情链接