博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
zedboard 驱动理解
阅读量:5260 次
发布时间:2019-06-14

本文共 5081 字,大约阅读时间需要 16 分钟。

1 驱动程序的编写

  驱动是LINUX开发的必经之路,应用层对底层的调用经过了库与内核,内核以下才是驱动层,当你在应用程序运行对底层的控制时,驱动程序为你的控制提供了接口,或者说是策略。

#include 
#include
#include
#include
#include

#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 addressunsigned long pwm_duty_addr = 0;	//pwm moulde's duty visual addressstatic 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 := 
/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

转载于:https://www.cnblogs.com/mfrbuaa/p/3995985.html

你可能感兴趣的文章
nginx修改内核参数
查看>>
C 筛选法找素数
查看>>
TCP为什么需要3次握手与4次挥手(转载)
查看>>
IOC容器
查看>>
Windows 2003全面优化
查看>>
URAL 1002 Phone Numbers(KMP+最短路orDP)
查看>>
web_day4_css_宽度
查看>>
electron入门心得
查看>>
格而知之2:UIView的autoresizingMask属性探究
查看>>
我的Hook学习笔记
查看>>
js中的try/catch
查看>>
寄Android开发Gradle你需要知道的知识
查看>>
简述spring中常有的几种advice?
查看>>
整理推荐的CSS属性书写顺序
查看>>
ServerSocket和Socket通信
查看>>
css & input type & search icon
查看>>
源代码的下载和编译读后感
查看>>
Kafka学习笔记
查看>>
Octotree Chrome安装与使用方法
查看>>
Windows 环境下基于 Redis 的 Celery 任务调度模块的实现
查看>>