mini2440的LED驱动编写与测试
一,编写驱动程序
在drivers/char目录下,建立一个驱动程序文件mini2440_leds.c
内容如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define DEVICE_NAME "leds"//设备名(/dev/leds)
//LED对应的GPIO端口列表
static unsigned long led_table [] = {
S3C2410_GPB(5),
S3C2410_GPB(6),
S3C2410_GPB(7),
S3C2410_GPB(8),
};
//LED对应端口将要输出的状态列表
static unsigned int led_cfg_table [] = {
S3C2410_GPIO_OUTPUT,
S3C2410_GPIO_OUTPUT,
S3C2410_GPIO_OUTPUT,
S3C2410_GPIO_OUTPUT,
};
/*ioctl函数的实现
* 在应用/用户层将通过ioctl函数向内核传递参数,以控制LED的输出状态
*/
static int sbc2440_leds_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
switch(cmd)
{
case 0:
case 1:
if (arg > 4) {
return -EINVAL;
}
//根据应用/用户层传递来的参数(取反),通过s3c2410_gpio_setpin函数设置LED对应的端口寄存器,
s3c2410_gpio_setpin(led_table[arg], !cmd);
return 0;
default:
return -EINVAL;
}
}
/*
* 设备函数操作集,在此只有ioctl函数,通常还有read, write, open, close等,因为本LED驱动在下面已经
* 注册为misc设备,因此也可以不用open/close
*/
static struct file_operations dev_fops = {
.owner = THIS_MODULE, //一个宏,指向编译模块时自动创建的__this_module变量,无需关注
.ioctl = sbc2440_leds_ioctl, //用来传输参数
};
/*
* 把LED驱动注册为MISC设备
*/
static struct miscdevice misc = {
.minor = MISC_DYNAMIC_MINOR, //动态设备号
.name = DEVICE_NAME, //设备名字
.fops = &dev_fops, //file_operations结构
};
/*
* 设备初始化
*/
static int __init dev_init(void)
{
int ret;
int i;
for (i = 0; i < 4; i++) {
//设置LED对应的端口寄存器为输出(OUTPUT)
s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
//设置LED对应的端口寄存器为低电平输出,在模块加载结束后,四个LED应该是全部都是发光状态
s3c2410_gpio_setpin(led_table[i], 0);
}
ret = misc_register(&misc); //自动注册设备函数
printk (DEVICE_NAME"\tinitialized\n"); //打印初始化信息
return ret;
}
static void __exit dev_exit(void)
{
misc_deregister(&misc); //卸载驱动程序
}
module_init(dev_init); //模块初始化
module_exit(dev_exit);//卸载模块
MODULE_LICENSE("GPL"); //版权信息
MODULE_AUTHOR("FriendlyARM Inc.");//开发者信息
二,打开drivers/char/Kconfig文件,添加如下红色部分内容:
config LEDS_MINI2440
tristate "LED Support for Mini2440 GPIO LEDs"
depends on MACH_MINI2440
default y if MACH_MINI2440
help
This option enables support for LEDs connected to GPIO lines on Mini2440 boards.
三,再根据该驱动的配置定义,把对应的驱动目标文件加入内核中,打开linux-2.6.32.2/drivers/char/Makefile文件,
obj-$(CONFIG_LEDS_MINI2440) += mini2440_leds.o
四,在内核源代码目录下执行:make menuconfig重新配置内核在此按空格键选择
“> LED Support for Mini2440 GPIO LEDs (NEW)”选项,并退出保存内核配置。在内核源代码根目录下执行;make zImage,把生成的新内核烧写到开发板中。执行make modules 就可以生成内核模块文件drivers/char/mini2440_leds.ko,通过网络tftp下载到开发板中
五,编写测试程序,新建一个leds-test.c文件,在命令行下执行:#arm-linux-gcc –o leds-test leds-test.c 将生成可执行目标文件leds-test,通过网络tftp下载到开发板中,比如放在/home/plg 目录下
#include
#include
#include
#include
int main(int argc, char **argv)
{
int on; //0或者1
int led_no; //
int fd;
if (argc != 3 || sscanf(argv[1], "%d", &led_no) != 1 || sscanf(argv[2],"%d", &on) != 1 || on < 0 || on > 1 || led_no < 0 || led_no > 3) //当出现参数格式不正确时,输出使用方法
{
fprintf(stderr, "Usage: leds led_no 0|1\n");
exit(1);
}
fd = open("/dev/leds0", 0);
if (fd < 0)
{
fd = open("/dev/leds", 0);
}
if (fd < 0)
{
perror("open device leds");
exit(1);
}
ioctl(fd, on, led_no); //传递参数,与驱动程序中对应
close(fd);
return 0;
}
六,在此使用 ftp 命令把编译出的mini6410_hello_module.ko
下载到板子中,并把它移动到/lib/modules/2.6.38-FriendlyARM 目录然后在板子中现在执行
insmod
mini2440_leds.ko
出现如下结果:
leds initialized
可以看到该模块已经被装载了(注意:使用modprobe 命令加载模块不需要加“ko”尾缀)
再执行以下命令,可以看到该模块被卸载
#rmmod mini6410_hello_module
注意: 要能够正常卸载模块, 必须把模块放入开发板的/lib/modules/2.6.38-FriendlyARM 目录
七,在单板根文件系统中建立设备文件
#mknod /dev/leds c 231 0
八,测试
#leds-test 3 0
阅读(1700) | 评论(0) | 转发(0) |