Chinaunix首页 | 论坛 | 博客
  • 博客访问: 46948
  • 博文数量: 15
  • 博客积分: 45
  • 博客等级: 民兵
  • 技术积分: 85
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-14 16:12
个人简介

Nothing to tell

文章分类

全部博文(15)

文章存档

2015年(1)

2012年(14)

我的朋友
最近访客

分类:

2012-07-17 18:36:02

移植步骤:

1. 由原理图得知LED电路是共阳极的,并分别由2440GPF0GPF1GPF2GPF3口控制的.

2. 去掉内核已有的LED驱动设置,因为IO口与mini2440开发板的不一致,根本就不能控制板上的LED

#gedit arch/arm/plat-s3c24xx/common-smdk.c

#if 0
/* LED devices */

static struct s3c24xx_led_platdata smdk_pdata_led4 = {
    .gpio        = S3C2410_GPF(4),
    .flags        = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
    .name        = "led4",
    .def_trigger    = "timer",
};

static struct s3c24xx_led_platdata smdk_pdata_led5 = {
    .gpio        = S3C2410_GPF(5),
    .flags        = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
    .name        = "led5",
    .def_trigger    = "nand-disk",
};

static struct s3c24xx_led_platdata smdk_pdata_led6 = {
    .gpio        = S3C2410_GPF(6),
    .flags        = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
    .name        = "led6",
};

static struct s3c24xx_led_platdata smdk_pdata_led7 = {
    .gpio        = S3C2410_GPF(7),
    .flags        = S3C24XX_LEDF_ACTLOW | S3C24XX_LEDF_TRISTATE,
    .name        = "led7",
};

static struct platform_device smdk_led4 = {
    .name        = "s3c24xx_led",
    .id        = 0,
    .dev        = {
        .platform_data = &smdk_pdata_led4,
    },
};

static struct platform_device smdk_led5 = {
    .name        = "s3c24xx_led",
    .id        = 1,
    .dev        = {
        .platform_data = &smdk_pdata_led5,
    },
};

static struct platform_device smdk_led6 = {
    .name        = "s3c24xx_led",
    .id        = 2,
    .dev        = {
        .platform_data = &smdk_pdata_led6,
    },
};

static struct platform_device smdk_led7 = {
    .name        = "s3c24xx_led",
    .id        = 3,
    .dev        = {
        .platform_data = &smdk_pdata_led7,
    },
};
#endif


/* devices we initialise */

static struct platform_device __initdata *smdk_devs[] = {
    &s3c_device_nand,
#if 0        
    &smdk_led4,
    &smdk_led5,
    &smdk_led6,
    &smdk_led7,
#endif    
};


void __init smdk_machine_init(void)
{
    /* Configure the LEDs (even if we have no LED support)*/
#if 0
    s3c2410_gpio_cfgpin(S3C2410_GPF(4), S3C2410_GPIO_OUTPUT);
    s3c2410_gpio_cfgpin(S3C2410_GPF(5), S3C2410_GPIO_OUTPUT);
    s3c2410_gpio_cfgpin(S3C2410_GPF(6), S3C2410_GPIO_OUTPUT);
    s3c2410_gpio_cfgpin(S3C2410_GPF(7), S3C2410_GPIO_OUTPUT);

    s3c2410_gpio_setpin(S3C2410_GPF(4), 1);
    s3c2410_gpio_setpin(S3C2410_GPF(5), 1);
    s3c2410_gpio_setpin(S3C2410_GPF(6), 1);
    s3c2410_gpio_setpin(S3C2410_GPF(7), 1);
#endif
    if (machine_is_smdk2443())
        smdk_nand_info.twrph0 = 50;

    s3c_device_nand.dev.platform_data = &smdk_nand_info;

    platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));

    s3c_pm_init();
}


3. 编写适合mini2440开发板的LED驱动,代码如下,文件名称:mxh2440_led.c

/*
 ==============================================
 Name : mxh2440_led.c.c
 Author : mxh20999
 Date : 12/11/2010
 Copyright : GPL
 Description : my2440 led driver
 ==============================================
 */


#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <mach/hardware.h>
#include <mach/regs-gpio.h>
#include <asm/gpio.h> //包含s3c2410_gpio_setpin和s3c2410_gpio_cfgpin

#define DEVICE_NAME "mxh2440_led" //设备名称,将出现在/dev/mxh2440_led

#define LED_MAJOR 231 //主设备号
#define LED_ON 1 //LED亮状态
#define LED_OFF 0 //LED灭状态

static unsigned long led_table[] = //控制LED的IO口
{
    S3C2410_GPF(0),
    S3C2410_GPF(1),
    S3C2410_GPF(2),
    S3C2410_GPF(3),
};


static int leds_open(struct inode *inode, struct file *file)
{
    return 0;
}
/*

*在应用/用户层将通过 ioctl 函数向内核传递参数,以控制 LED的输出状态

*/
static int leds_ioctl(struct inode *inode, struct file *file,
                     unsigned int cmd, unsigned long arg)
{
    //检测是第几个LED,因开发板上只有4个,索引从0开始 
    if(arg < 0 || arg > 3)
    {
        return -EINVAL;
    }

    //判断LED要执行哪种状态
    switch(cmd)
    {
        case LED_ON:
        {
            s3c2410_gpio_setpin(led_table[arg], ~(LED_ON));
            break;
        }
        case LED_OFF:
        {
            s3c2410_gpio_setpin(led_table[arg], ~(LED_OFF));
            break;
        }
        default:
        {
            return -EINVAL;
        }
    }

    return 0;
}
/*
*  设备函数操作集,在此只有 ioctl函数,通常还有 read, write, open, close 等*/
static struct file_operations leds_fops =
{
    .owner = THIS_MODULE,
    .open = leds_open,
    .ioctl = leds_ioctl,
};

/*
*  设备初始化
*/
static int __init led_init(void)
{
    int ret, i;

    for(i = 0; i < 4; i++)
    {
        //初始化各IO口为输出模式
        s3c2410_gpio_cfgpin(led_table[i], S3C2410_GPIO_OUTPUT);
        

        //这里初始化为1,不让LED点亮
        s3c2410_gpio_setpin(led_table[i], ~(LED_OFF));
    }

    //注册LED设备为字符设备
    ret = register_chrdev(LED_MAJOR, DEVICE_NAME, &leds_fops);

    if(ret < 0)
    {
        printk(DEVICE_NAME " register falid!\n");
        return ret;
    }
}

/*
注销设备
*/

static void __exit led_exit(void)
{
    unregister_chrdev(LED_MAJOR, DEVICE_NAME);
}

module_init(led_init);//模块初始化,仅当使用 insmod/podprobe 命令加载时有用,如果设备不是通过模块方式加载,此处将不会被调用
module_exit(led_exit);//卸载模块,当该设备通过模块方式加载后,可以通过 rmmod 命令卸载,将调用此函数

MODULE_LICENSE("GPL");//版权信息
MODULE_AUTHOR("mxh20999");//开发者信息
MODULE_DESCRIPTION("mxh2440 led driver");//模块描述

4.接下来,我们添加LED设备的内核配置选项,打开 drivers/char/Kconfig文件,添加如
下红色部分内容:

config MXH2440_LED
    tristate "mxh2440 Led Device"
    depends on ARCH_S3C2440
    default y
    ---help---
    mxh2440 User Leds


5.接下来,再根据该驱动的配置定义,把对应的驱动目标文件加入内核中,打开drivers/char/Makefile文件,添加如下红色部分内容:

obj-$(CONFIG_MXH2440_LED)    += mxh2440_led.o


6. 配置内核,选择LED设备选项

#make menuconfig

Device Drivers --->
    Character devices --->
        <*> mxh2440 Leds Device (NEW)


7. 编译内核并下载到开发板上,查看已加载的设备:#cat /proc/devices,可以看到mhx2440_led的主设备号为231.故建立节点

#mknod /dev/mxh2440_led c 231 0

8. 编写应用程序测试LED驱动,文件名:led_test.c

/*
 ==============================================
 Name : leds_test.c
 Author : mxh20999
 Date : 12/11/2010
 Copyright : GPL
 Description : mxh2440 leds driver test
 ==============================================
 */


#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>

int main(int argc, char **argv)
{
    int turn, index, fd;

    //检测输入的参数合法性

    if(argc != 3 || sscanf(argv[2], "%d", &index) != 1 || index < 1 || index > 4)
    {
        printf("Usage: leds_test on|off 1|2|3|4\n");
        exit(1);
    }

    if(strcmp(argv[1], "on") == 0)
    {
        turn = 1;
    }
    else if(strcmp(argv[1], "off") == 0)
    {
        turn = 0;
    }
    else
    {
        printf("Usage: leds_test on|off 1|2|3|4\n");
        exit(1);
    }

    //打开LED设备

    fd = open("/dev/mxh2440_led", 0);

    if(fd < 0)
    {
        printf("Open Led Device Faild!\n");
        exit(1);
    }

    //IO控制

    ioctl(fd, turn, index - 1);

    //关闭LED设备

    close(fd);

    return 0;
}


9. 在开发主机上交叉编译测试应用程序.

#arm-linux-gcc leds_test.c -o led_test

10.将生成的led_test通过串口,网络,或者usb下载到开发板。运行:

./led_test on 1

则开发板上对应的LED1点亮。

阅读(811) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~