第五篇:第一个字符型驱动

日期:2009-3-10

 

驱动板子上的LED,共四个,查原理图,发现教程上的四个GPIO与我板子的GPIO对应不上,教程上是用的GPIO_B7,8,9,10; 而我的板子是 GPIO_F4,5,6,7

所以我只替换了管脚的说明,其他一致呵呵

 

代码如下:

 

#ifndef _KERNEL_

#define _KERNEL_

#endif

#ifndef MODULE

#define MODULE

#endif

                                                                                               

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/version.h>

#include <linux/fs.h>

#include <linux/init.h>

#include <asm-arm/arch-s3c2410/hardware.h>

#define DEVICE_NAME "leds"

#define LED_MAJOR 232

                                                                                              

static unsigned long led_table[]={GPIO_F4,GPIO_F5,GPIO_F6,GPIO_F7};

static int 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;

        }

        write_gpio_bit(led_table[arg],!cmd);

        default:

                return -EINVAL;

        }

}

                                                                                               

static struct file_operations leds_fops={

        owner:THIS_MODULE,

        ioctl:leds_ioctl,

                                                                                               

};

                                                                                              

static int __init leds_init(void){

int ret;

int i;

ret = register_chrdev(LED_MAJOR,DEVICE_NAME,&leds_fops);

if(ret<0)

{

        printk(DEVICE_NAME"can't register major number");

        return ret;

}

for(i=0;i<4;i++)

{

        set_gpio_ctrl(led_table[i]|GPIO_PULLUP_EN|GPIO_MODE_OUT);

        write_gpio_bit(led_table[i],1);

}

printk(DEVICE_NAME "initialized/n");

return 0;

}

                                                                                               

static void __exit leds_exit(void){

        unregister_chrdev(LED_MAJOR,DEVICE_NAME);

}

                                                                                               

module_init(leds_init);

module_exit(leds_exit);      

 

 

 

按下列方式编译,我的乖乖,这么多警告,错误啊。

[root@localhost sin]# arm-linux-gcc -O2 -c -I/armsys2410/kernel/include/ led.c

In file included from led.c:13:

/armsys2410/kernel/include/asm-arm/arch-s3c2410/hardware.h:70: warning: no semic

olon at end of struct or union

/armsys2410/kernel/include/asm-arm/arch-s3c2410/hardware.h:70: parse error befor

e `offset'

/armsys2410/kernel/include/asm-arm/arch-s3c2410/hardware.h:70: warning: data def

inition has no type or storage class

led.c:19: warning: `struct file' declared inside parameter list

led.c:19: warning: its scope is only this definition or declaration, which is pr

obably not what you want.

led.c:19: warning: `struct inode' declared inside parameter list

led.c: In function `leds_ioctl':

led.c:24: `EINVAL' undeclared (first use in this function)

led.c:24: (Each undeclared identifier is reported only once

led.c:24: for each function it appears in.)

led.c:26: parse error before `)'

led.c:26: parse error before `u32'

led.c:26: `u32' undeclared (first use in this function)

led.c:26: parse error before `)'

led.c:26: parse error before `)'

led.c:26: parse error before `u32'

led.c:26: parse error before `)'

led.c: At top level:

led.c:32: variable `leds_fops' has initializer but incomplete type

led.c:33: unknown field `owner' specified in initializer

led.c:33: warning: excess elements in struct initializer

led.c:33: warning: (near initialization for `leds_fops')

led.c:34: unknown field `ioctl' specified in initializer

led.c:34: warning: excess elements in struct initializer

led.c:34: warning: (near initialization for `leds_fops')

led.c: In function `leds_init':

led.c:41: `LEDMAJOR' undeclared (first use in this function)

led.c:49: parse error before `)'

led.c:49: parse error before `u32'

led.c:49: `u32' undeclared (first use in this function)

led.c:49: parse error before `)'

led.c:49: parse error before `)'

led.c:49: parse error before `u32'

led.c:49: parse error before `)'

led.c:49: parse error before `)'

led.c:49: parse error before `u32'

led.c:49: parse error before `)'

led.c:49: parse error before `)'

led.c:49: parse error before `u32'

led.c:49: parse error before `)'

led.c:50: parse error before `)'

led.c:50: parse error before `u32'

led.c:50: parse error before `)'

led.c:50: parse error before `)'

led.c:50: parse error before `u32'

led.c:50: parse error before `)'

 

花了一下午时间,在网上搜集资料,但始终也没有解决

在坛上经大家的指点,用kernel/drivers/example-leds.c (发现这个和我的板子的GPIO定义都一样)

但一编译发现错误更多。。。(错误更多,就不列出来了,省的打击信心。。。)

继续找资料。。。

继续搜索资料,发现基于2.6内核的好象多些,胡乱看了一通。。。

有点心恢意冷了

病急乱投医了,开始怀疑内核没有编译会不会影响呢?

(之前把内核一释放,啥操作都没有做)

于是把交叉编译工具,内核都删除,按教程重新弄一边,问题依旧。。。

始终不得法门,郁闷啊,

后来就怀疑编译时,参数错了,换个关键字继续搜索

有人提到编译驱动要加 “-DKERNEL -DMODULE ”

于是

编译写成如下格式

arm-linux-gcc -DKERNEL -DMODULE -I/armsys2410/kernel/include -c led.c

仍旧有问题

没办法,看代码再

发现下面的两句 KERNEL前后的 下划线似乎有点短了,如下:

#ifndef _KERNEL_

#define _KERNEL_

 

改为:

(下面是两个下划线是两横 嘿嘿)

#ifndef __KERNEL__

#define __KERNEL__

再编译

arm-linux-gcc -DKERNEL -DMODULE -I/armsys2410/kernel/include -c led.c

哈哈 通过了,没有警告也没有错误,兴奋了一把

当前的目录下也多了个 led.o文件 嘿嘿

上传到开发板

修改其权限:

# chmod 777 led.o

挂载:

# insmod ./led.o

查看:

# cat /proc/devices

Character devices:

  1 mem

  2 pty/m%d

  3 pty/s%d

  4 vc/0

  5 ptmx

  7 vcs

 10 misc

 29 fb

 90 mtd

128 ptm

136 pts/%d

162 raw

204 ttyS%d

205 cua%d

232 leds

创建设备文件

# mknod /dev/leds c 243 0

 

查看

# ls /dev

bon          fb           misc         ptmx         shm          ttyS2

console      full         mtd          pts          touchscreen  urandom

cua0         kmem         mtdblock     pty          tty          vc

cua1         leds         null         random       ttyS0        vcc

cua2         mem          port         root         ttyS1        zero

#

 

测试程序

#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;

    if(argc!=3||sscanf(argv[1],"%d",&led_no)!=1|| sscanf(argv[2],"%d",&no)!=1 || on<0 || on>1 ||led_no<0 || led_no>3)

    {

        fprintf(stderr,"Usage:led led_no 1|0/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;

}

 

 

[root@localhost sin]# arm-linux-gcc -o ledtest led-test.c

[root@localhost sin]# ls

example-leds.c  hh     led.o   ledss.c  led-test.c  test.c  tt

hello.c         led.c  leds.c  ledtest  Makefile    test.o

[root@localhost sin]# cp ./ledtest /mnt/hgfs/share

 

上传到 开发板的 tmp目录

# chmod 777 ledtest

# ls

erase    led.o    ledtest

# ./ledtest 1 1

open device leds: No such device

# ./ledtest 1 1

open device leds: No such device

# ./ledtest 0 1

open device leds: No such device

 

居然说没有??真是奇怪了,哪里又出错了呢?

 

建立接点时出错了,驱动中用的主设备号是:232

而建立时用的是:243, 所以提示“open device leds: No such device”

不知道教程上,怎么出现这么个意外?

我也是网上搜索后,才知道这么个情况(所以啊,基础的东西还是要好好学习学习的)

后修改如下:

 

# mknod /dev/leds c 232 0

# ls /dev

bon          fb           misc         ptmx         shm          ttyS2

console      full         mtd          pts          touchscreen  urandom

cua0         kmem         mtdblock     pty          tty          vc

cua1         leds         null         random       ttyS0        vcc

cua2         mem          port         root         ttyS1        zero

# ./ledtest 0 1

# ./ledtest 1 1

# ./ledtest 2 1

# ./ledtest 3 1

 

OK, 板子上的LED有反应了 呵呵

 

Logo

更多推荐