三星S5PV210Android系统下LED灯驱动程序

来源:互联网 发布:mac网络还原 编辑:程序博客网 时间:2024/06/11 13:02

驱动文件:hello.c

/************************************************
LED的驱动,在Real210A开发板上做测试

维护记录:  2011-10-31  V1.0    

linux内核:2.6.35.7

驱动用法:
        设备名称:Real210-led
        点亮一个灯:LED_ON
        熄灭一个灯:LED_OFF
        点亮所有灯:ALL_LED_ON
        熄灭所有灯:ALL_LED_OFF
*************************************************/
#include<linux/init.h>
#include<linux/module.h>

#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/device.h>
#include <linux/gpio.h>

#define DEVICE_NAME    "Real210-led"    /* 设备名称 */        
static int LED_Major = 0;            /* 主设备号 ,系统自动分配*/

#define LED_OFF             0
#define LED_ON             1
#define ALL_LED_OFF      3
#define ALL_LED_ON       4

/* 用来指定LED所用的GPIO引脚 */
static unsigned long led_table [] =
{
    //S5PV210_GPH0(_nr);
    //在头文件“~/kernel/arch/arm/mach-s5pv210/include/mach/”

    S5PV210_GPH0(6),
    S5PV210_GPH0(7),
    S5PV210_GPH0(4),
    S5PV210_GPH0(5),
};

static int Real210_led_open(struct inode *inode, struct file *file)
{
//    MOD_INC_USE_COUNT;
    printk("Real210-LED Driver Open Called!\n");
    return 0;
}

static int Real210_led_release(struct inode *inode, struct file *file)
{
//    MOD_DEC_USE_COUNT;
    printk("Real210-LED Driver Release Called!\n");
    return 0;
}

static int Real210_led_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
    int i;
    if (arg > 4)
    {
        return -EINVAL;
    }
    switch(cmd)
    {
        case LED_ON:  //set the pin
            gpio_set_value (led_table[arg], 0);
            break;

        case LED_OFF:  //clr the pin
            gpio_set_value (led_table[arg], 1);
            break;
            
        case ALL_LED_ON:  //set all pin
            for (i = 0; i < 4; i++)
                gpio_set_value (led_table[i], 0);
            break;
            
        case ALL_LED_OFF:  //clr all pin
            for (i = 0; i < 4; i++)
                gpio_set_value (led_table[i], 1);
            break;

        default:
            return -EINVAL;
    }
}

static struct file_operations Real210_led_fops =
{
    .owner  =   THIS_MODULE,
    .open   =   Real210_led_open,
    .release =  Real210_led_release,
    .ioctl  =   Real210_led_ioctl,
};

static struct class *led_class;

static int __init Real210_led_init(void)
{

    printk("Real210 LED DRIVER MODULE INIT\n");

    LED_Major = register_chrdev(0, DEVICE_NAME, &Real210_led_fops);
    if (LED_Major < 0)
    {
        printk(DEVICE_NAME " can't register major number\n");
        return LED_Major;
    }
    printk("register Real210-LED Driver OK! Major = %d\n", LED_Major);

    led_class = class_create(THIS_MODULE, DEVICE_NAME);
    if(IS_ERR(led_class))
    {
        printk("Err: failed in Real210-LED class. \n");
        return -1;
    }

    device_create(led_class, NULL, MKDEV(LED_Major, 0), NULL, DEVICE_NAME);

    //IO初始化
    
    //IO方向配置
    gpio_direction_output (S5PV210_GPH0(6), 1);
    gpio_direction_output (S5PV210_GPH0(7), 1);
    gpio_direction_output (S5PV210_GPH0(4), 1);
    gpio_direction_output (S5PV210_GPH0(5), 1);  
    //IO初始化
    gpio_set_value (S5PV210_GPH0(6), 1);
    gpio_set_value (S5PV210_GPH0(7), 0);

    printk(DEVICE_NAME " initialized\n");
    return 0;
}

static void __exit Real210_led_exit(void)
{
    printk("Real210 LED DRIVER MODULE EXIT\n");
    unregister_chrdev(LED_Major, DEVICE_NAME);
    device_destroy(led_class, MKDEV(LED_Major, 0));
    class_destroy(led_class);
}

module_init(Real210_led_init);
module_exit(Real210_led_exit);

//MODULE_LICENSE("Dual BSD/GP");

MODULE_LICENSE("GPL");
MODULE_AUTHOR("wzl");
MODULE_DESCRIPTION("This is an example of hello drivers");
MODULE_ALIAS("A simplest module.");

Makefile文件:

ifneq ($(KERNELRELEASE),)

obj-m := hello.o

else

KDIR := /home/light/A8Android/android_gingerbread_realv210_ver_1_0/out/target/product/smdkv210/obj/KERNEL

all:
    make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-eabi-

clean:
    rm -f *.ko *.o *.mod.o *.mod.c *.symvers

endif


测试文件:led.c

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

int main(int argc, char **argv)
{
    unsigned int on;
    unsigned int led_num;
    int fd;
printf("Enter the test led !\n");
    fd = open("/dev/Real210-led", 0);
    if (fd < 0)
    {
        perror("open device led");
        exit(1);
    }


    ioctl(fd, 1, 0);    //可修改本句代码


    close(fd);
    return 0;
}

Makefile文件:

CROSS=arm-linux-

all: led

led:led.c
    $(CROSS)gcc -o led led.c -static
    $(CROSS)strip led
clean:
    @rm -vf led *.o *~


说明:

编译驱动时候应该指明内核源码编译后的中间文件。编译器用的是arm-eabi-gcc 4.4.3

编译测试程序时应该添加-static声明。编译器arm-linux-gcc 4.4.1





原创粉丝点击