全亮全灭点亮mini2440的设备驱动

来源:互联网 发布:phpstorm apache 编辑:程序博客网 时间:2024/06/06 04:34

首先,求助一下。今天忙了一下午,就为了找到一个可以和国嵌内核匹配的u-boot,但是还是没有找到。网上的大神们谁有国嵌的mini2440的u-boot可以传给我一个,感激不尽。

由于没有u-boot,内核模块编译出来了也不能在板子上运行,所以很多代码没有亲测。

 

首先说编译内核模块,编译内核模块的Makefile如下:

ifneq ($(KERNELRELEASE),)obj-m := mini2440_leds.oelseKDIR := /home/guoqian/4-3-1/linux-2.6.29all:make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-clean:rm -f *.ko *.o *.mod.o *.mod.c *.symvers  modul*endif

KDIR := /home/guoqian/4-3-1/linux-2.6.29   这个路径是要找到自己板载内核的路径,同时要注意这个路径下的内核是已经被编译过的,最好直接一次编译成zImage。要不然会出现各类的问题,不过还好前人走的路很多,随手百度问题也就解决了。

但是今天又开始面临了第二个困扰。上图。

这就是今天面临的情况。驱动程序中调用的IO函数一会再列出来,但是这两个驱动函数初步可以看出是在内核中实现的。出现的错误是寄存器的定义问题。所以要想把程序走通,必须使用国嵌移植的内核。所以弄到了国嵌的u-boot以后估计就可以开始测试代码了。

下面开始分析点亮和熄灭四个二极管的驱动程序。

1.dev_init

static int __init dev_init(void){int ret;int i;for (i = 0; i < 4; i++) {s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);//设置IO口的模式,定义为输出。s3c2410_gpio_setpin(led_table[i], 0);//定义引脚全部为低电平,在结束后,四个 LED 应该是全部都是发光。}  /*注册混杂设备*/ret = misc_register(&misc);printk (DEVICE_NAME"\tinitialized\n");return ret;}

注意:混杂设备注册是在dev_init函数中完成的。

2.在dev_init函数中完成了混杂设备的注册,下面列出混杂设备的属性定义。

static struct miscdevice misc = {.minor = MISC_DYNAMIC_MINOR,    //这个宏(内核中)定义的混杂设备的此设备号,                                //由内核动态的进行分配的。.name = DEVICE_NAME,            //定义了设备的名字--可以随意定义。.fops = &dev_fops,              //混杂设备的实质是字符设备,字符设备都有file_operations。};

3.file_operations

static struct file_operations dev_fops = {.owner=THIS_MODULE,.ioctl=sbc2440_leds_ioctl,//驱动程序不一定要实现open和release,但是内核会自动实现这两个设备方法。};

注意:最后一句备注。现在接触的程序太少了,没能真正的理解。

4.s3c2440_leds_ioctl函数。

static int s3c2440_leds_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)/*传递进来的是整形的参数arg,所以没有进行对参数的检测,只有传进来是指针的时候才进行检测。*/{switch(cmd) {case 0:case 1:if (arg > 4) {return -EINVAL;}s3c2410_gpio_setpin(led_table[arg], !cmd);//根据命令传进来的参数来直接设置灯的亮和灭----arg。return 0;default:return -EINVAL;}}

注意:命令的实质是一个三十二位的无符号长整形数,定义命令是要让命令具有更高的可读性,使命令执行的时候更加安全。
5.最后送上两个数组

static unsigned long led_table [] = {S3C2410_GPB5,S3C2410_GPB6,S3C2410_GPB7,S3C2410_GPB8,}; //LED 对应端口将要输出的状态列表static unsigned int led_cfg_table [] = {S3C2410_GPB5_OUTP,S3C2410_GPB6_OUTP,S3C2410_GPB7_OUTP,S3C2410_GPB8_OUTP,};

在网上找到了这两个数组参数具体实现的代码了,就不贴了,因为自己看不懂,所以就这样先。

6.直接粘上测试部分的应用程序

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <sys/ioctl.h>int main(int argc, char **argv){int on;int led_no;int fd;/*argv[1]本身是一个字符串,把这个字符串通过%d传递给led_no  on < 0 || on > 1 设定on的有效值只能取0或1。  led_no < 0 || led_no > 3  设定led_no的有效值。*/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/leds", 0);if (fd < 0) {perror("open device leds");exit(1);}ioctl(fd, on, led_no);close(fd);return 0;}


 

原创粉丝点击