点亮led过程分析

在mini2440中,led,按键等驱动默认已经被编译入内核,所以一直不知道同一个硬件设备资源能不能作为多个模块,编译入内核。

故重写了一个myled.ko,系统默认是led.ko,并用应用程序检测。

myled.c 

#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/gpio.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/mm.h>
#include <linux/device.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>
//**************
static struct device *dev;
//*************
#define DEVICE_NAME "myled"
static struct cdev *cdevp=NULL;//定义一个cdev结构体,并初始化
static dev_t devno;//定义一个设备号
static unsigned long led_table[] = {
   S3C2410_GPB(5),//定义端口
    S3C2410_GPB(6),
    S3C2410_GPB(7),
    S3C2410_GPB(8),
};
static unsigned int led_cfg_table[] = {
    S3C2410_GPIO_OUTPUT,//定义寄存器状态
    S3C2410_GPIO_OUTPUT,
    S3C2410_GPIO_OUTPUT,
    S3C2410_GPIO_OUTPUT,
};
static int s3c2440_leds_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg)
{
    switch(cmd)
    {
        case 0:
        case 1:
            if(arg>3)
            {
                return -EINVAL;
             }
        s3c2410_gpio_setpin(led_table[arg],!cmd);
        return 0;
        default:
            return -EINVAL;
     }
}
//应用程序与驱动映
static struct file_operations myled_fops = {
    .owner = THIS_MODULE,
    .ioctl = s3c2440_leds_ioctl,
};
//**************
static struct class *led_class;
//**************
static int __init myled_init_module(void)
{
    int ret;
    int i,err;
    ret = alloc_chrdev_region(&devno,0,1,DEVICE_NAME);//注册设备
    if(ret < 0)
    {
        printk(DEVICE_NAME "can't get the major number\n");
        return ret;
    }
//****************************
    led_class= class_create(THIS_MODULE,DEVICE_NAME);
  if(IS_ERR(led_class))
{
printk("Err: failed in leds-class.\n");
return -1;
}
   dev=device_create(led_class,NULL,devno,NULL,DEVICE_NAME);
//**************************
    cdevp = cdev_alloc();//动态申请一个cdev内存
    cdev_init(cdevp,&myled_fops);//初始化cdev
    cdevp->owner = THIS_MODULE;
    err=cdev_add(cdevp,devno,1);
    if(err)
    {
    printk(KERN_NOTICE "Error %d adding cdev",err);
      unregister_chrdev_region(devno,1);
       return -EFAULT;
    }
     for(i=0;i<4;i++)
    {
        s3c2410_gpio_cfgpin(led_table[i],led_cfg_table[i]);
         s3c2410_gpio_setpin(led_table[i],1)
    }
    printk(DEVICE_NAME "\tinitialized! 2012-12-9\n");
    return 0;
}
static void __exit myled_exit_module(void)
{
    cdev_del(cdevp);
    unregister_chrdev_region(devno,1);
//****************
    device_destroy(led_class,devno);
    class_destroy(led_class);
/*****************
    printk(DEVICE_NAME "\tunloaded by tong2012-12-9\n");

}
module_init(myled_init_module);
module_exit(myled_exit_module);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("tong 2012-12-9");

Makefile如下

ifneq ($(KERNELRELEASE),)
obj-m:=myled.o
else
KDIR := /opt/FriendlyARM/mini2440/linux-2.6.32.2_fa
all:
make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers
endif

拷贝到开发板上,insmod myled.ko可在/dev下生成设备节点myled.ko

现在采用系统给出的例程,但修改设备节点为myled,

led.c (必须使用交叉编译器)

#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", &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/myled", 0);
if (fd < 0) {
fd = open("/dev/myled", 0);
}
if (fd < 0) {
perror("open device leds");
exit(1);
}
ioctl(fd, on, led_no);
close(fd);
return 0;
}


先用/etc/rc.d/init.d/leds stop关闭系统初始化中,开启的让四个led循环闪动的服务,

通过ioctl函数可以控制让哪个led,是亮还是灭,能成功。

说明了,同一个硬件设备资源能被作为多个模块,换成不同的名字,互不干扰,也就是说可以同时硬件资源可以为应用程序中的多种服务工作,可以联想一下智能手机是如何工作的。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值