开发板上驱动程序模块的实现

来源:互联网 发布:cef chromium linux 编辑:程序博客网 时间:2024/06/03 19:07

       一、在同一个文件夹中,写一个驱动模块程序(file.c文件)和一个Makefile

              如:驱动模块程序:

                #include <linux/module.h>
                #include <linux/kernel.h>
                #include <linux/fs.h>
                #include <linux/init.h>
                #include <linux/delay.h>
                #include <linux/poll.h>
                #include <linux/irq.h>
                #include <asm/irq.h>
                #include <asm/io.h>
                 #include <linux/interrupt.h>
                #include <asm/uaccess.h>
                #include <mach/hardware.h>
                #include <linux/platform_device.h>
                #include <linux/cdev.h>
                #include <linux/miscdevice.h>
                #include <mach/gpio.h>
                #include <plat/gpio-cfg.h>
                #include <plat/regs-gpio.h>
                #include <plat/clock.h>
                #include <plat/cpu.h>
                #include <plat/regs-timer.h>
                #include <linux/device.h>
                #define DEVICE_NAME "ledtest"
                static struct class *led_class;
 
static int ledtest_open(struct inode *inode, struct file *file)
{
    unsigned int tmp;
     
    tmp = readl(S3C64XX_GPKCON);
    tmp =(tmp&~(0xffffU<<4)) | (0x1111U<<4);  
    //(tmp & ~(0xffffU<<0)) | (0x1111U<<0);
    writel(tmp, S3C64XX_GPKCON);
 
    tmp = readl(S3C64XX_GPKDAT);
    tmp |= (0x0F << 4);
    writel(tmp, S3C64XX_GPKDAT);
    
    return 0;
}
 
static int ledtest_close(struct inode *inode, struct file *file)
{
    unsigned int tmp;
     
    tmp = readl(S3C64XX_GPKCON);
    tmp = (tmp & ~(0xffffU<<4));    //input function
    writel(tmp, S3C64XX_GPKCON);    
     
    return 0;
}
 
static int ledtest_ioctl(struct inode *inode, struct file *file,
        unsigned int cmd, unsigned long arg)
{
    unsigned tmp;
    unsigned char num;
    num = *(unsigned char *)arg;
 
    //printk (DEVICE_NAME": %d %d\n", num, cmd);
 
    switch(cmd) {
        case 0:        //on
         if (num > 4) {
                    return -EINVAL;
            }
            tmp = readl(S3C64XX_GPKDAT);
            tmp &= ~(1 << (4 + num));
            //tmp |= ( cmd << (0 + num) );
            writel(tmp, S3C64XX_GPKDAT);
            return 0;
        case 1:        //off
         if (num > 4) {
                    return -EINVAL;
            }
         tmp = readl(S3C64XX_GPKDAT);
            tmp &= ~(1 << (4+ num));
            tmp |= ( cmd << (4 + num) );
            writel(tmp, S3C64XX_GPKDAT);
                return 0;  
             default:
              return -EINVAL;
  }
 return 0;
 
}
 
static struct file_operations dev_fops = {
    .owner    = THIS_MODULE,
    .open    = ledtest_open,
    .ioctl    = ledtest_ioctl,
    .release    = ledtest_close,
};
 
static struct miscdevice misc = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = DEVICE_NAME,
    .fops = &dev_fops,
};
 
static int __init dev_init(void)
{
    int ret;
 
    ret = misc_register(&misc);
    printk ("led driver initialized.\n");
    return ret;
}
static void __exit dev_exit(void)
{
    misc_deregister(&misc);
}
 
module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");


     如Makefile:

        ifneq ($(KERNELRELEASE),)
        obj-m := s3c6410_leds.o
        else
                     PWD  := $(shell pwd)    
                     KERNEL_DIR :=/home/ghh/linux-2.6.28.6

       all:
                      cd $(KERNEL_DIR); make SUBDIRS=$(PWD) modules
                        arm-linux-gcc -o leds_tese leds_test.c
       clean:
                     rm -rf .*.cmd *.o *.mod.c *.ko .tmp_versions *.order *.symvers
endif

二、然后执行make命令(make  -C  /内核路径/   SUBDIRS=$(pwd) modules),执行该命令后会生成几个文件,其中有一个是.KO文件,这个文件是用来做加载驱动模块用的

三、在同一文件中,写一个应用程序和一个Makefile

      如:应用程序

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

#define PATH "/dev/ledtest"    //device file
#define LED_ON    0
#define LED_OFF 1

int main(void)
{
    int fd, count;
    unsigned char num;
    unsigned char led_num[4] = {0, 1, 2, 3};

    fd = open("/dev/ledtest", 0);
    if (fd < 0) {
        printf("Failed to open leds driver\n");
        exit(1);
    }

    count = 4;
    while(1) {
        ioctl(fd, LED_ON, &led_num[count%4]);
        ioctl(fd, LED_OFF, &led_num[(count - 1)%4]);
        usleep(500000);
        count++;
        ioctl(fd, LED_ON, &led_num[count%4]);
        ioctl(fd, LED_OFF, &led_num[(count - 1)%4]);
        usleep(500000);
    }
    
    close(fd);
    
    return 0;
}

        


Makefile:

CROSS_COMPILE = /opt/FriendlyARM/toolschain/4.5.1/bin/arm-linux-
CC = $(CROSS_COMPILE)gcc
AR = $(CROSS_COMPILE)ar

ALL :  leds_test

leds_test:  leds_test.c
    $(CC) -o leds_test   leds_test.c
     
clean :
    rm -rf leds_test *~

四、然后执行make命令,就会生成一个可执行文件

五、启动NFS在宿主机上,并把前面生成的.KO文件和可执行文件拷坝到共享目录下

六、打开开发板的终端,然后挂载共享文件目录,而挂载共享文件有两种方式:例如:

   1、mount   -o  nolock   192.168.3.150:/home/share   /mnt

   2、mount   -t    nfs   -o  intr,nolock,wsize=1024,rsize=1024  192.168/3/150:/home/share  /mnt

七、挂载成功后,就进入/mnt进行加载.KO文件

    #cd   /mnt

   #insmod   file.ko

   #lsmod    //查看是否加载成功

   #lsmod   |   head   -参数   //可查看前面的模块

   #dmesg   |  tail     -参数    //查看尾的模块,并显示模块内容

八、在开发板上加载模块成功后,就执行应用程序生成的可执行文件 ,如:

    #  ./led_test   on或off

注:

       在执行make 的命令之前,记得要更新环境变量,即

      #soure   /etc/profile

0 0
原创粉丝点击