zedboard 驱动理解
1 驱动程序的编写
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <asm/io.h>
#define DEVICE_NAME "PWM_MOUDLE"
#define PWM_MOUDLE_PHY_ADDR 0x6CA00000 //This Address is based XPS 这个地址ISE EDK中分配的地址就是硬件的东东啦
/* 描述驱动程序的一些信息,不是必须的 */
MODULE_AUTHOR("Xilinx XUP"); // 驱动程序的作者
MODULE_DESCRIPTION("PWM moudle dirver"); // 一些描述信息
MODULE_VERSION("v1.0");
MODULE_LICENSE("GPL"); // 遵循的协议
static int pwm_driver_major;
static struct class* pwm_driver_class = NULL;
static struct device* pwm_driver_device = NULL; unsigned long pwm_fre_addr = 0; //pwm moulde's frequency visual address
unsigned long pwm_duty_addr = 0; //pwm moulde's duty visual address
static long frequency=0;
/*这个结构是字符设备驱动的核心*/
static struct file_operations pwm_driver_fops = {
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 在Export.h (c:\users\administrator\desktop\linux-3.3-digilent\include\linux):#define THIS_MODULE (&__this_module)*/
};
static ssize_t sys_pwm_frequency_set (struct device* dev, struct device_attribute* attr, const char* buf, size_t count)
{
long value = 0;
int i;
frequency=0;
outl(value, pwm_fre_addr); //close pwm moudle before we modfiy the frequency for (i = 0; i < count-1; i++){
frequency *= 10;
frequency += buf[i] - '0';
}
if(value>100000000) value=100000000;
value=100000000/frequency; // 100Mhz/frequency 100Mhz is set by XPS outl(value, pwm_fre_addr);
return count;
}
static ssize_t sys_pwm_duty_set (struct device* dev, struct device_attribute* attr, const char* buf, size_t count) //duty cycle
{
long value = 0;
int i;
//
outl(value, pwm_duty_addr); //close pwm moudle before we modfiy the duty cycle for (i = 0; i < count-1; i++){
value *= 10;
value += buf[i] - '0';
}
if (value>100) value=100;
value=100000000/frequency*value/100; if (value!= 0)
value = value | 0x80000000;
outl(value, pwm_duty_addr); return count;
}
static DEVICE_ATTR(pwm_frequency, S_IWUSR, NULL, sys_pwm_frequency_set);
static DEVICE_ATTR(pwm_duty, S_IWUSR, NULL, sys_pwm_duty_set);
/* 执行insmod xxx.ko时就会执行pwm_driver_module_init()函数 *
static int __init pwm_driver_module_init(void)
{
int ret;
/* 注册字符设备驱动程序
* 参数为主设备号、设备名字、file_operations结构;
* 这样,主设备号就和具体的file_operations结构联系起来了,
* 操作主设备为BUTTON_MAJOR的设备文件时,就会调用s3c24xx_buttons_fops中的相关成员函数
* BUTTON_MAJOR可以设为0,表示由内核自动分配主设备号
*/
pwm_driver_major=register_chrdev(0, DEVICE_NAME, &pwm_driver_fops);//内核注册设备驱动
if (pwm_driver_major < 0){
printk("failed to register device.\n");
return -1;
} pwm_driver_class = class_create(THIS_MODULE, "pwm_driver"); //创建PWM设备类
if (IS_ERR(pwm_driver_class)){
printk("failed to create pwm moudle class.\n");
unregister_chrdev(pwm_driver_major, DEVICE_NAME);
return -1;
}
pwm_driver_device = device_create(pwm_driver_class, NULL, MKDEV(pwm_driver_major, 0), NULL, "pwm_device"); //利用pwm_driver设备类创建一个pwm_device
if (IS_ERR(pwm_driver_device)){
printk("failed to create device .\n");
unregister_chrdev(pwm_driver_major, DEVICE_NAME);
return -1;
} ret = device_create_file(pwm_driver_device, &dev_attr_pwm_frequency); //在pwm_device设备中创建frequency与duty两个文件
if (ret < 0)
printk("failed to create pwm_frequency endpoint\n"); ret = device_create_file(pwm_driver_device, &dev_attr_pwm_duty);
if (ret < 0) //将pwm模块的物理地址映射到虚拟地址上 也就是EDK中分配的地址
printk("failed to create pwm_duty endpoint\n"); pwm_fre_addr = (unsigned long)ioremap(PWM_MOUDLE_PHY_ADDR, sizeof(u32));//To get Custom IP--PWM moudle's virtual address
pwm_duty_addr = pwm_fre_addr+4; printk(" pwm driver initial successfully!\n");
return 0;
}
/*
执行rmmod xxx.ko时就会执行pwm_driver_module_exit()函数
*/
static void __exit pwm_driver_module_exit(void)
{
device_remove_file(pwm_driver_device, &dev_attr_pwm_frequency);
device_remove_file(pwm_driver_device, &dev_attr_pwm_duty);
device_destroy(pwm_driver_class, MKDEV(pwm_driver_major, 0));
class_unregister(pwm_driver_class);
class_destroy(pwm_driver_class);
unregister_chrdev(pwm_driver_major, DEVICE_NAME);
printk("pwm module exit.\n");
}
/* 这两行指定驱动程序的初始化函数和卸载函数 */
module_init(pwm_driver_module_init);
module_exit(pwm_driver_module_exit);
2驱动程序的编译
makefile编写
ifneq ($(KERNELRELEASE),)
obj-m := pwm_driver.o
else
KERNEL_DIR := <YOUR_DIR>/ZedBoard/Kernel/Digilent-linux-3.3
PWD := $(shell pwd)
all:
$(MAKE) -C $(KERNEL_DIR) SUBDIRS=$(PWD) modules ARCH=arm
clean:
rm *.o *.ko *.mod.c
endif
<YOUR_DIR>/ZedBoard/Kernel/Digilent-linux-3.3 是你的路径
最后make 生成pwm_driver.ko 拷贝到zedboard文件系统上
3 驱动程序的测试
加载驱动
insmod pwm_driver.ko在/dev/ 下可以找到我们注册的设备 pwm_device
进入/sys/class/..目录
在zedboard 的shell上执行 echo 1000 > pwm_frequency
echo 50 > pwm_duty
zedboard 驱动理解的更多相关文章
- 基于Minifilter框架的文件过滤驱动理解
概述 Minifilter即File System Minifilter Drivers,是Windows为了简化第三方开发人员开发文件过滤驱动而提供的一套框架,这个框架依赖于一个称之为Filter ...
- DDD领域驱动理解
在理解领域驱动的时候,网上很多大谈理论的文章,这种对于初学者不是太容易接受.根据我自己的学习经历,建议按照如下几个步骤学习: 粗略的看一遍领域驱动的理论,做到心中有形,知道领域驱动是什么,解决什么问题 ...
- Binder驱动理解
1.Binder的三层架构 2.BC.BR的理解 通信模型 Binder协议包含在IPC数据中,分为两类: BINDER_COMMAND_PROTOCOL:binder请求码,以"BC_&q ...
- 宋宝华:Linux设备驱动框架里的设计模式之——模板方法(Template Method)
本文系转载,著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 作者: 宋宝华 来源: 微信公众号linux阅码场(id: linuxdev) 前言 <设计模式>这本经典 ...
- 安卓高级6 SnackBar
引言 文/李牧羊(简书作者) 原文链接:http://www.jianshu.com/p/2654e6bda3b1 著作权归作者所有,转载请联系作者获得授权,并标注"简书作者". ...
- 适合初学者的嵌入式Linux计划
俗话说万事开头难,刚开始的时候,你是否根本就不知如何开始,上网查资料被一堆堆新名词搞的找不到北,去图书馆看书也是找不到方向?又是arm,又是linux,又是uboot头都大了,不知道自己究竟从哪里开始 ...
- zedboard上首个驱动实践——Led
// led驱动 *myled.c*//头文件 #include<linux/module.h> //最基本的文件,支持动态添加和卸载模块 #include<linux/kernel ...
- 浅谈我对DDD领域驱动设计的理解
从遇到问题开始 当人们要做一个软件系统时,一般总是因为遇到了什么问题,然后希望通过一个软件系统来解决. 比如,我是一家企业,然后我觉得我现在线下销售自己的产品还不够,我希望能够在线上也能销售自己的产品 ...
- IDDD 实现领域驱动设计-理解领域和子域
上一篇:<IDDD 实现领域驱动设计-一个简单业务用例的回顾和理解> 在<实现领域驱动设计>第二章的前半部分内容中,提到领域和子域的概念,并且作者把这两者又进行了细致的区分,其 ...
随机推荐
- 关于Android 访问权限设置
我前几天在做同城交友网(www.niyuewo.com)与医药网(www.yiyaojing.com)时遇到的问题整理如下: Android开发应用程序时,如果应用程序需要访问网络权限,需要在 And ...
- 一款基于jQuery轮播切换焦点图,可播放多张图片
今天给大家分享一款基于jQuery轮播切换焦点图,可播放多张图片,在这个组件中,你可以任意指定8张图片,然后插件就会帮你自动生成缩略图,并且自动开始切换播放图片.当然,你也可以手动切换图片,只要点击缩 ...
- 关于禁止Android scrollView 因内容变化而自动滚动 android:descendantFocusability
出现这种情况是因为你让scrollview获得了焦点,所以它才会滚动.如果你百度了以后,你可能会发现有些博客会说让焦点停在固定的一个view中就可以了.这对于不存在刷新的页面确实是可以的,但是当你出现 ...
- docker镜像的操作
在主机上列出镜像 sudo docker images 每从Docker Hub下载一个镜像就会启动相对的创建一个容器 在镜像列表中看到三个重要的东西: 来自什么镜像源,例如ubuntu 每个镜像都有 ...
- URL请求过程
一.URL(Uniform Resource Locator)统一资源定位符,是可以从互联网上得到的资源的位置和访问方法的一种简洁表示,是互联网上标准资源的地址.互联网上的每一个文件都有一个唯一的UR ...
- Find the Clones
Find the Clones Time Limit: 5000MS Memory Limit: 65536K Total Submissions: 6365 Accepted: 2375 D ...
- struts2与cookie实现自动登录和验证码验证
主要介绍struts2与cookie结合实现自动登录 struts2与cookie结合时要注意采用.action 动作的方式实现cookie的读取 struts2的jar包 链接数据库文件 db.pr ...
- 【HTML5 3】《html5 开发精要与实例讲解》 step2 -- 结构元素 (待续)
主要内容:通过 一个博客网站和一个企业网站的制作 展示如何运用HTML5中的各种 结构元素,构建出一个语义清晰,结构分明的Web3.0时代的网站. 案例1:用HTML5中的结构元素构建一个博客网站 疑 ...
- CGFloat、CGPoint、CGSize和CGRect
CGFloat:是表示浮点数类型. CGPoint:表示二维坐标的点.通过x和y坐标定义.点表示位置值. CGSIZE:表示矩形的宽度和高度.通过宽度和高度来定义. CGRect: 表示矩形的位置和大 ...
- linux_机器信息查询
查看系统版本:[root@css-management ~]# lsb_release -aLSB Version: :core-4.0-amd64:core-4.0-noarch:graphics- ...