搞了两天~~还没有成功~~有待进一步研究,现在将过程及错误列出:
源码如下:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/gpio.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#define DEVICE_NAME "tx2440_led"
static int tx2440_led_Major=0;
#define LED_OFF 0
#define LED_ON 1
#define ALL_LED_OFF 3
#define ALL_LED_ON 4
//指定led所用的io引脚,这里查看原理图
static unsigned long led_table[]= //这里的S3C2410_GPF(0)等在哪里定义的?
{
S3C2410_GPF(0),
S3C2410_GPF(1),
S3C2410_GPF(2),
S3C2410_GPF(3),
};
static int tx2440_led_open(struct inode *inode,struct file *filp)
{
printk(KERN_INFO "TX2440_LED DRIVER OPEN CALLED!/n");
return 0;
}
static int tx2440_led_release(struct inode *inode,struct file *filp)
{
printk(KERN_INFO "TX2440_LED_DRIVER CLOSE CALLED!/n");
return 0;
}
static int tx2440_led_read(struct file *filp, char *buf, size_t count, loff_t *f_ops)
{
printk(KERN_INFO "TX2440_LED_DRIVER READ CALLED!/n");
return 0;
}
static int tx2440_led_write(struct file *filp, char *buf, size_t count, loff_t *f_pos)
{
printk(KERN_INFO "TX2440_LED_DRIVER WRITE CALLED!/n");
return 0;
}
static int tx2440_led_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int i;
if (arg>4) //arg参数有什么用?
{
return -EINVAL;
}
switch(cmd)
{
case LED_ON:
s3c2410_gpio_setpin(led_table[arg],0); //低电平点亮
break;
case LED_OFF:
s3c2410_gpio_setpin(led_table[arg],1);
break;
case ALL_LED_ON:
for(i=0;i<4;i++)
s3c2410_gpio_setpin(led_table[i],0);
break;
case ALL_LED_OFF:
for(i=0;i<4;i++)
s3c2410_gpio_setpin(led_table[i],1);
break;
default: return -EINVAL;
}
}
static struct file_operations tx2440_led_fops =
{
.owner = THIS_MODULE,
.open = tx2440_led_open,
.release = tx2440_led_release,
.read = tx2440_led_read,
.write = tx2440_led_write,
.ioctl = tx2440_led_ioctl,
};
static struct class *tx2440_led_class; //这里要注意是什么东西?
static int __init tx2440_led_init(void)
{
printk(KERN_INFO "TX2440_LED_DRIVER MODULE INIT/n");
tx2440_led_Major=register_chrdev(0,DEVICE_NAME,&tx2440_led_fops);
if(tx2440_led_Major<0)
{
printk(KERN_WARNING "Can't register the major number/n");
return tx2440_led_Major;
}
else
printk( "Register the major number ok.Major=%d/n",tx2440_led_Major);
//注册一个类,使mdev可以在"/dev/"目录下面建立设备节点
tx2440_led_class = class_create(THIS_MODULE, DEVICE_NAME);
if(IS_ERR(tx2440_led_class))
{
printk("Err: failed in tx2440_led_class. /n");
return -1;
}
//创建一个设备节点,节点名为DEVICE_NAME
else
device_create(tx2440_led_class, NULL, MKDEV(tx2440_led_Major, 0), NULL, DEVICE_NAME);
printk(DEVICE_NAME " initialized/n");
return 0;
}
static void __exit tx2440_led_exit(void)
{
printk("tx2440_led MODULE EXIT/n");
unregister_chrdev(tx2440_led_Major, DEVICE_NAME);
device_destroy(tx2440_led_class, MKDEV(tx2440_led_Major, 0));
class_destroy(tx2440_led_class);
}
module_init(tx2440_led_init);
module_exit(tx2440_led_exit);
MODULE_AUTHOR("YWW");
MODULE_DESCRIPTION("My Driver");
MODULE_LICENSE("GPL");
Makefile文件源码如下:
#Makefile for tx2440_led
ifneq ($(KERNELRELEASE),)
obj-m:=tx2440_led.o
else
KERNELDIR ?= /usr/local/src/linux-2.6.31
PWD := $(shell pwd)
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif
测试代码如下:
/******************************************************
LED驱动测试程序,在TX2440A开发板做测试
驱动用法:
设备名称:TX2440-led
测试程序名称:led
如果只带一个参数,且参数为0 1
led 0:四个灯全灭
led 1: 四个灯全亮
如果带两个参数,参数1表示哪盏灯,参数2表示亮灭
led 1 0:第一盏灯灭
led 4 1: 第四盏灯亮
*******************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
int main(int argc, char **argv)
{
unsigned int on;
unsigned int led_num;
int fd;
fd = open("/dev/tx2440_led", 0);
if (fd < 0)
{
perror("open device led");
exit(1);
}
if (argc == 2)
{
sscanf(argv[1], "%d", &on);
if (on < 2)
{
ioctl(fd, on+3, 0);
sleep(5);
}
else
{
printf("Usage: led led_num 0|1 or led 0|1/n");
exit(1);
}
}
if (argc == 3)
{
sscanf(argv[1], "%d", &led_num);
sscanf(argv[2], "%d", &on);
if ((on < 2) && (led_num>0 || led_num < 4))
{
ioctl(fd, on, (led_num-1));
sleep(5);
}
else
{
printf("Usage: led led_num 0|1 or led 0|1/n");
exit(1);
}
}
close(fd);
return 0;
}
通过驱动程序的Makefile编译出了tx2440_led.ko文件,下载到开发板的/lib/modules/2.6.31目录下运行的现象如下
[root@YWW-2440 2.6.31]#led 1 1
TX2440_LED DRIVER OPEN CALLED!
TX2440_LED_DRIVER CLOSE CALLED!
[root@YWW-2440 2.6.31]#led 4 1
TX2440_LED DRIVER OPEN CALLED!
TX2440_LED_DRIVER CLOSE CALLED!
显然应用程序能够调用驱动程序里的open与close函数~~
但是问题在开发板上的发光二极管没亮~
这是怎么回事~~??
今天又在在ioctl中也添加了printk打印函数,一样能够打印出信息,也就是能正确调用icotl函数,那问题就出在s3c2410_gpio_setpin()函数了~~可是,这个函数是这样调用的啊~~那问题到底出在哪里??是不是要设置S3C2410_GPFDAT这个寄存器使gpf 口作为输出??? 有高手看到可以指点小弟~~谢谢~~