查看: 29114|回复: 10

BeagleBone Black Linux驱动程序开发入门(1): LED驱动程序

  [复制链接]
  • TA的每日心情
    开心
    2013-8-7 09:31
  • 签到天数: 5 天

    连续签到: 1 天

    [LV.2]偶尔看看I

    发表于 2013-7-12 08:08:23 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 dolphi 于 2013-7-12 08:15 编辑

    这篇文章展示如何在BBB平台上编写LED驱动程序,本文的程序是根据国嵌S3C2440的LED驱动的例子并结合内核中OMAP系列的gpio操作来改的。本文中的程序包括驱动程序模块和用户空间程序。废话不多说,先贴程序出来吧。
    /****************************************************
    am3359_leds_misc.c
    *****************************************************/
    /***************头文件也许不用包含这么多*************/
    #include <linux/miscdevice.h>
    #include <linux/delay.h>
    //#include <asm/irq.h>
    #include <linux/gpio.h>
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/mm.h>
    #include <linux/fs.h>
    #include <linux/types.h>
    #include <linux/delay.h>
    #include <linux/moduleparam.h>
    #include <linux/slab.h>
    #include <linux/errno.h>
    #include <linux/ioctl.h>
    #include <linux/cdev.h>
    #include <linux/string.h>
    #include <linux/list.h>
    #include <linux/pci.h>
    #include <asm/uaccess.h>
    #include <asm/atomic.h>
    #include <asm/unistd.h>
    #include <asm/io.h>
    #include <asm/system.h>
    #include <asm/uaccess.h>
    //#include <mux.h>
    #include "memdev.h"
    #define DEVICE_NAME "leds"
    static unsigned long led_table[] = { 53, 54, 55,56, };
    /*static unsigned intled_cfg_table[] = { OMAP_PIN_OUTPUT, OMAP_PIN_OUTPUT,
           OMAP_PIN_OUTPUT, OMAP_PIN_OUTPUT, };*/
    static int sbc2440_leds_ioctl(
        struct file *file,
        unsigned int cmd,
        unsigned long arg) {
        int i = 0;
        /* 检测命令的有效性 */
        if (_IOC_TYPE(cmd) != MEMDEV_IOC_MAGIC)
           return -EINVAL;
        if (_IOC_NR(cmd) > MEMDEV_IOC_MAXNR)
           return -EINVAL;
        printk("here in kernel ioctl\n");
        /* 根据命令,执行相应的操作 */
        switch (cmd) {
        case MEMDEV_IOCOFF:
           /*灯全灭*/
           cmd = 0;
           for (i = 0; i < 4; i++)
               gpio_set_value(led_table, cmd);
        return 0;
        case MEMDEV_IOCON:
           /*灯全亮*/
           cmd = 1;
           for (i = 0; i < 4; i++)
               gpio_set_value(led_table, cmd);
           return 0;
        default:
           return -EINVAL;
        }
    }
    /*文件操作结构体*/
    static struct file_operations dev_fops = { .owner = THIS_MODULE, .unlocked_ioctl =
           sbc2440_leds_ioctl, };
    static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR, .name =
           DEVICE_NAME, .fops = &dev_fops, };
    static int __init dev_init(void)
    {
        int ret;
        int i;
        /*设置GPIO控制寄存器,GPIO设置为输出模式,默认下灯全灭*/
        for (i = 0; i < 4; i++) {
    //     这四个引脚内核中已经初始化为输出了
    //     omap_mux_init_gpio(led_table, led_cfg_table);
           gpio_set_value(led_table, 1);
        }
        /*注册混杂型字符设备驱动*/
        ret = misc_register(&misc);
        printk (DEVICE_NAME"\tinitialized\n");
        return ret;
    }
    static void __exit dev_exit(void)
    {
        int i;
        for (i = 0; i < 4; i++) {
               gpio_set_value(led_table, 0);
           }
        printk(DEVICE_NAME"\tdrivermodule exit\n");
        /*注销混杂型字符设备驱动*/
        misc_deregister(&misc);
    }
    module_init(dev_init)
    ;
    module_exit(dev_exit)
    ;
    MODULE_AUTHOR("David Xie")
    ;
    MODULE_LICENSE("GPL")
    ;
    /*****************************************************************
    memdev.h
    *****************************************************************/
    #ifndef _MEMDEV_H_
    #define _MEMDEV_H_
    #include <linux/ioctl.h>
    /* 定义幻数 */
    #define MEMDEV_IOC_MAGIC  'k'
    /* 定义命令 */
    #define MEMDEV_IOCON  _IO(MEMDEV_IOC_MAGIC, 1)
    #define MEMDEV_IOCOFF _IO(MEMDEV_IOC_MAGIC, 2)
    #define MEMDEV_IOC_MAXNR 2
    #endif /* _MEMDEV_H_ */
    /*******************************************************************
    Makefile
    ********************************************************************/
    ifneq ($(KERNELRELEASE),)
    obj-m := am3359_leds_misc.o
    else
       
    KDIR := /root/beaglebone/origin-kernel/kernel/
    all:
        make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
    clean:
        rm -f *.ko *.o *.mod.o *.mod.c *.symvers  modul*
       
    endif
    以上就是内核模块的所有代码了。在Ubuntu中make一下,马上就得到了一个内核模块am3359_leds_misc.ko,用SSH把它和下面这个appled.c以及上面的memdev.h头文件COPY到板子的/home/root/drivers/led文件夹里面(user app可以直接在板子上编译)。
    /********************************************************************
    appled.c
    ********************************************************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    #include "memdev.h"  /* 包含命令定义 */
    int main(int argc, char **argv)
    {
        int on;
        int fd;
        if (argc != 2 || sscanf(argv[1],"%d", &on) != 1 ||on < 0 ||on > 1 ) {
           fprintf(stderr, "Usage:%s0|1\n",argv[0]);
           exit(1);
        }
        fd = open("/dev/leds", 0);
        if (fd < 0) {
           perror("open deviceleds");
           exit(1);
        }
        /*通过ioctl来控制灯的亮、灭*/
        if(on){
           printf("turn on allleds!\n");
           ioctl(fd,  MEMDEV_IOCON,0);
        }
        else {
           printf("turn offall leds!\n");
           ioctl(fd, MEMDEV_IOCOFF, 0);
        }
        close(fd);
        return 0;
    }
    输入以下命令编译用户程序:
    gcc appled.c-o appled
    加载led驱动模块之前运行以下命令可以关闭所有四个led:
    /usr/bin/led_aging.sh~
    输入以下命令加载led驱动模块:
    insmod  am3359_leds_misc.ko
    运行LED用户程序:
    ./appled 1
    参数为1的时候所有4LED被点亮.
    ./appled 0
    参数为0的时候所有4LED熄灭.
    回复

    使用道具 举报

  • TA的每日心情
    开心
    2013-8-7 09:31
  • 签到天数: 5 天

    连续签到: 1 天

    [LV.2]偶尔看看I

     楼主| 发表于 2013-7-12 08:09:12 | 显示全部楼层
    为什么自动变成斜体{:soso_e116:}
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2015-8-5 11:09
  • 签到天数: 3 天

    连续签到: 1 天

    [LV.2]偶尔看看I

    发表于 2013-7-12 08:44:51 | 显示全部楼层
    mark,顶楼主!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2020-9-28 10:10
  • 签到天数: 1018 天

    连续签到: 1 天

    [LV.10]以坛为家III

    发表于 2013-7-15 09:02:43 | 显示全部楼层
    dolphi 发表于 2013-7-12 08:09
    为什么自动变成斜体

    楼主指哪儿自动斜体啦?
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2013-8-7 09:31
  • 签到天数: 5 天

    连续签到: 1 天

    [LV.2]偶尔看看I

     楼主| 发表于 2013-7-16 08:44:10 | 显示全部楼层
    xinxincaijq 发表于 2013-7-15 09:02
    楼主指哪儿自动斜体啦?

    我自己改过来了,不知道怎么的,发的时候,文章后半部分自动变成了斜体
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    发表于 2013-9-3 10:38:44 | 显示全部楼层
    期待第二篇啊!
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    2014-11-15 21:16
  • 签到天数: 179 天

    连续签到: 1 天

    [LV.7]常住居民III

    发表于 2013-10-21 12:34:25 | 显示全部楼层
    用linux肿么感觉很麻烦的样子。。。。
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2018-12-13 08:40
  • 签到天数: 138 天

    连续签到: 1 天

    [LV.7]常住居民III

    发表于 2015-9-17 15:50:14 | 显示全部楼层
    楼主明显是根据2440程序改编过来的,我想问一下omap_mux_init_gpio(led_table, led_cfg_table);这种怎么控制gpio啊,我写了驱动程序,可是老是提示我这种结构体没有定义,不知道头文件怎么添加进去,
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    奋斗
    2022-8-28 11:59
  • 签到天数: 1558 天

    连续签到: 1 天

    [LV.Master]伴坛终老

    发表于 2015-9-17 19:44:22 | 显示全部楼层
    看看,学习啦
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    开心
    2017-12-27 09:25
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    发表于 2017-12-27 11:01:10 | 显示全部楼层
    谢谢分享。
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-11-20 02:33 , Processed in 0.200895 second(s), 32 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.