//  led驱动  *myled.c*
//头文件
#include<linux/module.h> //最基本的文件,支持动态添加和卸载模块
#include<linux/kernel.h> //内核相关文件
#include<linux/fs.h> //包括文件操作相关struct的定义(struct file_operations和struct inode),MINOR、MAJOR的头文件
#include<linux/init.h> //初始化头文件
#include<linux/delay.h> //延时头文件
#include<asm/uaccess.h> //包括copy_to_user、copy_from_user等内核访问用户进程内存地址的函数定义
#include<asm/irq.h> //与处理器相关的中断
#include<asm/io.h> //包括ioremap、iowrite等内核访问IO内存等函数的定义
#include<asm/arch/regs-gpio.h> //与处理器相关的IO口操作
#include<asm/hardware.h> //与处理器相关的硬件
#include<linux/device.h> //包括device、class等结构的定义
#include<linux/slab.h> //包括kcalloc、kzalloc内存分配函数的定义
#include<linux/semaphore.h> //使用信号量必须的头文件
#include<linux/spinlock.h> //自旋锁 //定义变量
#define DEVICE "myled"
static struct class * myled_class;
static struct class * myled_class_dev;
int major;
volatile unsigned long * led_reg = NULL; //open函数
//这个函数一般包括硬件的相关设置、初始化等,比如GPIO的属性。不过zedboard的gpio在硬件定制中已经设置属性,故此函数不需要添加
static int myled_open(struct inode * inode,struct file * file)
{
  printk("Open LED_DRV\n");
  return ;
} //write函数
static ssize_t myled_write(struct file * file,const char _ _user * buf,size_t count,loff_t * ppos)
{
  int val;
  printk("Open MY_LED_write\n");
  copy_from_user(&val,buf,count);//从用户空间赋值数据到内核空间
  * led_reg = val;
  return ;
} //file_operations结构体
static struct file_operations myled_fops={
  .owner = THIS_MODULE,
  .open = myled_open,
  .write = myled_write,
};//注意这个分号不能少 //驱动初始化函数
static int myled_init(void)
{
  major=register_chrdev(,"myled",&myled_fops);
  myled_class = class_create(THIS_MODULE,"myled");
  myled_class_dev = device_create(myled_class,NULL,MKDEV(major,),NULL,"myled");
  led_reg = (volatile unsigned long *)ioremap(0x6a000000,);
  * led_reg = 0x55;
  printk("Open LED_init\n");
  return ;
}
//驱动卸载函数
static int myled_exit(void)
{
  unregister_chrdev(major,"myled");
  device_unregister(myled_class_dev);
  class_destroy(myled_class);
  iounmap(led_reg);
  printk("MY_LED_exit\n");
  return ;
} //驱动加载和卸载入口函数
module_init(myled_init);
module_exit(meled_exit);
MODULE_LICENSE("GPL");

驱动程序myled.c编写完成之后,需要对其进行编译,为了方便编译程序,需要编写一个Makefile文件

Makefile文件
KERN_SRC = /zedboard/linux-digilent-3.6-digilent-13.01
boj-m:=myled.o
all:
  make -C $ (KERN_SRC) M='pwd' modules
clean:
  make -C $ (KERN_SRC) M='pwd='clean
//在zedboard目录下新建driver文件夹,并将以上myled.c和Makefile文件放到该文件夹
mkdir driver
//进入driver目录,编译驱动,完成后会生成myled.ko驱动模块文件
cd driver
mak ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi-
//驱动设计完成后,需要将其添加到设备树中
//打开设备树文件,并添加以下大号斜黑体内容
gedit arch/arm/boot/dts/digileng-zed.dts
spi-speed-hz = <>;
spi-sclk-gpio = <&ps7_gpio_0 >;
spi-sdin-gpio = <&ps7_gpio_0 >;
};
myled{
compatible
= "dglnt,myled-1.00.a";
reg = <0x6a000000 0x10000>
;
};

};
};
//重新生成设备树dtb文件
 ./scripts/dtc/dtc -I dts -O dtb -o .../devicetree.dtb   arch/arm/boot/dts/digilent-zed.dts
//将生成的设备树文件复制到SD卡的boot分区,接下来就可以进行加载驱动测试

简单测试驱动:
1.将SD卡插入PC,在ubuntu下降生成的myled.ko文件复制到SD卡的rootfs分区的home目录,然后启动zedboard;
2.启动linaro后,在串口终端里进入home目录,并使用insmod命令加载驱动程序;
 cd /home/
insmod myled.ko
3.如果要卸载驱动,执行以下命令;
rmmod myled
应用程序调用驱动测试:
1.首先要编写一个简单的上位机测试程序ledtest.c,实现对LED的控制。
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<stdio.h> int main(int argc,char * * argv)
{
  int fd;
  int val = 0xAA;
  fd = open("/dev/myled",O_RDWR);
  if(fd<)
  {
    printf("error,can't open\n");
    return ;
  }
  write(fd,&val,);
  return ;
}

其中fd=open就是打开myled这个设备,val是输出到led的值,最后通过write将其值写入到led寄存器

2.将ledtest.c复制到driver目录下,并对其编译
arm-xilinx-linux-gnueabi-gcc   -o   ledtest   ledtest.c
3.编译完成后,同样将生成的ledtest可执行文件复制到SD卡的rootfs分区的home目录下
4.启动zedboard,在串口下执行如下命令即完成了驱动测试
cd   /home
insmod myled.ko
./ledtest
最后,总结一下编写驱动的一般步骤:

1.查看原理图,理解设备的工作原理;
2.定义主设备号;
3.实现初始化和卸载函数,实现对驱动的注册和注销;
4.设计所需要的文件操作,即file_operations结构;
5.实现所需的文件操作调用,如read,write函数等;
6.实现中断服务,用request_irq向内核注册(可选);
7.编写Makefile文件;
8.独立编译驱动,并修改设备树文件,最终使用insmod命令进行动态加载;或者直接把驱动编译进内核;
9.测试驱动,编写应用程序。



zedboard上首个驱动实践——Led的更多相关文章

  1. 超简单易用的 “在 pcduino 开发板上写 Linux 驱动控制板载 LED 的闪烁”

    版权声明:本文为博主原创文章,未经博主同意不得转载.转载联系 QQ 30952589,加好友请注明来意. https://blog.csdn.net/sleks/article/details/251 ...

  2. 平安银行在开源技术选型上的思考和实践 RocketMQ

    小结: 1. https://mp.weixin.qq.com/s/z_c5D8fvHaYvHSczm0nYFA 平安银行在开源技术选型上的思考和实践 平安银行·吴建峰 阿里巴巴中间件 3月7日 随着 ...

  3. 在Ubuntu18.04上安装Nvidia驱动

    拿到了一台新机子,带显卡的那种,当然是各种倒腾了!于是我又一天装了三遍机子来进行各种尝试熟悉配置啥的. 所以首先是在裸机上安装Nvidia驱动. 环境:Ubuntu18.04 刚安装完系统,当然是把软 ...

  4. Linux驱动实践:中断处理函数如何【发送信号】给应用层?

    作 者:道哥,10+年嵌入式开发老兵,专注于:C/C++.嵌入式.Linux. 关注下方公众号,回复[书籍],获取 Linux.嵌入式领域经典书籍:回复[PDF],获取所有原创文章( PDF 格式). ...

  5. [异常解决] ubuntu上安装JLink驱动遇到的坑及给后来者的建议

    一.前言 最近将整个电脑格式化,改成了linux操作系统 希望这样能让自己在一个新的世界探索技术.提升自己吧- win上的工具用多了,就不想变化了- 继上一篇<ubuntu上安装虚拟机遇到的问题 ...

  6. zedboard上移植OPENCV库

    zedboard上移植OPENCV库 之前做了很多移植OPENCV库的工作,但是需要包含的各种库,需要交叉编译,X264 ,JPGE ,FFMPGE等等 注意:在<嵌入式系统软硬件协同设计实战指 ...

  7. ZedBoard上运行linux系统的准备工作框架

    目标:ZedBoard上运行linux系统. 需要什么:图中上色部分. 应该做哪些工作:上色部分之前的所有步骤. 由上图得知,为了顺利在zedboard上构建嵌入式Linux操作系统,我们一般需要如下 ...

  8. I.mx6s上移植wm8960驱动(基于linux3.0.101版本)

    I.mx6s上移植wm8960驱动   此篇博文只记录移植的步骤,其他不做分析.首先上一张wm8960的硬件连接图: 1  上电操作   配置wm8960的上电脚,文件位置:arch/arm/mach ...

  9. OpenCV在Zedboard上的移植

    OpenCV编译 本文的前提是zynq交叉编译环境设置 下载opencv3.1.0源码,并解压 wget https://github.com/Itseez/opencv/archive/3.1.0. ...

随机推荐

  1. c++类成员函数后边加const是为什么?

    时间是让人猝不及防的东西,晴是有风阴时有雨,争不过朝夕,又念着往昔,偷走了青丝却留住一个你 #include <iostream> #include <string> usin ...

  2. msyql同步的时候报错 : 错误代码: 1293 Incorrect table definition;there can be only one TIMESTAMP column with CURRENT_TIMESTAMP in DEFAULT or ON UPDATE clause

    场景,两个不同服务器上的数据库,进行数据库同步 但是执行之后,提示报错 错误代码: 1293 Incorrect table definition; there can be only one TIM ...

  3. akka cluster singleton

    cluster singleton 需要注意的一点是 ClusterSingletonProxy 必须和 ClusterSingletonManager 一起工作 尝试过通过 path 来获得 sin ...

  4. ASP.NET MVC 4 (八) URL链接和Ajax帮助函数

    使用帮助函数创建链接 MVC提供一些帮助函数创建链接,这些函数根据路径映射表自动调整生成的URL: 说明 示例 输出结果 应用程序相对URL Url.Content("~/Content/S ...

  5. SpringBoot(十四)-- 整合Swagger2

    1.pom依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-s ...

  6. 【JS加密库】SJCL :斯坦福大学JS加密库

    斯坦福大学Javascript加密库简称SJCL,是一个由斯坦福大学计算机安全实验室创立的项目,旨在创建一个安全.快速.短小精悍.易使用.跨浏览器的JavaScript加密库. 斯坦福大学下载地址:h ...

  7. Bootstrap的Model源码详细注释 (转)

    原文: http://my.oschina.net/haogrgr/blog/323079?p=1 /* =============================================== ...

  8. 排序算法--冒泡排序(Bubble Sort)_C#程序实现

    排序算法--冒泡排序(Bubble Sort)_C#程序实现 排序(Sort)是计算机程序设计中的一种重要操作,也是日常生活中经常遇到的问题.例如,字典中的单词是以字母的顺序排列,否则,使用起来非常困 ...

  9. linux Email 体系

    大致了解了DNS与邮件服务器之间的关系后,接下来我们介绍邮件到底是如何传送到目的邮件主机的.下面我们分成“寄信”与“收信”两个主要的邮件服务器使用方式进行介绍.先说明关于“寄信”的部分.通常我们都是使 ...

  10. python的数据结构之栈

    栈是一种特殊的列表,栈内的元素只能通过列表的一端访问,这一端称为栈顶.栈被称为一种后入先出(LIFO,last-in-first-out)的数据结构. 由于栈具有后入先出的特点,所以任何不在栈顶的元素 ...