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 实现领域驱动设计-一个简单业务用例的回顾和理解> 在<实现领域驱动设计>第二章的前半部分内容中,提到领域和子域的概念,并且作者把这两者又进行了细致的区分,其 ...
随机推荐
- JqGrid TreeView使用
1.前端 <script src="@Url.Content("~/Scripts/jquery/jquery-1.9.0.min.js")" type= ...
- iOS本机生成证书请求文件流程
第一步:苹果机上打开“Finder”,选择“应用程序”,双击打开“实用工具” 第二步:在“实用工具”中,选“择钥匙串访问”,双击打开 第三步: “钥匙串访问”打开,看到如下页面 第四步:选择菜单中“钥 ...
- Socket 之 API函数介绍
1.创建套接字──socket() 应用程序在使用套接字前,首先必须拥有一个套接字,系统调用socket()向应用程序提供创建套接字的手段,其调用格式如下: SOCKET PASCAL FAR soc ...
- IOS 应用中从竖屏模式强制转换为横屏模式
在 iPhone 应用里,有时我们想强行把显示模式从纵屏改为横屏(反之亦然),CocoaChina 会员 “alienblue” 为我们提供了两种思路 第一种:通过人为的办法改变view.transf ...
- jQery无缝滚动效果
思路: 赋值所有li,添加到ul末尾,重新计算ul宽度 每次移动一个固定的值,当超出一半时,将ul拉回原位 以下代码 <!DOCTYPE html> <html> <he ...
- [课程相关]homework-09
零.前言 这次的作业比较特殊,有两种做法.由于我对网页很熟悉,所以选择网页. 细节不赘述,下面写一下这次作业的几个亮点. 一.亮点 最大的亮点就是这个页面是纯客户端的,没有服务端.也就是说所有功能都是 ...
- Oracle基础 TO_CHAR函数参考(转)
Postgres 格式化函数提供一套有效的工具用于把各种数据类型(日期/时间,int,float,numeric)转换成格式化的字符串以及反过来从格式化的字符串转换成原始的数据类型. 注意:所有格式化 ...
- Java Script基础(四) BOM模型
一.BOM模型 BOM模型(Browser Object Model),也称为文档对象模型,它包含浏览器相关的属性和方法,例如操作,前进后退按钮,控制地址栏,关闭浏览器窗口,打开新窗口等等.它包含的对 ...
- linux_jvm_jhat_dump内存分析
jhat命令 jhat命令 -- Java Head Analyse Tool 用途:是用来分析java堆的命令,可以将堆中的对象以html的形式显示出来,包括对象的数量,大小等等,并支持对象查询 ...
- [Android]天气App 2 项目搭建
对于天气App,为了简化一些功能,暂时模仿MUUI系统提供的那个App. 本项目需要引入本人经常使用的一个工具库DroidTool,这个是本人根据工作中,收集到一些工具类,下载地址. ...