導航:首頁 > 編程系統 > 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讀取寄存器相關的資料

熱點內容
文件夾正裝 瀏覽:279
剛復制的文件找不到怎麼辦 瀏覽:724
試運行適用於哪些體系文件 瀏覽:987
ghost文件復制很慢 瀏覽:967
傑德原車導航升級 瀏覽:240
編程dest是什麼意思 瀏覽:935
linux埠鏡像 瀏覽:820
iphone5屏幕清塵 瀏覽:157
機頂盒密碼怎麼改 瀏覽:672
w7系統下載32位教程 瀏覽:618
pcb文件包括哪些內容 瀏覽:598
g00文件 瀏覽:607
用bat程序刪除程序 瀏覽:516
dnf鬼泣90版本打安圖恩 瀏覽:668
245倒角編程怎麼計算 瀏覽:599
可以買生活用品的app有哪些 瀏覽:175
cad在c盤產生的文件夾 瀏覽:541
聯想手機解鎖工具 瀏覽:696
瑞銀3887win10 瀏覽:833
學網路編程哪個好 瀏覽:805

友情鏈接