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

1.利用IO Port的方式:

#include <linux/module.h>
#include <linux/moduleparam.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> /* copy_*_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 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<<led->offset,(unsigned)(S3C2410_GPBDAT)); 
  //value = ioread32(led->base);
  //iowrite32( value | 1<<led->offset, led->base);  
 }
 else
 {
  printk(KERN_INFO "debug by baikal: 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);

}

module_init(led_init);
module_exit(led_exit);

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

2.利用IO Mem的方式:

#include <linux/module.h>
#include <linux/moduleparam.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> /* copy_*_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 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<<led->offset, led->base);  
 }
 else
 {
  printk(KERN_INFO "debug by baikal: 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);

}

module_init(led_init);
module_exit(led_exit);

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

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

Linux下读写寄存器的更多相关文章

  1. Linux下读写芯片的I2C寄存器

    要想在Linux下读写芯片的I2C寄存器,一般需要在Linux编写一份该芯片的I2C驱动,关于Linux下如何编写I2C驱动,前一篇文章<手把手教你写Linux I2C设备驱动>已经做了初 ...

  2. Linux下读写UART串口的代码

    Linux下读写UART串口的代码,从IBM Developer network上拿来的东西,操作比較的复杂,就直接跳过了,好在代码能用,记录一下- 两个实用的函数- //////////////// ...

  3. Linux 下挂在ntfs 硬盘

    CentOS 7 下想要挂载NTFS的文件系统该怎么办呢? 我们需要一个NTFS-3G工具,并编译它之后在mount就可以了,就这么简单. 首先要进入官网下载NTFS-3G工具 http://www. ...

  4. linux 下使用opengl的glut库显示和旋转BMP图片

    效果图: 这里显示的图和原图有明显的色差,目前猜测是opengl渲染时的颜色表顺序跟BMP文件里的颜色表顺序相反导致. BMP里应该是BGRBGRBRG... ,而opengl渲染时应该是按照RGBR ...

  5. 在Linux下如何用Shell脚本读写XML?现有一个config.xml(转)

    在Linux下如何用Shell脚本读写XML?现有一个config.xml <?xml version="1.0" encoding="UTF-8"?&g ...

  6. linux下操作gpio寄存器的方法

    一. 在驱动中: 1. 用的时候映射端口:ioremap; #define GPIO_OFT(x) ((x) - 0x56000000) #define GPFCON (*(volatile unsi ...

  7. linux下c通过虚拟地址映射读写文件的代码

    在代码过程中中,把开发过程中比较好的一些代码片段记录起来,如下的代码内容是关于 linux下c通过虚拟地址映射读写文件的代码,应该对小伙伴有些好处.#include<stdio.h>#in ...

  8. linux下测试磁盘的读写IO速度-简易方法

    linux下测试磁盘的读写IO速度-简易方法 参考资料:https://blog.csdn.net/zqtsx/article/details/25487185 一:使用hdparm命令 这是一个是用 ...

  9. Linux下按扇区读写块设备

    本文介绍Linux下按扇区读写块设备(示例TF卡),实际应用是在Android系统上,主要方法如下: 1.找到sdcard的挂载点,在android2.1系统下应该为/dev/block/mmcblk ...

随机推荐

  1. 使用INSERT…SELECT语法插入记录(三十二)

    前面,我们在谈INSERT语句时,使用两种语句:INSERT…SELECT  和  INSERT…VALUES. INSERT…SELECT可以使用子查询.因为在写SELECT时.  ***  =   ...

  2. 互联网金融研究组:P2P借贷平台:性质、风险与监管(上)

    互联网金融研究组(): P2P借贷平台:性质.风险与监管(上) 目 录 一.性质与合法性 1.  P2P网络借贷 1.1  概念重新界定 1.2  发展概况与特点 2.  延伸模式及其合法性浅析 2. ...

  3. 关于echarts3版本里的tree图形显示Bug、无法缩放和移动

    在使用echarts3版本的js绘制tree图表的时候,如果想动态更新tree的数据,可能会出现图表渲染有异常,并且api给出的roam配置无法控制图表通过鼠标缩放和移动,如下图: 不过更改echar ...

  4. codeforces111D. Petya and Coloring(组合数学,计数问题)

    传送门: 解题思路: 要求一条直线分割矩阵时左右颜色数一样,那么就说明一个问题.直线左右移动时是不会改变左右矩阵的颜色集合的.所以说明:2~m-1列的颜色集一定属于第一列与第m列颜色集的交集.而且第一 ...

  5. 虚拟摄像头vivi的测试(二)

    (前一部分的基础操作来源于作者:LingXiaokai 的 Ubuntu 9.10 下如何使用笔记本摄像头以及虚拟摄像头vivi的测试) 自己仅对实际操作中需要注意的点进行阐述 一.先在Ubuntu ...

  6. jquery正则匹配URL地址

    JQuery代码: var regexp = /((http|ftp|https|file):\/\/([\w\-]+\.)+[\w\-]+(\/[\w\u4e00-\u9fa5\-\.\/?\@\% ...

  7. 如何实现对网站页面访问量的统计(javaweb和php)

    如何实现对网站页面访问量的统计(javaweb和php) 一.总结 一句话总结:其实很简单啦,每访问一次那个页面对应的index函数(控制器中的那个函数)访问次数就加1就可以了. 1.javaweb中 ...

  8. CentOS下编译安装PHP5.6

    目录 1 安装php依赖的扩展 2 下载解压PHP 3 编译PHP 4 让Apache支持PHP 5 测试安装  安装php依赖的扩展: yum install -y libxml2-devel op ...

  9. 码农Coding Peasant(s):一般指从事没有发展前景的软件开发职位

    码农Coding Peasant(s):一般指从事没有发展前景的软件开发职位,这种职位只能强化职业者在单方面的技术领域技能,学不到新技术,同时也是部分从事软件开发工作人员的一个自嘲的称号.一个依靠写代 ...

  10. Vue 国家省市三级联动

    在网上查阅一下,基本上是省市区三级联动,国家省市的就只能自己动手了. 样式就根据自己的需要去调整了. JSON数组太长,就折叠放在了后面. 效果图: <!DOCTYPE html> < ...