Linux驱动练手-驱动LED

来源:互联网 发布:json static.lib 编辑:程序博客网 时间:2024/05/17 01:16

 经过一段时间的,翻过了好几本书,大致上理解了linux驱动的基本步骤。从驱动LED入手实践操作,一路碰钉不少。经过一番挣扎,还是成功地让LED在开发板上闪起来!下面将粗略分享下过程。

建立交叉编译环境

       scrosstools3.4.1,解压后放到指定目录。再对 /etc/profile 文件修改相关信息。再执行命令

source /etc/profile

可将该交叉编译器成为当前默认编译器。

执行命令

arm-linux-gcc –v

可以检测该编译器安装是否成功。

驱动程序

       Linux的外设可以分为3类:字符设备 (character device) 、块设备(block device)和网络接口(network interface)

       这里LED以字符设备类型驱动。LED驱动程序文件名为 s3c24xx_leds.c ,将它放置内核代码中的 /kerner/drivers/char ,用于往后的编译工作。

       先来看看s3c24xx_leds.c 文件中主要有那些函数:

(以下为《嵌入式linux开发完全手册》中的程序)

/* 应用程序对设备文件/dev/leds执行open(...)时,

 * 就会调用s3c24xx_leds_open函数

 */

static int s3c24xx_leds_open(struct inode *inode, struct file *file)

 

 

/* 应用程序对设备文件/dev/leds执行ioclt(...)时,

* 就会调用s3c24xx_leds_ioctl函数

*/

static int s3c24xx_leds_ioctl(

    struct inode *inode,

    struct file *file,

    unsigned int cmd,

unsigned long arg)

 

/* 这个结构是字符设备驱动程序的核心

 * 当应用程序操作设备文件时所调用的openreadwrite等函数,

 * 最终会调用这个结构中指定的对应函数

 */

static struct file_operations s3c24xx_leds_fops = {

    .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */

    .open   =   s3c24xx_leds_open,    

    .ioctl  =   s3c24xx_leds_ioctl,

};

 

/*

 * 执行“insmod s3c24xx_leds.ko”命令时就会调用这个函数

 */

static int __init s3c24xx_leds_init(void)

{

       /* 注册字符设备驱动程序

     * 参数为主设备号、设备名字、file_operations结构;

     * 这样,主设备号就和具体的file_operations结构联系起来了,

     * 操作主设备为LED_MAJOR的设备文件时,就会调用s3c24xx_leds_fops中的相关成员函数

     * LED_MAJOR可以设为0,表示由内核自动分配主设备号

     */

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

.

.

.

 

}

 

/*

* 执行”rmmod s3c24xx_leds.ko”命令时就会调用这个函数

*/

static void __exit s3c24xx_leds_exit(void)

 

 

       要加LED到内核里面,首先要为LED设备获得一个注册号,即主、次设备号。可以自定义主设备号,但是要确保该号不能被其它设备使用,也可以让主设备好为0,让系统自动分配。这里我定义主设备号为222

       理解驱动程序中函数的功能后,现在可以进行编译。执行命令

make modules SUBDIRS=drivers/char

       编译字符设备驱动,编译成功后,可以在该文件夹下找到s3c24xx_leds.ko 文件。将它放到开发板的文件夹中(如/mydevices),执行命令加载驱动设备

insmod s3c24xx_leds.ko

没有返回错误提示,则加载成功。执行命令

 lsmod

可以看见该该驱动设备的信息。

Module                  Size  Used by    Not tainted

s3c24xx_leds            2048  0

测试程序

       驱动加载成功后,还需要应用程序对设备的控制。

 

int main(void)

{

    int fd = -1;

 

    fd = open("/dev/led", 0);  // 打开设备

    if (fd < 0) {                  //打开设备失败

        printf("Can't open /dev/led/n");

        return -1;

    }

    else {printf("led is running");//打开设备成功

     printf("by:jammy-lee");}

 

    ioctl(fd, IOCTL_LED_ON, 0);     

    ioctl(fd, IOCTL_LED_OFF, 1);   

    ioctl(fd, IOCTL_LED_OFF, 2);   

    ioctl(fd, IOCTL_LED_ON, 3);     

}

 

       上面的程序中fd = open("/dev/led", 0); 可以看到,/dev/led 为设备文件,所以还需要执行命令建立设备文件

mknod /dev/led c 222 0

其中,c代表字符设备,222为主设备号,0为次设备号。那么应用程序通过读写led设备文件,从而连接到s3c24xx_leds.ko 中的函数操作。

       执行命令编译应用程序

arm-linux-gcc –o led_test led_test.c  %编译程序

arm-linux-strip led_test                   %去掉led_test调试部分,生成的程序小很多

 

       一开始运行应用程序的时候,发现不能运行"-sh: ./led_test: Permission denied"。以为是编译出了问题,反复安装交叉编译以及编译程序还是不能解决。后来请教一下高人,才知道是权限问题,导致不能运行。执行指令

chmod 777 led_test

程序真的能动起来!激动啊!!!!

作者:jammy_lee 

原创粉丝点击