LINUX下读写寄存器.docx
《LINUX下读写寄存器.docx》由会员分享,可在线阅读,更多相关《LINUX下读写寄存器.docx(10页珍藏版)》请在冰豆网上搜索。
![LINUX下读写寄存器.docx](https://file1.bdocx.com/fileroot1/2023-1/23/5dad2f58-5878-4cbb-9676-e0c9325a279e/5dad2f58-5878-4cbb-9676-e0c9325a279e1.gif)
LINUX下读写寄存器
arm裸机下读写寄存器很容易,各个寄存器和内存的地址是单一地址空间,他们是用相同的指令进行读写操作的.而在linux下就要复杂很多,因为linux支持多个体系架构的CPU。
比如arm和x86就不一样,具体的差别我暂时也说不上来,这个涉及到CPU体系的设计。
目前我只关心:
linux为了支持多个硬件体系,在IO访问上做了自己的接口。
可以通过IO内存和IO端口这两种方式进行IO访问。
在LED的例子上给出这两种方式的具体实现:
1.利用IOPort的方式:
[cpp]viewplaincopy
#include
#include
#include
#include/*printk()*/
#include/*kmalloc()*/
#include/*everything...*/
#include/*errorcodes*/
#include/*size_t*/
#include
#include/*O_ACCMODE*/
#include
#include
#include
#include
#include/*cli(),*_flags*/
#include/*copy_*_user*/
#include
#defineLED_NUM4
structled_dev
{
structcdevdev;
unsignedport;
unsignedlongoffset;
};
structled_devled[4];
dev_tdev=0;
staticstructresource*led_resource;
intled_open(structinode*inode,structfile*filp)
{
structled_dev*led;/*deviceinformation*/
led=container_of(inode->i_cdev,structled_dev,dev);
filp->private_data=led;/*forothermethods*/
return0;/*success*/
}
intled_release(structinode*inode,structfile*filp)
{
return0;
}
ssize_tled_read(structfile*filp,char__user*buf,size_tcount,loff_t*f_pos)
{
return0;
}
ssize_tled_write(structfile*filp,constchar__user*buf,size_tcount,loff_t*f_pos)
{
chardata;
structled_dev*led;
u32value;
printk(KERN_INFO"debugbybaikal:
leddevwrite\n");
led=(structled_dev*)filp->private_data;
copy_from_user(&data,buf,count);
if(data=='0')
{
printk(KERN_INFO"debugbybaikal:
ledoff\n");
value=inl((unsigned)(S3C2410_GPBDAT));
outl(value|1<offset,(unsigned)(S3C2410_GPBDAT));
//value=ioread32(led->base);
//iowrite32(value|1<offset,led->base);
}
else
{
printk(KERN_INFO"debugbybaikal:
ledon\n");
value=inl((unsigned)(S3C2410_GPBDAT));
outl(value&~(1<offset),(unsigned)(S3C2410_GPBDAT));
//value=ioread32(led->base);
//iowrite32(value&~(1<offset),led->base);
}
}
structfile_operationsled_fops={
.owner=THIS_MODULE,
.read=led_read,
.write=led_write,
//.ioctl=led_ioctl,
.open=led_open,
.release=led_release,
};
staticintled_init(void)
{
intresult,i;
result=alloc_chrdev_region(&dev,0,LED_NUM,"LED");
if(result<0){
printk(KERN_WARNING"LED:
can'tgetmajor%d\n",MAJOR(dev));
returnresult;
}
led_resource=request_region(0x56000014,0x4,"led");
if(led_resource==NULL)
{
printk(KERN_ERR"UnabletoregisterLEDI/Oaddresses\n");
return-1;
}
for(i=0;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;//ledsGPB5\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'taddled%d\n",i);
returnresult;
}
}
return0;
}
staticvoidled_exit(void)
{
inti;
release_region(0x56000014,0x4);
for(i=0;i{
//iounmap(led[i].base);
cdev_del(&led[i].dev);
}
unregister_chrdev_region(dev,LED_NUM);
}
module_init(led_init);
module_exit(led_exit);
MODULE_AUTHOR("Baikal");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SimpleLEDDriver");
2.利用IOMem的方式:
[cpp]viewplaincopy
#include
#include
#include
#include/*printk()*/
#include/*kmalloc()*/
#include/*everything...*/
#include/*errorcodes*/
#include/*size_t*/
#include
#include/*O_ACCMODE*/
#include
#include
#include
#include/*cli(),*_flags*/
#include/*copy_*_user*/
#include
#defineLED_NUM4
structled_dev
{
structcdevdev;
void__iomem*base;
unsignedlongoffset;
};
structled_devled[4];
dev_tdev=0;
intled_open(structinode*inode,structfile*filp)
{
structled_dev*led;/*deviceinformation*/
led=container_of(inode->i_cdev,structled_dev,dev);
filp->private_data=led;/*forothermethods*/
return0;/*success*/
}
intled_release(structinode*inode,structfile*filp)
{
return0;
}
ssize_tled_read(structfile*filp,char__user*buf,size_tcount,loff_t*f_pos)
{
return0;
}
ssize_tled_write(structfile*filp,constchar__user*buf,size_tcount,loff_t*f_pos)
{
chardata;
structled_dev*led;
u32value;
printk(KERN_INFO"debugbybaikal:
leddevwrite\n");
led=(structled_dev*)filp->private_data;
copy_from_user(&data,buf,count);
if(data=='0')
{
printk(KERN_INFO"debugbybaikal:
ledoff\n");
value=ioread32(led->base);
iowrite32(value|1<offset,led->base);
}
else
{
printk(KERN_INFO"debugbybaikal:
ledon\n");
value=ioread32(led->base);
iowrite32(value&~(1<offset),led->base);
}
}
structfile_operationsled_fops={
.owner=THIS_MODULE,
.read=led_read,
.write=led_write,
//.ioctl=led_ioctl,
.open=led_open,
.release=led_release,
};
staticintled_init(void)
{
intresult,i;
result=alloc_chrdev_region(&dev,0,LED_NUM,"LED");
if(result<0){
printk(KERN_WARNING"LED:
can'tgetmajor%d\n",MAJOR(dev));
returnresult;
}
for(i=0;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;//ledsGPB5\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'taddled%d\n",i);
returnresult;
}
}
return0;
}
staticvoidled_exit(void)
{
inti;
release_mem_region(0x56000014,0x4);
for(i=0;i{
iounmap(led[i].base);
cdev_del(&led[i].dev);
}
unregister_chrdev_region(dev,LED_NUM);
}
module_init(led_init);
module_exit(led_exit);
MODULE_AUTHOR("Baikal");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SimpleLEDDriver");
目前,对于具体体系上的linux在移植过程中如何实现这两种方式的方法还不清楚,现在只是会用。
等以后有机会了再慢慢理清楚。