linux 驱动读写文件,Linux下读写寄存器

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

1.利用IO Port的方式:

#include

#include

#include

#include  /* printk() */

#include   /* kmalloc() */

#include   /* everything... */

#include  /* error codes */

#include  /* size_t */

#include

#include  /* O_ACCMODE */

#include

#include

#include

#include

#include   /* cli(), *_flags */

#include  /* copy_*_user */

#include

#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 baikal: led dev write\n");

led = (struct led_dev *)filp->private_data;

copy_from_user(&data,buf,count);

if(data == '0')

{

printk(KERN_INFO "debug by baikal: led off\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 "debug by baikal: led on\n");

value = inl((unsigned)(S3C2410_GPBDAT));

outl(value & ~(1<offset),(unsigned)(S3C2410_GPBDAT));

//value = ioread32(led->base);

//iowrite32( value & ~(1<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);

}

module_init(led_init);

module_exit(led_exit);

MODULE_AUTHOR("Baikal");

MODULE_LICENSE("GPL");

MODULE_DESCRIPTION("Simple LED Driver");

2.利用IO Mem的方式:

#include

#include

#include

#include  /* printk() */

#include   /* kmalloc() */

#include   /* everything... */

#include  /* error codes */

#include  /* size_t */

#include

#include  /* O_ACCMODE */

#include

#include

#include

#include   /* cli(), *_flags */

#include  /* copy_*_user */

#include

#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 baikal: led dev write\n");

led = (struct led_dev *)filp->private_data;

copy_from_user(&data,buf,count);

if(data == '0')

{

printk(KERN_INFO "debug by baikal: led off\n");

value = ioread32(led->base);

iowrite32( value | 1<offset, led->base);

}

else

{

printk(KERN_INFO "debug by baikal: led on\n");

value = ioread32(led->base);

iowrite32( value & ~(1<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);

}

module_init(led_init);

module_exit(led_exit);

MODULE_AUTHOR("Baikal");

MODULE_LICENSE("GPL");

MODULE_DESCRIPTION("Simple LED Driver");

目前,对于具体体系上的linux在移植过程中如何实现这两种方式的方法还不清楚,现在只是会用。等以后有机会了再慢慢理清楚。0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值