一、驱动源码

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
//#include <asm/irq.h>
//#include <mach/regs-gpio.h>
//#include <mach/hardware.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/miscdevice.h>
#include <linux/types.h>
#include <linux/ioctl.h> #include <linux/cdev.h> #define led_pin 0
#define DEVICE_NAME "mydriver"
//#define DEVICE_NAME "dragino2:red:wlan"
static int MYDRIVER_Major = ; static int mydriver_open(struct inode *inode,struct file *filp)
{
printk("My Driver Open Called!\n");
return ;
} static int mydriver_release(struct inode *inode,struct file *filp)
{
printk("My Driver Release Called!\n");
return ;
} static int mydriver_read(struct file *filp,char *buf,size_t count, loff_t *f_pos)
{
printk("My Driver Read Called!\n");
return ;
} static int mydriver_write(struct file *filp,char *buf,size_t count, loff_t *f_pos)
{
printk("My Driver Writet Called!\n");
return ;
} static long op_mydriver_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
switch(cmd) {
case :
gpio_set_value(led_pin, );
break;
case :
//if (arg > 2) {
// return -EINVAL;//判读用户的参数是否有误
//} //gpio_set_value(led_pin, !cmd);//用户选定的LED并设置值
gpio_set_value(led_pin, );
//printk(DEVICE_NAME": %d %d\n", arg, cmd);
break;
default:
return -EINVAL;
}
return ;
} /*
static int mydriver_probe()
{
printk("My Driver Probe Called!\n");
} static int mydriver_remove()
{
printk("My Driver Remove Called!\n");
}
*/ //??
/*
static struct device_driver mydriver_driver = {
//.driver = {
// .name = DEVICE_NAME,
// .owner = THIS_MODULE,
//},
.name = DEVICE_NAME,
.probe = mydriver_probe,
.remove = mydriver_remove,
};
*/ static struct file_operations mydriver_fops =
{
.owner = THIS_MODULE,
.open = mydriver_open,
.release = mydriver_release,
.read = mydriver_read,
.write =mydriver_write,
.unlocked_ioctl = op_mydriver_unlocked_ioctl,
}; static struct miscdevice mydriver_miscdev =
{
.minor = MISC_DYNAMIC_MINOR,//由系统自动配置,次设备号
.name = DEVICE_NAME,
.fops = &mydriver_fops,
}; static int __init mydriver_init(void)
{
int ret;
//ret = ath79_register_leds_gpio(0,DEVICE_NAME,&mydriver_driver);
//ret = driver_register(&mydriver_driver);
ret = gpio_request(led_pin,"LED");//申请IO引脚gpio_request
//ret = gpio_request_one(led_pin,10,"LED");
ret = register_chrdev(MYDRIVER_Major, DEVICE_NAME, &mydriver_fops);
if (ret) {
printk("request GPIO for led error\n");
return ret;
}
gpio_direction_output(led_pin, );
//gpio_set_value(led_pin, 1); ret = misc_register(&mydriver_miscdev);//创建设备节点
if (ret) {
printk("misc_unregister error\n");
return ret;
}
printk("MY DRIVER MODULE INIT\n");
return ;//没有这句,那默认返回值是多少? } static void __exit mydriver_exit(void)
{
int ret; //gpio_free(led_pin);
unregister_chrdev(MYDRIVER_Major, DEVICE_NAME);
ret = misc_deregister(&mydriver_miscdev);
if (ret)
{
printk("misc_register error\n");
return ret;
} printk("My DRIVER MODULE EXIT\n");
} module_init(mydriver_init);
module_exit(mydriver_exit); MODULE_AUTHOR("www.txmcu.com");
MODULE_DESCRIPTION("My Driver");
MODULE_LICENSE("GPL");

说明:

1、在驱动初始化及驱动退出函数中,

static int __init mydriver_init(void){...}

static void __exit mydriver_exit(void){...}

双下划线表示模块在内核启动和关闭时自动运行和退出,注意不是单下滑线。

2、该设备注册用杂项(misc)设备方式进行注册,如果一个字符设备驱动要驱动多个设备,那么它就不应该用misc设备来实现。

3、led管脚的选择,参考《AR9331.pdf》的第17页,选择led的管脚为LED0即GPIO0,所以

#define led_pin 0

该管脚为高电平点亮led灯,低电平为熄灭led灯。

4、该驱动实现对led的控制是在以下函数中:

static long op_mydriver_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg){...}

以下两个函数实现对led管脚设置高低电平:

gpio_set_value(led_pin, 0);

gpio_set_value(led_pin, 1);

5、初始化要return 0,否则加载驱动时,会输出很多乱起八糟的东西。

二、驱动编译

1、Kconfig文件的书写

config DRIVER-MODEL
tristate "Custom GPIO-based led driver"
depends on GENERIC_GPIO
select SPI_GPIO //this option would also be choosed
help
This is an led driver to register
GPIO lines.
The devices will be exposed to userspace as /dev/spidevX.X This module is maily intended to interface microcontrollers
and other led devices without a specific kernel driver. This support is also available as a module.

2、Makefile文件

obj-${CONFIG_DRIVER_MODEL}    += driver-model.o
#obj-m += driver-model.o

说明:

其中${CONFIG_DRIVER_MODEL}看作一个整体,一个变量,其值是由上级目录的Makefile文件确定。

3、上级Makefile文件

#
# Copyright (C) OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
# include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=driver-model
PKG_RELEASE:= include $(INCLUDE_DIR)/package.mk define KernelPackage/driver-model
SUBMENU:=LED modules
TITLE:=gpio control led
# DEPENDS:=@GPIO_SUPPORT +kmod-spi-bitbang +kmod-spi-gpio
DEPENDS:=@GPIO_SUPPORT
FILES:=$(PKG_BUILD_DIR)/driver-model.ko
# KCONFIG:=CONFIG_DRIVER_MODEL=m
# CONFIG_SPI_BITBANG=y
KCONFIG:=
AUTOLOAD:=$(call AutoLoad,,driver-model,)
endef define KernelPackage/driver-model/description
Kernel module for control a led.
endef EXTRA_KCONFIG:= \
CONFIG_DRIVER_MODEL=m EXTRA_CFLAGS:= \
$(patsubst CONFIG_%, -DCONFIG_%=, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \
$(patsubst CONFIG_%, -DCONFIG_%=, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \ MAKE_OPTS:= \
ARCH="$(LINUX_KARCH)" \
CROSS_COMPILE="$(TARGET_CROSS)" \
SUBDIRS="$(PKG_BUILD_DIR)" \
EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
$(EXTRA_KCONFIG) define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef define Build/Compile
$(MAKE) -C "$(LINUX_DIR)" \
$(MAKE_OPTS) \
modules
endef $(eval $(call KernelPackage,driver-model))

说明:

AUTOLOAD:=$(call AutoLoad,50,driver-model,1)当把驱动编译进内核,即选择Y时,该函数实现开机自动安装驱动。

4、make menuconfig

选中kmod-driver-model。

三、测试源码

#include <stdio.h>
#include <unistd.h> #include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h> #include <linux/ioctl.h> /*
int main(int argc, char **argv)
{
int fd;
char i;
//char buff[1024];
fd = open("/dev/mydriver", O_RDWR);
if (fd < 0) {
perror("open");
return 1;
}
printf("open success!\n");
for(i=5;i>0;i--)
{
ioctl(fd,1,1);
sleep(1);
ioctl(fd,0,1);
sleep(1);
}
close(fd);
return 0;
}
*/ int main(int argc, char **argv)
{
int on;
int led_no;
int fd; if(argc != ||sscanf(argv[],"%d",&led_no) != ||
sscanf(argv[],"%d",&on) != ||
on < || on > || led_no < || led_no>)
{
fprintf(stderr,"Usage:led led_no 0|1\n");
exit();
} //打开/dev/leds0设备文件
fd = open("/dev/mydriver",);
if(fd < )
{
perror("/dev/mydriver");
exit();
} //通过系统调用ioctl和输入的参数控制led
if(led_no ==)//第一个参数为功能选择,0为手动控制功能;第二个参数为控制灭还是亮;
{
ioctl(fd,on,led_no);
}
else//第一个参数为功能选择,1为自动控制功能;
{
while()
{
ioctl(fd,,led_no);
usleep();
ioctl(fd,,led_no);
usleep();
}
} //关闭设备句柄
close(fd);
return ;
}

说明:

1、该测试程序需要外部输入两个参数;

2、usleep的最大值不能超过1000000。

四、应用程序编译

1、Makefile文件

all: led

led: led.c
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< clean:
rm -f led

2、上级目录的Makefile文件

#
# Copyright (C) - OpenWrt.org
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
# include $(TOPDIR)/rules.mk PKG_NAME:=led
PKG_VERSION:=
PKG_RELEASE:= include $(INCLUDE_DIR)/package.mk define Package/led
SECTION:=utils
CATEGORY:=Utilities
TITLE:=led
MAINTAINER:=tingpan
PKGARCH:=all
endef define Package/led/description
led world!
endef define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef define Build/Configure
endef define Build/Compile
$(MAKE) -C $(PKG_BUILD_DIR) \
CC="$(TARGET_CC)" \
CFLAGS="$(TARGET_CFLAGS) -Wall" \
LDFLAGS="$(TARGET_LDFLAGS)"
endef define Package/led/install
$(INSTALL_DIR) $()/usr/sbin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/led $()/usr/sbin/
endef $(eval $(call BuildPackage,led))

五、烧写固件及测试

1、烧写固件

(1)连接串口、网线;

(2)打开SecureCRT ,两秒内按下键盘任意键,输入http

(3)打开浏览器,输入192.168.0.250

(4)开始刷机,自动重启。

2、查看驱动

在终端输入lsmod,存在driver-model的驱动,也可以进入dev文件查看存在mydriver设备。

3、测试代码进行测试

(1)led 0 1开启led灯

(2)led 0 0 关闭led灯

(3)led 1 0或led 1 1 实现led每秒闪一次

(4)如果要实现开机启动,可在网页中进行设置,

a、查看进程

b、杀死进程(这样才能手动控制,否则一直在后台运行,没法结束)

4、测试

应用程序return 0 或中断执行会执行release函数。

补充:开机启动

可以再etc文件夹中添加,如果是系统服务加入init.d文件夹下,写入名字就好;

如果是自己编写的应用程序,或需要网络启动后再启动,可以再rc.local文件中添加。

可在makefile中添加:

$(INSTALL_DIR) $()/usr/sbin
$(INSTALL_DIR) $()/etc/config
$(CP) ./files/scws $()/etc/config/
$(INSTALL_BIN) $(PKG_BUILD_DIR)/scws $()/usr/sbin/

相关源码下载地址:

http://pan.baidu.com/s/1sDikY

led的驱动及测试程序的更多相关文章

  1. 嵌入式linux驱动开发之点亮led(驱动编程思想之初体验)

    这节我们就开始开始进行实战啦!这里顺便说一下啊,出来做开发的基础很重要啊,基础不好,迟早是要恶补的.个人深刻觉得像这种嵌入式的开发对C语言和微机接口与原理是非常依赖的,必须要有深厚的基础才能hold的 ...

  2. Arduino 数码管LED屏驱动

    今天測试数码管LED屏驱动,用某产品的一个共阴极的LED屏,依据电路图做数码管LED屏的检測. 代码写得有些冗长,有好几种驱动的方法,这里仅仅是当中一种最直接的方案,抽出时间要做个更有效率的调用和驱动 ...

  3. 旧接口注册LED字符驱动设备(动态映射)

    #include <linux/init.h> // __init __exit #include <linux/module.h> // module_init module ...

  4. Linux内核的LED设备驱动框架【转】

    /************************************************************************************ *本文为个人学习记录,如有错 ...

  5. 嵌入式Linux学习笔记(三) 字符型设备驱动--LED的驱动开发

    在成功构建了一个能够运行在开发板平台的系统后,下一步就要正式开始应用的开发(这里前提是有一定的C语言基础,对ARM体系的软/硬件,这部分有疑问可能要参考其它教程),根据需求仔细分解任务,可以发现包含的 ...

  6. 【玩转单片机系列001】 08接口双色LED显示屏驱动方式探索

    前些日子,从淘宝上购得一块08接口的双色LED显示屏(打算做个音乐频谱显示器),捣鼓了好几天,终于搞清楚了其控制原理,在这里做个总结,算是备忘吧. 1.LED显示屏的扫描方式 LED显示屏的扫描方式有 ...

  7. led.c驱动框架2nd

    led.c: #include <linux/module.h> #include <linux/init.h> #include <linux/fs.h> ; v ...

  8. 中颖内带LED资源驱动代码

    //上一篇写了LCD驱动,本篇写下LED驱动 //DISPCON 最高位为1时, 选择LED驱动,LCD驱动无效 最高位为0时, 选择LCD驱动.LED驱动无效 void Sh79fLed_Init( ...

  9. Tiny4412之蜂鸣器驱动与led灯驱动

    一:LED驱动编写 要编写LED驱动,首先的知道开发板的构造:开发板分为核心板与底板:编写驱动的第一步就是要看开发板,找到LED灯在开发板上的位置及所对应的名字:第一步就要查看核心板电路图,以及底板电 ...

随机推荐

  1. redis 处理命令的过程

    redis版本:redis-3.2.9 在客户端输入 set name zhang,调试redis服务器,得到调用栈如下: 在dictReplace中加了断点,结果跳出来4个线程,redis还是单进程 ...

  2. JavaScript学习总结(八)——JavaScript数组

    JavaScript中的Array对象就是数组,首先是一个动态数组,无需预先制定大小,而且是一个像Java中数组.ArrayList.Hashtable等的超强综合体. 一.数组的声明 常规方式声明: ...

  3. vs2012团队连接(Team Foundation Server)怎样从已登录的用户退出

    在用visual studio 连接团队项目时,首次输入用户名和密码后,默认保存住凭据了,等以后连接会自动采用首次的凭证. 但是如何采用新的用户重新登录呢 解决方法有两个: 1.删除原有账号登陆的凭证 ...

  4. 小程序数组型图片自适应效果的实现(交流QQ群:604788754)

    //本例代码如有问题,请加群,下载今日日期文件,测试.(如对本例有疑问,也可加群咨询群主) WXML: <view class="imgbox"> <block ...

  5. 火狐扒代码插件ScrapBook

    ScrapBook这个火狐插件很好用,但偶尔用下,不经常使用,是仿站扒代码的前端利器.

  6. artDialog 弹窗提示

    artDialog 弹窗提示,方便调用,不用去查文档了. /// <reference path="../../Scripts/artDialog5.0/artDialog.min.j ...

  7. JQuery, Silverlight 公用WCF

    WCF web.config配置: <?xml version="1.0"?> <configuration> <system.web> < ...

  8. 算法训练 Multithreading

     算法训练 Multithreading   时间限制:1.0s   内存限制:256.0MB      问题描述 现有如下一个算法: repeat ni times yi := y y := yi+ ...

  9. opencv实现遍历文件夹下所有文件

    前言 最近需要将视频数据集中的每个视频进行分割,分割成等长的视频片段,前提是需要首先遍历数据集文件夹中的所有视频. 实现 1.了解opencv中的Directory类: 2.实现测试代码: 系统环境 ...

  10. poj-1170 (状态压缩形式下的完全背包)

    #include <iostream> #include <algorithm> #include <cstring> using namespace std; ; ...