点亮led过程分析

来源:互联网 发布:数据储存 编辑:程序博客网 时间:2024/05/19 02:29

在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.oelseKDIR := /opt/FriendlyARM/mini2440/linux-2.6.32.2_faall:make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-clean:rm -f *.ko *.o *.mod.o *.mod.c *.symversendif

拷贝到开发板上,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,是亮还是灭,能成功。

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


原创粉丝点击