linux使用i/o内存访问外设
一。linux中访问外设的方法.
1.IO端口(IO port)
linux系统给外设分配不同的端口号,linux利用端口号来访问设备(驱动) (cpu x86)
cpu访问外设通过端号,访问通过地址
gec@ubuntu:/mnt/hgfs/tea/demo2$ cat /proc/ioports
0000-0cf7 : PCI Bus 0000:00
0000-001f : dma1
0020-0021 : pic1
0040-0043 : timer0
0050-0053 : timer1
0060-0060 : keyboard
0064-0064 : keyboard
0070-0071 : rtc0
0080-008f : dma page reg
00a0-00a1 : pic2
00c0-00df : dma2
00f0-00ff : fpu
0170-0177 : 0000:00:07.1
0170-0177 : ata_piix
2.IO内存 (IO mem) ---> ARM/MPIS
cpu访问外设的方法和访问内存方法都是一样,都是根据地址来方问。
外设(GPIO,ADC,WDT)都内存一样,是统一编址。
二。LINUX中IO内存的使用
思想:申请IO内存区-->动态是映射--->使用虚拟地址--> 解除动态映射击--->释放IO内存区。
1.IO内存的申请
struct resource *request_mem_region(resource_size_t start,resource_size_t n,const char *name)
参数值:
start-->资源的内存区的开始地址(物理地址)
n ----->物理内存区的大小
name --->自定义内存区的名字 cat /proc/iomem
返回值:
struct resource * -->申请到的资源
NULL--->申请失败
2.释放IO内存
void release_mem_region(resource_size_t start,resource_size_t n)
例:
struct resource *ledp=request_mem_region(OxE0200280,8,"gpj2_led");
----------------------------------------------------------------------------
3.IO内存的动态映射
void __iomem * ioremap (unsigned long phys_addr, unsigned long size)
参数:
unsigned long phys_addr--》需要映射的物理内存的地址(开始地址)
unsigned long size -->需要映射的物理内存大小
返值:
void __iomem * --->映射后虚拟地址(开始地址)
NULL --->失败
4。IO内存动态映射解除
void iounmap(void *addr)
void *addr--->映射后的虚拟地址
例:
#define OxE0200280 GPJ2CON_PA
unsigned int *GPJ2CON_VA =ioremap(GPJ2CON_PA,8);
unsigned int *GPJ2DAT_VA =GPJ2CON_VA+1;
iounmap(GPJ2CON_VA);
-------------------------------------------------
5.访问虚拟地址的函数(读写)
1.
unsigned int ioread32(void __iomem *addr)
void __iomem *addr--->虚拟地址
unsigned int ---》数据
void iowrite32(u32 b, void __iomem *addr);
例:
unsigned int a=ioread(GPJ2CON_VA);
a &= ;
iowrite32(a,GPJ2CON_VA)
2.
static inline u32 readl(const volatile void __iomem *addr)
static inline void writel(unsigned int b, volatile void __iomem *addr)
3.
static inline u32 __raw_readl(const volatile void __iomem *addr)
static inline void __raw_writel(u32 v, volatile void __iomem *addr)
实例:LED字符设备的驱动模块、
#include <linux/module.h>
#include <linux/kernel.h>
#include<linux/cdev.h>
struct cdev chrdev3;
unsigned int TestMajor=0;
unsigned int TestMinor=0;
#define *** GPJ*CON_PA
#define *** GPJ*DAT_PA
unsigned int *GPJ2CON_VA;
dev_t dev_no;
int testopen(struct inode *inode, struct file *file)
{
//LED输出
printk("led init \n");
}
int testclose (struct inode *inode, struct file *file);
{
printk("close");
return 0;
}
ssize_t testwrtie(struct file *, char __user *usr, size_t len, loff_t *off)
{
char buf[12];
copy_from_user(buf,usr,);
buf[12];
//if(buf[]=='1')
// led点明
printk(,buf);
}
ssize_t testread(struct file *, char __user *usr, size_t len, loff_t *);
{
char buf='r';
read_led;
copy_to_user(usr,buf,);
}
struct file_operations fops= --->结构体初始化 .---???????????????
{ .owner=THIS_MODULE,
.open=testopen,
.write=testwrite,
.release=testclose,
}
static int __init test_init(void) //入口函数
{
printk("hello world!\n"); //相当于printf()
int ret;
dev_no =MKDEV(TestMajor,TestMinor)
if(dev_no>0)
{
ret=register_chrdev_region(dev_no, 1,"chrdev_test");//静态注册设备号
}
else //动态申请设备号
{
alloc_chrdev_region(&dev_no,TestMinor, 1,"chrdev_test");
}
if(ret<0)
{
return ret;
}
cdev_init(&chrdev3,&fops);
cdev.owner=THIS_MODULE;
cdev_add(&chrdev3,dev_no,1);
request_mem_region();
GPJ2CON_VA =ioremap(GPJ2CON_PA,8);
GPJ2DAT_VA =GPJ2CON_VA+1;
return 0;
}
static void __exit test_exit(void) //出口函数
{
unregister_chrdev_region(dev_no, 1);
cdev_del(&chrdev3);
}
module_init(test_init); //驱动的入口 #insmod *.ko
module_exit(test_exit); //驱动的出口 #rmmod *.ko
//#modinfo *.ko 可以查看module的信息
MODULE_AUTHOR("fbx@GEC");
MODULE_DESCRIPTION("the first module of drivers");
MODULE_LICENSE("GPL");
MODULE_VERSION("V1.0");
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/cdev.h>
#include<linux/fs.h>
#include<linux/kdev_t.h>
#include<linux/types.h>
#include<linux/uaccess.h>
#include<linux/string.h>
#include<linux/ioport.h>
#include<asm/io.h> #define GPJ2CON_PA 0xe0200280
#define GPJ2DAT_PA 0xe0200280
unsigned int *GPJ2CON_VA;
unsigned int *GPJ2DAT_VA;
struct cdev chrdev;
struct resource *res;
unsigned int TestMajor=;
unsigned int TestMinor=;
dev_t dev_no;
int ret; int testopen(struct inode *inode,struct file *file)
{
unsigned int a = ioread32(GPJ2CON_VA);
a |= 0x1111;
iowrite32(a,GPJ2CON_VA);
printk("cdev init\n");
return ; }
ssize_t testwrite(struct file *file, const char __user *usr, size_t len, loff_t *off)
{
unsigned int a; copy_from_user(&a,usr,len);
iowrite32(a,GPJ2DAT_VA); }
ssize_t testread(struct file *file, char __user *usr, size_t len, loff_t *off)
{
unsigned int a = ioread32(GPJ2DAT_VA);
copy_to_user(usr,&a,len); }
int testrelease(struct inode *inode, struct file *file)
{
printk("close\n");
return ; } struct file_operations fops=
{
.owner=THIS_MODULE,
.open = testopen,
.write = testwrite,
.read = testread,
.release = testrelease,
};
static int __init test_init(void)
{
dev_no = MKDEV(TestMajor,TestMinor);
if(dev_no>)
{
ret = register_chrdev_region(dev_no,,"chrdev_test");
}
else
{
alloc_chrdev_region(&dev_no,,,"chrdev_test");
}
if(ret<)
{
return ret;
}
cdev_init(&chrdev,&fops);
chrdev.owner=THIS_MODULE;
cdev_add(&chrdev,dev_no,);
res = request_mem_region(GPJ2CON_PA,,"gpj2_led");
GPJ2CON_VA = ioremap(GPJ2CON_PA,);
GPJ2DAT_VA = GPJ2CON_VA + ;
return ;
} static int __exit test_exit(void)
{
unregister_chrdev_region(dev_no,);
cdev_del(&chrdev);
iounmap(GPJ2CON_VA);
release_mem_region(GPJ2CON_PA,);
return ;
} module_init(test_init);
module_exit(test_exit); MODULE_AUTHOR("FENG");
MODULE_DESCRIPTION("the first module of char drivers");
MODULE_LICENSE("GPL");
MODULE_VERSION("V1.0");
test.c 使一盏led循环点灭
#include<stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <string.h> int main()
{
unsigned int ledconfig;
char buf1[];
int fd = open("/dev/chrdev_test",O_RDWR);
if(fd<)
perror("open() error!\n");
bzero(buf1,);
while()
{
read(fd,&ledconfig,);
ledconfig ^=0x1;
write(fd,&ledconfig,);
sleep();
}
}
linux使用i/o内存访问外设的更多相关文章
- Linux内核访问外设I/O--动态映射(ioremap)和静态映射(map_desc) (转载)
[转](转)Linux内核访问外设I/O资源的方式-静态映射(map_desc)方式 Linux内核访问外设I/O资源的方式 Author: Dongas Date: 08-08-02 我们知道默认外 ...
- Linux驱动技术(二) _访问I/O内存
ARM是对内存空间和IO空间统一编址的,所以,通过读写SFR来控制硬件也就变成了通过读写相应的SFR地址来控制硬件.这部分地址也被称为I/O内存.x86中对I/O地址和内存地址是分开编址的,这样的IO ...
- [转载]linux段页式内存管理技术
原始博客地址: http://blog.csdn.net/qq_26626709/article/details/52742470 一.概述 1.虚拟地址空间 内存是通过指针寻址的,因而CPU的字长决 ...
- java语言:Linux与JVM的内存关系分
在一些物理内存为8g的服务器上,主要运行一个Java服务,系统内存分配如下:Java服务的JVM堆大小设置为6g,一个监控进程占用大约 600m,Linux自身使用大约800m.从表面上,物理内存应该 ...
- C++成员变量内存对齐问题,ndk下非对齐的内存访问导致BUS_ADRALN
同样的代码,在vs下运行正常,在android ndk下却崩溃: signal 7(SIGBUS),code 1 (BUS_ADRALN),fault addr 0xe6b82793 Func(sho ...
- 转: 关于Linux与JVM的内存关系分析
转自: http://tech.meituan.com/linux-jvm-memory.html Linux与JVM的内存关系分析 葛吒2014-08-29 10:00 引言 在一些物理内存为8g的 ...
- Linux按照CPU、内存、磁盘IO、网络性能监测
系统优化是一项复杂.繁琐.长期的工作,优化前需要监测.采集.测试.评估,优化后也需要测试.采集.评估.监测,而且是一个长期和持续的过程,不 是说现在优化了,测试了,以后就可以一劳永逸了,也不是说书 ...
- Linux 下增大tomcat内存
我的服务器的配置: # OS specific support. $var _must_ be set to either true or false. JAVA_OPTS="-Xms10 ...
- Linux内核高端内存 转
Linux内核地址映射模型x86 CPU采用了段页式地址映射模型.进程代码中的地址为逻辑地址,经过段页式地址映射后,才真正访问物理内存. 段页式机制如下图. Linux内核地址空间划分 通 ...
随机推荐
- 98、vue.js简单入门
本篇导航: 介绍与安装 vue常用指令 一.介绍与安装 vue是一套构建用户界面的JAVASCRIPT框架.与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用.Vue 的核心库只关注视图层, ...
- MVC编程实例----简易电子商务网站(一)
一.总体概览.规划 本文将会创建一个基本的电子商务网站.由于电子商务网站的基本功能都是差不多的,此处省去了需求分析等工作,直接总结出结论.分为4个基本功能: 商品浏览 会员功能 购物车 订单结账 其中 ...
- 一步一步从原理跟我学邮件收取及发送 5.C语言的socket示例
说到 C 语言版本的程序,首先要解决的问题就是兼容性. 作为 20 年开发有 10 多年是在服务端的程序员,我深刻地感受到服务端平台的两极分化之严重,linux 派对 windows 那是超级的不屑一 ...
- 如何利用vue和php做前后端分离开发?
新手上路,前端工程师,刚毕业参加工作两个月,上面让我用vue搭建环境和php工程师一起开发,做前后端分离,然而我只用过简单的vue做一些小组件的经验,完全不知道怎样和php工程师配合,ps: php那 ...
- Java XML 序列化和反序列化
Utils 类: import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWr ...
- 直接请求转发(Forward)和间接请求转发(Redirect)两种区别?
用户向服务器发送了一次HTTP请求,该请求肯能会经过多个信息资源处理以后才返回给用户,各个信息资源使用请求转发机制相互转发请求,但是用户是感觉不到请求转发的.根据转发方式的不同,可以区分为直接请求转发 ...
- 20165206学习基础和C语言基础调查
- 技能 我的一项可以拿的出手的技能是萨克斯.但不敢说有多厉害,更不敢说比大多数人更好,只能说是还可以.我学萨克斯有5年左右的时间吧,这5年里印象最深刻的还是前两年.前两年主要是基础训练.我从最基础的 ...
- Django类方式写view
问题: Django官方教程中都是通过def函数方式来写view,如何通过类方式写view以及为何要通过类方式写view? 那,如何解决这个问题? 用户访问浏览器,一般两种方式,get获取网页和pos ...
- Servlet--ServletConfig接口,GenericServlet类
ServletConfig接口 定义:public interface ServletConfig 这个接口定义了一个对象, 通过这个对象, Servlet 引擎配置一个 Servlet 并且允许 S ...
- Windows 产品激活状态、密钥等信息查看
目前,大多PC都是预装了微软家的桌面级系统 Windows ,这也算是微软一大得意之作.可是 Windows 产品可不是免费的,是要 $ 的.可能在中国,大多数系统可能是盗版过来的,像当年的雨林木风( ...