1. 程式人生 > >開發板上驅動程式模組的實現

開發板上驅動程式模組的實現

       一、在同一個資料夾中,寫一個驅動模組程式(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