#include <linux/init.h>            // __init   __exit
#include <linux/module.h> // module_init module_exit #include <linux/fs.h> //file_operations #include <asm/uaccess.h> //copy_from_user copy_to_user #include <mach/regs-gpio.h>
#include <mach/gpio-bank.h> #include <asm/string.h> #include <linux/ioport.h> //request_mem_region
#include <asm/io.h> //ioremap #define S5PV210_PA_GPIOJ0CON 0xe0200240 volatile unsigned int *rGPJ0CON = NULL;
volatile unsigned int *rGPJ0DAT = NULL; static int led_open(struct inode *inode, struct file *file);
ssize_t led_read(struct file *file, char __user *user, size_t count, loff_t *loff);
ssize_t led_write(struct file *file, const char __user *user, size_t count, loff_t *loff);
static int led_release(struct inode *inode, struct file *file); static int led_major = -;
static char kbuf[] = {};
static const struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = led_open,
.read = led_read,
.write = led_write,
.release = led_release,
}; int led_open(struct inode *inode, struct file *file)
{
printk(KERN_INFO "led_open successful\n");
return ;
} ssize_t led_read(struct file *file, char __user *user, size_t ucount, loff_t *loff)
{
printk(KERN_INFO "led_read successful\n");
if (copy_to_user(user,kbuf , ucount))
{
printk(KERN_INFO "copy_to_user fail\n");
return -EINVAL;
}
printk(KERN_INFO "copy_to_user successful\n");
return strlen(kbuf);
} ssize_t led_write(struct file *file, const char __user *user, size_t ucount, loff_t *loff)
{
printk(KERN_INFO "led_write successful\n");
memset(kbuf,,sizeof(kbuf));
if (copy_from_user(kbuf, user, ucount))
{
printk(KERN_INFO "copy_from_user fail\n");
return -EINVAL;
} if(!strcmp(kbuf,"on"))
{
*rGPJ0CON &=0xff000fff;
*rGPJ0CON |=0x00111000;
*rGPJ0DAT &=~((0x01<<)|(0x01<<)|(0x01<<));
}
else if(!strcmp(kbuf,"off"))
{
*rGPJ0CON &=0xff000fff;
*rGPJ0CON |=0x00111000;
*rGPJ0DAT |=((0x01<<)|(0x01<<)|(0x01<<));
}
return ucount;
printk(KERN_INFO "copy_from_user successful\n");
} int led_release(struct inode *inode, struct file *file)
{
printk(KERN_INFO "led_release successful\n");
return ;
} // 模块安装函数
static int __init chrdev_init(void)
{
int ret = -;
printk(KERN_INFO "chrdev_init successful\n"); if ((led_major = register_chrdev (, "led_dev", &led_fops)) < )
{
printk(KERN_WARNING "led_module.c: Failed to register character device.");
ret = -EINVAL;
}
if (request_mem_region(S5PV210_PA_GPIOJ0CON, , "GPIOJ0CON") == NULL)
{
printk(KERN_WARNING "failed to get memory region\n");
ret = -ENOENT;
goto err_req;
}
rGPJ0CON = ioremap(S5PV210_PA_GPIOJ0CON,);
if (rGPJ0CON == NULL)
{
printk(KERN_WARNING "fail to ioremap() region\n");
ret = -ENOENT;
goto err_map;
}
rGPJ0DAT = rGPJ0CON+;
err_map:
iounmap(rGPJ0CON); err_req:
release_mem_region(S5PV210_PA_GPIOJ0CON,); return ;
} // 模块卸载函数
static void __exit chrdev_exit(void)
{
iounmap(rGPJ0CON);
release_mem_region(S5PV210_PA_GPIOJ0CON,);
unregister_chrdev(led_major,"led_dev");
printk(KERN_INFO "chrdev_exit successful\n"); } module_init(chrdev_init);
module_exit(chrdev_exit); // MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL"); // 描述模块的许可证
MODULE_AUTHOR("musk"); // 描述模块的作者
MODULE_DESCRIPTION("module test"); // 描述模块的介绍信息
MODULE_ALIAS("alias xxx"); // 描述模块的别名信息

上述程序是led非常简陋,手动注册的字符驱动代码。真正的内核驱动不是这么简单!

一. 关于字符设备注册,静态虚拟地址请查看上篇文章《注册LED字符驱动设备(静态映射)》

二. 关于动态映射

2.1. 虚拟地址到物理地址的映射可以多对1,但是不能1对多,故可以多个动态虚拟地址和一个静态虚拟地址同事指向同一个物理地址寄存器。

2.2. 向内核申请&释放需要映射的内存资源

2.2.1. 由于soc所有的资源都是内核管理的,使用时应先申请,这样如果资源以及被其他驱动使用了则申请不到。这样可以很好的避免一个资源在两个驱动中同时被使用造成错误。

2.2.2. 申请函数request_mem_region

#define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n), (name), 0)

a. 参数start 是要申请资源的物理地址

b. 参数n是要申请资源的大小(单位是byte)

c. 参数name是给申请的资源起个别名

d. 成功返回非NULL失败返回NULL

2.2.2. 申请函数release_mem_region

#define release_mem_region(start,n)__release_region(&iomem_resource, (start), (n))

a. 参数start 是要申请资源的物理地址

b. 参数n是要申请资源的大小(单位是byte)

2.2.3. IO内存映射/去映射

2.2.3.1. release_mem_region申请了IO资源,接下来就是进行物理地址到虚拟地址的映射

2.2.3.2. IO内存映射函数:ioremap(cookie,size)

#define ioremap(cookie,size)		__arm_ioremap(cookie, size, MT_DEVICE)

a. 参数cookie是映射资源的物理地址

b. 参数size是映射的大小

2.2.3.3. IO内存映射函数:iounmap(cookie)

#define iounmap(cookie)__iounmap(cookie)

a. 参数cookie是映射资源的物理地址

三. 应用层调用内核

3.1. 相关代码如下

#include <stdio.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> #include <string.h> #define DEVFILE "/dev/led_dev" int main(void)
{
char buf[] = {};
int fd = -;
if((fd =open(DEVFILE, O_RDWR))<)
{
perror("open");
return -;
}
printf("open successful fd = %d\n",fd);
if(write(fd, "on", strlen("on"))<)
{
perror("write");
return -;
}
sleep();
memset(buf,,sizeof(buf));
if(read(fd, buf, )<)
{
perror("read");
return -;
}
printf("read data = %s\n",buf); if(write(fd, "off", strlen("off"))<)
{
perror("write");
return -;
}
sleep();
memset(buf,,sizeof(buf));
if(read(fd, buf, )<)
{
perror("read");
return -;
}
printf("read data = %s\n",buf); close(fd);
return ;
}

旧接口注册LED字符驱动设备(动态映射)的更多相关文章

  1. 旧接口注册LED字符驱动设备(静态映射)

    #include <linux/init.h> // __init __exit #include <linux/module.h> // module_init module ...

  2. 新接口注册LED字符驱动设备

    #include <linux/init.h> // __init __exit #include <linux/module.h> // module_init module ...

  3. 嵌入式Linux学习笔记(三) 字符型设备驱动--LED的驱动开发

    在成功构建了一个能够运行在开发板平台的系统后,下一步就要正式开始应用的开发(这里前提是有一定的C语言基础,对ARM体系的软/硬件,这部分有疑问可能要参考其它教程),根据需求仔细分解任务,可以发现包含的 ...

  4. Linux内核驱动学习(三)字符型设备驱动之初体验

    Linux字符型设备驱动之初体验 文章目录 Linux字符型设备驱动之初体验 前言 框架 字符型设备 程序实现 cdev kobj owner file_operations dev_t 设备注册过程 ...

  5. linux驱动初探之字符驱动

    关键字:字符驱动.动态生成设备节点.helloworld linux驱动编程,个人觉得第一件事就是配置好平台文件,这里以字符设备,也就是传说中的helloworld为例~ 此驱动程序基于linux3. ...

  6. 嵌入式linux驱动开发之点亮led(驱动编程思想之初体验)

    这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...

  7. 基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(一)之miscdevice和ioctl

    基于OMAPL138的Linux字符驱动_GPIO驱动AD9833(一)之miscdevice和ioctl 0. 导语 在嵌入式的道路上寻寻觅觅很久,进入嵌入式这个行业也有几年的时间了,从2011年后 ...

  8. fl2440 platform总线led字符设备驱动

    首先需要知道的是,设备跟驱动是分开的.设备通过struct device来定义,也可以自己将结构体封装到自己定义的device结构体中: 例如:struct platform_device: 在inc ...

  9. linux设备驱动归纳总结(三):1.字符型设备之设备申请【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-59416.html linux设备驱动归纳总结(三):1.字符型设备之设备申请 操作系统:Ubunru ...

随机推荐

  1. @Component和@Bean以及@Autowired、@Resource

    1. 有这么一个故事,从xml配置文件的bean说起   Spring用xml配置文件的时候(不知道阅读这篇文章的你用没用过,我用过一段时间,那是黑暗伤痛的回忆QQQ),一个xml配置文件里面有很多个 ...

  2. 原创——Nginx基础

    Nginx基础 一.Nginx概述: Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器. Nginx ...

  3. SpringBoot拦截器和 Servlet3.0自定义Filter、Listener

    官方文档译文 Spring Boot 包括对嵌入式Tomcat,Jetty和Undertow服务器的支持.大多数开发人员使用适当的“Starter”来获取完全配置的实例.默认情况下,嵌入式服务器在 p ...

  4. echarts画柱状图

    drawLeftHistogram(){ let Histogram = echarts.init(document.getElementById('data-left-bottom-table-wr ...

  5. [CF1093E]Intersection of Permutations:树套树+pbds

    分析 裸的二维数点,博主用树状数组套平衡树写的,顺便pbds真好用. Update on 2018/12/20:再解释一下为什么是二维数点,第一维是\(la \leq i \leq ra\),第二维是 ...

  6. CSS3实现图片黑白滤镜居中,hover缩放遮罩的效果

       hover: 在前端开发中经常会遇到项目展示,往往会采用卡片方式来描述.众多网站中,普遍采用CSS3的scale()方法来实现交互. 本文即是利用纯CSS实现图片居中缩放,此类方法各大网站均有应 ...

  7. CS2001 VS编译错误

    Severity Code Description Project File Line Suppression State Error CS2001 Source file 'C:\Workspace ...

  8. C#配置IIS站点

    一.源码特点       1.  一些基于ASP.NET应用产品,在用户环境中都无可避免的涉及到部署到目标环境的应用服务器上,而配置站点是此过程的核心步骤,此源码对过程进行了高度封装,从创建IIS所需 ...

  9. UEFI手札

    基于Intel TianoCore衍生的EDK-II诞生的UEFI,用来取代Legacy BIOS. INF文件 Module Information File,模块描述文件.Module可以是可执行 ...

  10. sh/bash/csh/Tcsh/ksh/pdksh等shell的区别

    w shell confusion..what is diff between bash, ksh, csh, tcsh..??  http://www.linuxquestions.org/ques ...