arm中驅動模塊加載並由應用程序調用

開發板:s3c2440

驅動模塊程序如下:

#include <linux/types.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <linux/cdev.h>
#include <linux/ioctl.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <asm/segment.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>

#include "my_ioctl.h"

unsigned int test_major= 253;//主設備號
unsigned int test_minor= 0;//次設備號
struct cdev cdevc;
MODULE_LICENSE("Dual BSD/GPL");//告知內核,該模塊帶有一個自由的許可證

static int read_test(struct file *file, const char *buf, int count, loff_t *f_pos)
{
    if (copy_to_user(buf, S3C2410_GPGDAT, sizeof(unsigned int)))
    {
        printk("error!/n");
        return -1;
    }
    return sizeof(unsigned int);
}

static int write_test(struct file *file, const char *buf, int count, loff_t *f_pos)
{
    __raw_writel (*buf, S3C2410_GPGDAT);//把buf中的數據賦值給GPGDAT,不可直接賦值,一定要調用此函數
    printk ("write_test/n");
    return 0;
}

int write_CFG(GPIO_Data_S *arg)
{
    __raw_writel (0x0001<<2*arg->bit, S3C2410_GPACON+arg->port*0x10);//找到寄存器的某個引腳,並配置成輸入或輸出
    __raw_writel (arg->value<<arg->bit, S3C2410_GPADAT+arg->port*0x10);//
    return 0;
}

static int ioctl_test (struct inode *inode, struct file *file , unsigned int cmd, unsigned long arg)
{
    GPIO_Data_S *data;
    data= (GPIO_Data_S *)arg;

    switch(cmd)
    {
//        case GPIO_IO_SET_CFG: set_CFG(data); break;
        case GPIO_IO_GET_CFG: get_CFG(data); break;
        case GPIO_IO_WRITE: write_CFG(data); break;
//        case GPIO_IO_READ: read_CFG(data); break;
        default: printk("The command is errot!/n");
    }
    return 0;
}

static int open_test(struct inode *inode, struct file *file)
{
//    __raw_writel (0x1400, S3C2410_GPGCON);//"S3C2410_GPGCON"在asm/arch/regs-gpio.h庫函數中得到宏定義,可查閱

    printk ("open_test/n");
    return 0;
}

static int release_test(struct inode *inode, struct file *file)
{
    printk ("release_test/n");
    return 0;
}
//初始化字符設備驅動的file_operations結構體,在設備編號和驅動程序之間建立鏈接
struct file_operations test_fops={
.owner= THIS_MODULE,
.read= read_test,
.write= write_test,
.ioctl= ioctl_test,
.open= open_test,
.release= release_test,
};

int dev_test_init_module(void)
{
    int result;
    dev_t dev= 0;
   
    dev= MKDEV (test_major, test_minor);//獲取設備編號
    result= register_chrdev_region(dev, 1, "dev_test");//靜態方式註冊設備驅動
   
    printk ("major= %d, minor= %d/n", test_major, test_minor);
    if(result<0)
    {
        printk (KERN_INFO"test:can't get major nuber!/n");
        return result;
    }   
   
    cdev_init(&cdevc, &test_fops);
    cdevc.owner= THIS_MODULE;
    cdevc.ops= &test_fops;
    result= cdev_add(&cdevc, dev, 1);
    if (result)
    {
        printk("Error %d adding test", result);
    }
   
    return 0;
}

void dev_test_cleanup_module(void)
{
    dev_t dev= 0;
    dev= MKDEV(test_major, test_minor);
    cdev_del(&cdevc);
    unregister_chrdev_region(dev, 1);

    printk("Module Exit!/n");
}

module_init(dev_test_init_module);
module_exit(dev_test_cleanup_module);

 

應用程序如下:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/ioctl.h>
#include "my_ioctl.h"

int main(void)
{
    int dev_test;
    int in_port;
    int in_bit;
    int in_value;
    GPIO_Data_S data;

    printf("Input the number: ");
    scanf("%d %d %d", &in_port, &in_bit, &in_value);
    printf("%d, %d, %d/n",in_port, in_bit, in_value);
   
    data.port= in_port;
    data.bit= in_bit;
    data.value= in_value;

    dev_test= open("/dev/dev_test1", O_RDWR);
    if (dev_test== -1)
    {
        printf("Can't open file.../n");
        exit(0);
    }
   
    while(1)
    {           
        sleep(1);
        ioctl(dev_test , GPIO_IO_WRITE, &data);
        sleep(1);
        data.value= ~(data.value);
        ioctl(dev_test , GPIO_IO_WRITE, &data);
    }
   
    close (dev_test);
}

 

my_ioctl.h庫函數如下:

#ifndef __IOCTL_C_H__
#define __IOCTL_C_H__



typedef struct GPIO_Data_t
{
    unsigned int port;
    unsigned int bit;
    unsigned int value;
} GPIO_Data_S;



#define GPIO_IOC_MAGIC 12  //Documentation/ioctl-number.txt

#define GPIO_IO_SET_CFG _IOW(GPIO_IOC_MAGIC,0,sizeof(GPIO_Data_S))
#define GPIO_IO_GET_CFG _IOWR(GPIO_IOC_MAGIC,1,sizeof(GPIO_Data_S))
#define GPIO_IO_WRITE   _IOW(GPIO_IOC_MAGIC,2,sizeof(GPIO_Data_S))
#define GPIO_IO_READ    _IOWR(GPIO_IOC_MAGIC,3,sizeof(GPIO_Data_S))

#endif

 

Makefile文件如下:

# To build modules outside of the kernel tree, we run "make"
# in the kernel source tree; the Makefile these then includes this
# Makefile once again.
# This conditional selects whether we are being included from the
# kernel Makefile or not.
ifeq ($(KERNELRELEASE),)

    # Assume the source tree is where the running kernel was built
    # You should set KERNELDIR in the environment if it's elsewhere
#    KERNELDIR ?= /lib/modules/$(shell uname -r)/build
    KERNELDIR = /home/wangwei/utu-linux_for_s3c2440_V1.5.3
#    KERNELDIR=$(KDIR)

    # The current directory is passed to sub-makes as argument
    PWD := $(shell pwd)
modules:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules

modules_install:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install

clean:
    rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions

.PHONY: modules modules_install clean

else
    # called from kernel build system: just declare what our modules are
    obj-m := dev_test1.o
endif

 

 

執行順序:

      1.編譯驅動模塊程序和應用程序,分別生成dev_test1.ko和data_deal1,並用串口燒到開發板

      2.加載模塊:insmod  dev_test1

      3.創建設備結點,mknod /dev/dev_test1 c 253 0

      4.執行應用程序:./data_deal1(可能需要修改權限)

串口燒寫方式簡介:

      1.啓動開發板,進入開發板系統,按ctrl+a並釋放,再按z鍵

      2.出現很多選項,選s--傳輸文件

      3.enter鍵選zmoden

      4.按向右方向鍵,選中[轉到],按enter鍵

      5.打入所要傳輸文件在你主機上的絕對路徑,按enter鍵

      6.選中要傳輸文件,按enter鍵

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章