Linux下读写寄存器
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下读写寄存器的更多相关文章
- Linux下读写芯片的I2C寄存器
要想在Linux下读写芯片的I2C寄存器,一般需要在Linux编写一份该芯片的I2C驱动,关于Linux下如何编写I2C驱动,前一篇文章<手把手教你写Linux I2C设备驱动>已经做了初 ...
- Linux下读写UART串口的代码
Linux下读写UART串口的代码,从IBM Developer network上拿来的东西,操作比較的复杂,就直接跳过了,好在代码能用,记录一下- 两个实用的函数- //////////////// ...
- Linux 下挂在ntfs 硬盘
CentOS 7 下想要挂载NTFS的文件系统该怎么办呢? 我们需要一个NTFS-3G工具,并编译它之后在mount就可以了,就这么简单. 首先要进入官网下载NTFS-3G工具 http://www. ...
- linux 下使用opengl的glut库显示和旋转BMP图片
效果图: 这里显示的图和原图有明显的色差,目前猜测是opengl渲染时的颜色表顺序跟BMP文件里的颜色表顺序相反导致. BMP里应该是BGRBGRBRG... ,而opengl渲染时应该是按照RGBR ...
- 在Linux下如何用Shell脚本读写XML?现有一个config.xml(转)
在Linux下如何用Shell脚本读写XML?现有一个config.xml <?xml version="1.0" encoding="UTF-8"?&g ...
- linux下操作gpio寄存器的方法
一. 在驱动中: 1. 用的时候映射端口:ioremap; #define GPIO_OFT(x) ((x) - 0x56000000) #define GPFCON (*(volatile unsi ...
- linux下c通过虚拟地址映射读写文件的代码
在代码过程中中,把开发过程中比较好的一些代码片段记录起来,如下的代码内容是关于 linux下c通过虚拟地址映射读写文件的代码,应该对小伙伴有些好处.#include<stdio.h>#in ...
- linux下测试磁盘的读写IO速度-简易方法
linux下测试磁盘的读写IO速度-简易方法 参考资料:https://blog.csdn.net/zqtsx/article/details/25487185 一:使用hdparm命令 这是一个是用 ...
- Linux下按扇区读写块设备
本文介绍Linux下按扇区读写块设备(示例TF卡),实际应用是在Android系统上,主要方法如下: 1.找到sdcard的挂载点,在android2.1系统下应该为/dev/block/mmcblk ...
随机推荐
- Gym - 100625F Count Ways 快速幂+容斥原理
题意:n*m的格子,中间有若干点不能走,问从左上角到右下角有多少种走法. 思路:CountWay(i,j) 表示从 i 点到 j 点的种数.然后用容斥原理加加减减解决 #pragma comment( ...
- Sqoop 的优势
1.sqoop可以高效的可控的利用资源,比如它可以通过调整任务数,来控制任务的并发度,另外还可以配置数据库的访问时间等等 2.sqoop能自动的完成数据类型的映射与转换 3.它支持多种数据库,比如my ...
- 51nod 编辑距离 + 滚动数组优化
这道题一开始觉得增加和删除会移动字符串的位置很不好做 两个字符串dp状态一般是第一个前i个和第二个前j个 #include<cstdio> #include<algorithm> ...
- Intellij IDEA使用指南(持续更新)(转)
一.项目层面 1.Java开发工具IntelliJ IDEA导入项目 http://jingyan.baidu.com/article/a17d52852118ac8098c8f2c1.html 2. ...
- Split Shape by Plane in OpenCASCADE
Split Shape by Plane in OpenCASCADE eryar@163.com Abstract. Sometimes you want to split a shape by p ...
- java正則表達式总结
近期用到的正則表達式 因为近期在做一个android的新闻client.多次用到了正則表達式.因此总结下. 1.使用正則表達式获取Rss资源内的文章内容的图片url 由于在每条新闻浏览的listVie ...
- C#运算符小例子
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- windows WEB 高可用/可伸缩
windows NLB+ARR实现Web负载均衡高可用/可伸缩 基于IIS的ARR负载均衡 基于NLB负载均衡 这两篇分别分ARR 和 NLB基本配置,下面我们讲讲,如何组合使用,搭配成高可用/可 ...
- ubuntu下eclipse java ee首次打开提示找不到jdk的问题
最近想搭建一个本地服务器,方便写一些网络请求相关的demo,遂下载了eclipse ee版 ( IDEA证书好贵,暂时不想买-=-),下载---解压 一切正常,但是当在terminal下打开ecli ...
- uva 11248 最小割
Dinic 1 #include<iostream> #include<string> #include<algorithm> #include<cstdli ...