免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 971 | 回复: 0
打印 上一主题 下一主题

LED驱动阅读 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-18 23:40 |只看该作者 |倒序浏览
整理一下思路,刚刚看的mini2440 led驱动。

mini2440的led接了4个GPIO,分别是GPB5-8
关于这几个GPIO的寄存器描述可以看三星的文档,主要是GPBCON,GPBDAT和GPBUP,GPBCON寄存器可以表示某引脚是输入功能还是输出功能,因为这些引脚是复用的。GPBDAT用来给某引脚读写数据的。GPBUP表示是否使用内部上拉电阻,这里没有用上,貌似,不懂。

linux对ARM支持很好,有关gpio的操作都有函数写好了,直接用就可以。
以前真是傻呀,自己写,呵呵。

linux/arch/arm/plat-s3c24xx/gpio.c描述了对gpio的操作,这里用到两个函数:
s3c2410_gpio_cfgpin(led_table, led_cfg_table);
s3c2410_gpio_setpin(led_table, 0);
第一个函数是设置led_table表示的引脚为输入或者输出(led_cfg_table定义的),其实就是设置GPBCON寄存器;
第二个函数是设置引脚读写数据为0或者其他值,比如1.
led_table, led_cfg_table在这个文件里都有定义,定义中涉及的宏S3C2410_GPB6 和S3C2410_GPB6_OUTP 之类都在arch/arm/mach-s3c2410/include/mach/regs-gpio.h中定义好了。
下面的就是LED的驱动程序:

#include linux/miscdevice.h>
#include linux/delay.h>
#include asm/irq.h>
#include mach/regs-gpio.h>
#include mach/hardware.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>
#define DEVICE_NAME "leds" 设备名
static unsigned long led_table [] = {  4个对应的引脚
    S3C2410_GPB5,
    S3C2410_GPB6,
    S3C2410_GPB7,
    S3C2410_GPB8,
};
static unsigned int led_cfg_table [] = {  引脚功能都是输出
    S3C2410_GPB5_OUTP,
    S3C2410_GPB6_OUTP,
    S3C2410_GPB7_OUTP,
    S3C2410_GPB8_OUTP,
};
static int sbc2440_leds_ioctl(   ioctl具体实现,对应应用程序中的ioctl
    struct inode *inode,
    struct file *file,   这个参数对应应用程序中的第一个参数,文件
    unsigned int cmd, 两个值,0或1,led灭或者亮
    unsigned long arg)  参数个数,不能超过4,表示只有4个led
{
    switch(cmd) {
    case 0:
    case 1:
        if (arg > 4) {
            return -EINVAL;
        }
        s3c2410_gpio_setpin(led_table[arg], !cmd); 设置某个led数据0或1
        return 0;
    default:
        return -EINVAL;
    }
}
file_operations 数据结构填充
static struct file_operations dev_fops = {
    .owner    =    THIS_MODULE,
    .ioctl    =    sbc2440_leds_ioctl,对应的ioctl函数实现
};
misc设备,也就是非字符,非块,非网络,其他设备。这种设备统一采用一个主设备号
static struct miscdevice misc = {
    .minor = MISC_DYNAMIC_MINOR, 次设备号
    .name = DEVICE_NAME,
    .fops = &dev_fops,
};
static int __init dev_init(void)  初始化设备
{
    int ret;
    int i;
   
    for (i = 0; i  4; i++) {
       设置引脚为输出功能
        s3c2410_gpio_cfgpin(led_table, led_cfg_table);
       各引脚写入0,即都是不亮的
       s3c2410_gpio_setpin(led_table, 0);
    }
    ret = misc_register(&misc); 注册misc设备
    printk (DEVICE_NAME"\tinitialized\n");
    return ret;
}
static void __exit dev_exit(void)
{
    misc_deregister(&misc);  注销misc设备
}
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("FriendlyARM Inc.");
led的应用程序如下:
#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条件表示,有三个参数,on的值只能是0或者1,led_no的值只能是0-3
    //sscanf的返回值为0,出错,否则返回正确格式化数据的个数,这样就确保main参数每个都读的争取
    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/leds0", 0);  不知道什么意思?
    if (fd  0) {
        fd = open("/dev/leds", 0); 读取设备
    }
    if (fd  0) {
        perror("open device leds");
        exit(1);
    }
    ioctl(fd, on, led_no);  调用ioctl,和驱动里的对应。不过那个ioctl函数貌似四个参数,第一个参数是inode节点,后面三个和这里是对应的,有点茫然。
    close(fd);
    return 0;
}
交叉编译后,执行:
#./led 2 1
第三个led亮


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/45113/showart_1903718.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP