GPIO(led灯)驱动和测试程序
来源:互联网 发布:财务报表主要数据分析 编辑:程序博客网 时间:2024/06/08 02:26
看着内核分析,慢慢的感觉这些内核里面的驱动就那么纠结呢,先把内核分析放一边吧,看下以前弄的驱动,算是借鉴别人的驱动,修改了下而已。
环境:
内核:Linux-2.6.25.4
交叉编译器:arm-linux-3.4.5
GPIO_led.c
#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 <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <linux/device.h> /*所用到的头文件*/
#define DEVICE_NAME "GPIO-leds" /*device name,you will see device name when execute "cat /proc/devices" */
#define LED_MAJOR 231 /*major devive number*/
/*the second parameter of ioctl(fd,cmd,arg) */
#define IOCTL_LED_ON 1
#define IOCTL_LED_OFF 0
/*制定LED所用的 GPIO pins */
static unsigned long led_port [] =
{
S3C2410_GPB5,
S3C2410_GPB6,
S3C2410_GPB7,
S3C2410_GPB8,//我用的就是TQ2440板,用到的GPIO是GPB5-8。
};
/*用来指定GPIO pin的功能:output*/
static unsigned int led_out [] =
{
S3C2410_GPB5_OUTP,
S3C2410_GPB6_OUTP,
S3C2410_GPB7_OUTP,
S3C2410_GPB8_OUTP,
};
/* 应用程序对设备文件/dev/GPIO-leds执行 open(...)时,
* 就会调用iFico_leds_open函数
*/
static int iFico_leds_open(struct inode *inode, struct file *file)
{
// int i;
// for (i = 0; i < 4; i++)
// {
//
// s3c2410_gpio_cfgpin(led_led[i], led_out[i]);
// }
return 0;
}
/* 应用程序对设备文件/dev/GPIO-leds执行 ioctl(...)时,
* 就会调用iFico_leds_ioctl函数
*/
static int iFico_leds_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
if (arg > 4)
{
return -EINVAL;
}
switch(cmd)
{
case IOCTL_LED_ON:
// 设置指定引脚的输出电平为0
s3c2410_gpio_setpin(led_port[arg], 0);
return 0;
case IOCTL_LED_OFF:
// 设置指定引脚的输出电平为1
s3c2410_gpio_setpin(led_port[arg], 1);
return 0;
default:
return -EINVAL;
}
}
/* 这个结构是字符设备驱动程序的核心
* 当应用程序操作设备文件时所调用的open、read、write等函数,
* 最终会调用这个结构中指定的对应函数
*/
static struct file_operations iFico_leds_fops =
{
.owner = THIS_MODULE, /* 这是一个宏,指向编译模块时自动创建的__this_module变量 */
.open = iFico_leds_open,
.ioctl = iFico_leds_ioctl,
};
static char __initdata banner[] = "iFico2440 LEDS,Sunny/n";
static struct class *led_class;
/*
* 执行“insmod GPIO_leds.ko”命令时就会调用这个函数
*/
static int __init iFico_leds_init(void)
{
int ret;
printk(banner);
/* 注册字符设备驱动程序
* 参数为主设备号、设备名字、file_operation结构;
* 这样,主设备号就和具体的file_operation结构联系起来了,
* 操作主设备为LED_MAJOR的设备文件时,就会调用iFico_leds_fops中的相关成员函数
* LED_MAJOR可以设为0,表示由内核自动分配主设备号
*/
ret = register_chrdev(LED_MAJOR, DEVICE_NAME, &iFico_leds_fops);
if (ret < 0)
{
printk(DEVICE_NAME " can't register major number/n");
return ret;
}
//注册一个类,是mdev可以在“/dev/”目录下面建立设备节点
led_class = class_create(THIS_MODULE, DEVICE_NAME);
if(IS_ERR(led_class))
{
printk("Err: failed in GPIO-leds class. /n");
return -1;
}
//创建一个设备节点,节点名为DEVICE_NAME
class_device_create(led_class, NULL, MKDEV(LED_MAJOR, 0), NULL, DEVICE_NAME);
printk(DEVICE_NAME " initialized/n");
return 0;
}
/*
* 执行“rmmod GPIO_leds.ko”命令时就会调用这个函数
*/
static void __exit iFico_leds_exit(void)
{
/* 卸载驱动程序 */
unregister_chrdev(LED_MAJOR, DEVICE_NAME);
class_device_destroy(led_class, MKDEV(LED_MAJOR, 0)); //删掉设备节点
class_destroy(led_class); //注销类
}
/* 这两行指定驱动程序的初始化函数和卸载函数 */
module_init(iFico_leds_init);
module_exit(iFico_leds_exit);
/* 描述驱动程序的一些信息,不是必须的*/
MODULE_AUTHOR("Sunny"); // 驱动程序的作者
MODULE_DESCRIPTION("Sunny LED Driver"); // 一些描述信息
MODULE_LICENSE("GPL"); // 遵循的协议
编写好驱动程序后,放到drivers/char/目录下,修改此目录下的Makefiel 和Kconfig:
修改“Kconfig”文件,在6行开始添加如下内容(红色部分所示):
#
# Character device configuration
#
menu "Character devices"
config iFico_LEDS
tristate "Sunny LEDs Driver"
depends on ARCH_S3C2440
help
2440 User leds.
然后修改“Makefile”文件,在大概12行添加如下内容(红色部分所示):
#
# Makefile for the kernel character device drivers.
#
#
# This file contains the font map for the default (hardware) font
#
FONTMAPFILE = cp437.uni
obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o
obj-$(CONFIG_iFico_LEDS) += GPIO_leds.o
obj-$(CONFIG_LEGACY_PTYS) += pty.o
添加完毕以上内容之后,输入:#make menuconfig,然后配置如下:
Device Drivers --->
Character devices --->
<*> Sunny LEDs Driver
保存编译内核,烧写到开发板中。在系统中的/dev目录下会看到GPIO-leds,说明驱动加载成功。
然后再编写测试程序。
/*************************************
NAME:leds.c
*************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#define IOCTL_LED_ON 1
#define IOCTL_LED_OFF 0
void usage(char *exename)
{
printf("Usage:/n");
printf(" %s<led_no><on/off>/n",exename);
printf(" led_no=1,2/n");
}
int main(int argc, char **argv)
{
unsigned int led_no;
int fd;
if(argc !=3)
goto err;
// system("/etc/rc.d/init.d/leds stop");
fd = open("/dev/GPIO-leds", 0);
if (fd < 0) {
perror("Can't open /dev/GPIO-leds/n");
return -1;
}
led_no= strtoul(argv[1],0,0)-1;
if(led_no>3)
goto err;
if(!strcmp(argv[2],"on")){
ioctl(fd,IOCTL_LED_ON,led_no);
}else if(!strcmp(argv[2],"off")){
ioctl(fd,IOCTL_LED_OFF,led_no);
}else {
goto err;
}
close(fd);
return 0;
err:
if(fd>0)
close(fd);
usage(argv[0]);
return -1;
}
[root@sunny /]# arm-linux-gcc -o ledtest leds.c
[root@sunny /]# arm-linux-strip ledtest
然后将ledtest通过NFS或者U盘拷贝到开发板中/sbin目录下,重启
[root@sunny /]# ledtest 1 on 就会看到开发板上的led1亮;
[root@sunny /]# ledtest 1 off 就会看到开发板上的led1灭;
这是一个比较简单的例子,仅仅是控制IO口,驱动是一个复杂的圈圈,还是要好好的学习啊!
- GPIO(led灯)驱动和测试程序
- 小小的led驱动和测试程序
- led驱动测试程序
- S3C6410 GPIO 驱动(二) --- LED驱动
- STM8 GPIO 学习(驱动LED、Button)
- S3C6410 GPIO 驱动(三) ---LED应用程序--实现关闭或打开指定LED灯
- TQ2440 GPIO驱动及测试程序
- DM8168 GPIO驱动与测试程序
- s3c2440- led驱动分析及其测试程序
- Windows CE GPIO/LED驱动
- cubieboard2使用GPIO驱动LED
- (one) GPIO和LED
- Android GPIO LED 驱动与HAL分析(转)
- 基于TX2440开发板在ADS1.2中编写LED的驱动(GPIO的使用)裸机程序
- led驱动模块编译、加载和测试
- Linux嵌入式驱动初体验(六)--- LED驱动测试程序
- LED驱动测试程序以及静态加载驱动过程
- IMX6Q学习笔记———编写LED驱动和测试程序以及相关管脚配置
- MYSQL计算两日期/时间之间相差的天数,秒数...分钟
- (C#)实现无限级分类树
- 类与对象
- Java this、super的用法
- HDU 1527
- GPIO(led灯)驱动和测试程序
- 精巧的代码(待续)
- javamail例子
- 关于TWS 中一个JOB 对多个文件的CHECK!
- Prototype messes up the multipart boundary
- bluetooth 外围设备 驱动有问题 解决办法
- 如何修改MYSQL数据库密码
- dreamwear 电子书
- dom4j读取xml文件例子