一、驱动源码

#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. CSS3动画和JS动画的比较

    前言 之前有被问到一个问题,css3动画和js动画性能谁更好,为什么.据我的经验,当然觉得css3动画性能更好,至于为什么一时还真答不上来,所以特意查了一下资料总结一波. JS动画 优点: js动画控 ...

  2. js 数组复制问题

    师兄面试回来问个问题,js中数组怎么复制,工作中没遇到,面试也涨见识 了,他给我说了下,太晚没留心,打早起来研究下,写个dom,来看下 代码如下 <!doctype html> <h ...

  3. 手机端的META你知道多少

    一.天猫 <title>天猫触屏版</title> <meta content="text/html; charset=utf-8" http-equ ...

  4. Android 注解的使用与注意事项

    一般情况下我们最常用到的三个注解分别是@EActivity  @ViewById  和@Click    @EActivity这个注解是用来修饰Activity的,向Activity注入布局,功能相当 ...

  5. 如何成为一名合格的Android工程师?

    首先需要申明的是,我并不是一名合格的Android工程师,无论从开发经验或者是技术水平上来说,我都没有资质承担以为Android工程师的责任,但是我把它作为一个目标,也一如既往的努力着.如果我的论点有 ...

  6. ACCESS删除datagridview和数据库中的一条数据,同时更新显示的方法源码

    //删除,行删除 private void 删除_Click(object sender, EventArgs e) { int dgrcount = dataGridView1.SelectedRo ...

  7. windows运行打开服务命令

    1. gpedit.msc-----组策略    2. sndrec32-------录音机   3. Nslookup-------IP地址侦测器   4. explorer-------打开资源管 ...

  8. 【c++基础】accumulate

    accumulate // accumulate example #include <iostream> // std::cout #include <functional> ...

  9. linux平台程序高精度延时问题select-usleep等

    前言 微秒级别的延时... 1.能用 #include <unistd.h> int usleep(useconds_t usec);              微秒级:1/10^-6 2 ...

  10. android复制包需要修改的几个地方

    1.要看什么情况,若是在同一个eclipse下,那么就需要修改包名.若不在的话,那就可以不用了. 2.这个app_name也是一样. 3.先说下情况,这是我修改好的.原本这个R的是引之前包的,必须要改 ...