前言:
本文将结合简单的驱动代码,讲述编写LINUX下驱动代码流程。所使用的平台是Ubantu14.。
本文讲述流程是:先放代码,编译生成驱动,安装卸载驱动。这个流程走完后再讲解驱动代码。
驱动测试代码(test.c):
#include <asm/siginfo.h>
#include <linux/rcupdate.h>
#include <linux/version.h>
#include <linux/slab.h>
#include <linux/kobject.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/uaccess.h>
#include <linux/sched.h>
#include <linux/device.h>
/* 该驱动支持PCIE设备数量 */
#define CM_PCIE_MAX_MINORS (3)
/* 该驱动的名称 */
#define CM_PCIE_DRIVER_NAME "cm_cpie"
/* 配置信息 */
#define CM_ALTERA_ARRIA10_PCI_ID (0xe003)
#define CM_ALTERA_ARRIA10_PCI_VID (0x1172)
/* 逻辑类指针 */
static struct class *g_cmpcie_class = NULL;
/* 主设备号 */
static int g_cmpcie_major = 0;
/* 设备标记位 */
static unsigned char g_cmpcie_devices[CM_PCIE_MAX_MINORS];
/* 设备配置信息 */
static struct pci_device_id cmpcie_ids[] = {
{ PCI_DEVICE(CM_ALTERA_ARRIA10_PCI_VID, CM_ALTERA_ARRIA10_PCI_ID) },
{ 0 }
};
/* PCI-E设备插入内核时调用的函数 */
static int probe(struct pci_dev *dev, const struct pci_device_id *id)
{
printk("@INFO hava a pcie driver inster\n");
return 0;
}
/* PCI-E设备拔出内核调用的函数 */
static void remove(struct pci_dev *dev)
{
printk("@INFO hava a pcie driver remove\n");
}
/* PCI-E驱动实例 */
static struct pci_driver g_cmpcie_driver = {
.name = CM_PCIE_DRIVER_NAME, //驱动程序名称
.id_table = cmpcie_ids, //配置信息
.probe = probe, //PCI-E设备插入内核时调用的函数
.remove = remove, //PCI-E设备拔出内核时调用的函数
};
/* 驱动初始化函数 */
static int pcie_driver_init(void)
{
int i = 0, ret = 0;
dev_t dev;
printk("@INFO driver init\n");
/* 初始化设备标记位 */
for(i = 0; i < CM_PCIE_MAX_MINORS; i++)
{
g_cmpcie_devices[i] = 0;
}
/* 申请设备号 */
ret = alloc_chrdev_region(&dev, 0, CM_PCIE_MAX_MINORS, CM_PCIE_DRIVER_NAME);
if(ret)
{
printk("apply for dev fail\n");
}
else
{
printk("apply for dev success @dev %d\n", dev);
}
g_cmpcie_major = MAJOR(dev);
/* 申请逻辑类指针 */
g_cmpcie_class = class_create(THIS_MODULE, CM_PCIE_DRIVER_NAME);
if( IS_ERR(g_cmpcie_class) )
{
printk("apply for class fail\n");
}
else
{
printk("apply for class success\n");
}
/* 在PCI-E总线上申请驱动 */
ret = pci_register_driver(&g_cmpcie_driver);
if(ret)
{
printk("apply for driver fail");
}
else
{
printk("apply for driver success");
}
return 0;
}
/* 驱动销毁函数 */
static void pcie_driver_exit(void)
{
printk("driver exit");
/* 释放驱动 */
pci_unregister_driver(&g_cmpcie_driver);
/* 释放指针 */
class_destroy(g_cmpcie_class);
/* 释放设备号 */
unregister_chrdev_region(MKDEV(g_cmpcie_major, 0), CM_PCIE_MAX_MINORS);
}
module_init(pcie_driver_init);
module_exit(pcie_driver_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Wang jianbin");
MODULE_DESCRIPTION("This is a driver for PCIE");
同一目录下的Makefile文件
#you want produce module name
obj-m := modules.o
#module needed object file name
modules-objs := test.o
#environment needed to complie the module
KDIR := /lib/modules/`uname -r`/build
#loalce path
PWD := $(shell pwd)
#M is source file path
all:
make -C $(KDIR) M=$(PWD) modules
clean:
rm *.o *.ko *.order *.symvers *.mod.c
运行 make all
如图modules.ko便是驱动程序
安装驱动命令:insmod modules.ko
查看驱动信息命令:modinfo modules.ko
分析驱动依赖性名:depend modules.ko
卸载驱动命令:rmmod modules
查看内核输出信息:dmesg
查看所有驱动命令:lsmod
查看设备号命令 : cat /pro/devices