前言:
本文將結合簡單的驅動代碼,講述編寫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