字符设备驱动应用---LED设备驱动实现
来源:互联网 发布:编程更改组策略 编辑:程序博客网 时间:2024/05/23 23:33
目标
本次实验将为开发上的LED灯实现驱动代码,应用程序可以通过ioctl系统调用控制LED灯的亮灭。
硬件资源
处理器
本人使用的开发板是讯为科技的iTop4412开发板,CPU是三星的4412,属于A9系列。
原理图
在开发板的原理图中,可以看到LED是连到GPL2_0引脚的,因此我们要控制LED,就要控制这个引脚。
寄存器物理地址转化成虚拟地址
翻看4412的芯片手册,可以找到控制led的I/O口的相关寄存器,我们需要对其进行设置。
不像裸机代码里,控制某个寄存器可以使用物理地址,在Linux系统里,用户用到的所有地址内核都认为是虚拟地址。内核看到一个地址以后把它当成虚拟地址,当内核需要读写这些地址时,需要经过内存管理子系统翻译成物理地址再读写。因此我们想要控制I/O寄存器,需要将寄存器的地址转化成虚拟地址,然后再通过虚拟地址控制这些寄存器。
内核中提供了如下宏将物理地址转化成虚拟地址:
ioremap(physaddr,size);
physaddr 是待转化的物理地址,size是物理地址的长度,返回虚拟地址。
内核还提供了若干函数给相关虚拟地址写数据:
void writel(unsigend int data,volatile void _iomem *addr);
代码实现
根据字符设备驱动,可以编写基于字符设备驱动模型的LED设备驱动,代码如下:
驱动代码
#include <linux/init.h>#include <linux/module.h>#include <linux/cdev.h>#include <linux/io.h>/*设备描述符*/struct cdev led_dev;/*设备号*/dev_t devno;/*控制寄存器地址*/#define LEDCON 0x11000100#define LEDDAT 0x11000104/*控制器转换后的虚拟地址*/unsigned int *led_con;unsigned int *led_dat; /*打开函数*/int led_open(struct inode *inode,struct file *file){ led_con = ioremap(LEDCON,4); led_dat = ioremap(lEDDAT,4); writel(0x00000001,led_con); return 0;}/*控制函数*/long led_ioctl(struct file *file,unsigned int cmd,unsigned long arg){ switch(cmd){ //点亮led case 1: writel(0x01,led_dat); break; //熄灭led case 0: writel(0x00000000,led_dat); break; default: return -EINVAL; } return 0;}/*关闭函数*/int led_close(struct inode *inode, struct file *file){ return 0;}/*文件操作函数集合*/struct file_operations led_ops = { .open = led_open, .unblocked_ioctl = led_ioctl, .release = led_close,};/*模块初始化*/static int led_init(void){ int ret; //初始化cdev cdev_init(&led_dev,&led_ops); //分配设备号 alloc_chrdev_region(&devno,0,1,"myled"); //注册驱动 ret = cdev_add(&led_dev,devno,1); return ret;}/*模块注销*/static void led_exit(void){ //注销设备结构 cdev_del(&led_dev); //注销设备号 unregister_chrdev_region(&led_dev,2);}/*遵循协议声明*/MODULE_LICENSE("GPL");/*模块安装和卸载函数*/module_init(led_init);module_exit(led_exit);
应用代码
#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <sys/ioctl.h>#include <stdio.h>#include <fcntl.h>int main(int arg,char *argv[]){ int fd; int i=0; if((fd=open("/dev/myled",O_RDWR))<0){ printf("App open file failed!\n"); return 0; } while(i++ < 4){ ioctl(fd,0); sleep(1); ioctl(fd,1); sleep(1); } return 0;}
0 0
- 字符设备驱动应用---LED设备驱动实现
- LED字符设备驱动
- led字符设备驱动
- 字符设备驱动---Led
- 字符设备驱动-LED驱动
- 字符设备实现控制led的驱动
- 字符设备实现控制led的驱动
- 字符设备驱动之LED
- 字符设备驱动点亮led
- 字符设备驱动----LED驱动程序
- Linux 字符设备驱动 LED
- 字符设备驱动--LED驱动程序
- Linux驱动开发-OK6410-LED字符设备驱动实现过程
- Linux字符设备驱动之LED驱动
- linux字符设备驱动-LED驱动
- 字符设备驱动之LED-混杂设备驱动(misc)
- linux设备驱动(一)---字符设备之led驱动
- Tiny6410 简单的LED字符设备驱动
- STM32 启动代码分析
- 单选框radio改变事件
- Spring MVC 核心配置文件
- This email address is not valid for use as an Apple ID.
- Android 自定义adapter(二)
- 字符设备驱动应用---LED设备驱动实现
- JavaWeb学习总结---JSP原理
- 解决ScrollView.setOnScrollChangeListener()API23以下不可用
- spring xml 定时任务
- s5pv210 IROM启动流程详解
- 如何让button保持点击状态
- windows下erlang环境搭建和创建第一个简单例子
- Android-幻灯片播放
- ORA-00604: 递归 SQL 级别 1 出现错误 ORA-01653: 表 SYS.AUD$ 无法通过 8192 (在表空间 SYSTEM 中) 扩展