一、驱动源码

#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. javascript--- document.write()和 innerHTML的区别

    document.write是直接写入到页面的内容流,如果在写之前没有调用document.open, 浏览器会自动调用open.每次写完关闭之后重新调用该函数,会导致页面被重写. innerHTML ...

  2. 061——VUE中vue-router之通过程序控制路由跳转

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. FE英文缩写

    PM:product manager,产品经理,又称品牌经理,brand managerRD:research and development enginner,研发工程师FE:front-end d ...

  4. 莪的拽、像省田各号①样没尽頭队——需求改进&原型设计

    需求改进&原型设计 1. 需求&原型改进 经过老师的指导以及组内成员的讨论后,我们认为之前的需求分析已经比较准确完备. 根据电子宠物的形象结构特点,以及模拟屏幕的空间限制,我们设计出了 ...

  5. CDMA LTE FAQ2

    1.UE等级 LTE CAT4,应该指的是LTE Category4,字面意思是LTE的ue-Category设置为4.ue-Category指的是UE的接入能力等级.也就是UE能够支持的传输速率的等 ...

  6. 1017 A除以B

    本题要求计算 A/B,其中 A 是不超过 1000 位的正整数,B 是 1 位正整数.你需要输出商数 Q 和余数 R,使得 A=B×Q+R 成立. 输入格式: 输入在一行中依次给出 A 和 B,中间以 ...

  7. 麻省理工大学新发明:暗黑WiFi透视技术

    美国麻省理工学院(MIT)宣布,该大学的研究人员开发出了一种可以通过WiFi信号来检测人体移动情况的系统(Wi-Vi).据MIT介绍,该系统可以检测出钢筋混凝土墙壁背后的人体移动情况,其未来可以被作为 ...

  8. C++语言的一些问题

    论坛上看到的有人提出的关于C++的一些问题,真是细致(下面还有回复说他对C++一知半解的),一直以为自己的C++还是可以的,可是看了之后真是内牛满面,为什么自己从来没有想的这么深入,差距真的有这么大吗 ...

  9. 务实java基础之集合总结

    Java 提供了容纳对象(或者对象的句柄)的多种方式.其中内建的类型是数组,此外, Java 的工具库提供了一些 "集合类",利用这些集合类,我们可以容纳乃至操纵自己的对象. 声明 ...

  10. 【linux】wifi不能使用的问题

    Worked solution (Requirements: kernel >=4.11) : Download driver directory from this repo:https:// ...