LINUX驅動入門(一)

前言:

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

 

 

 

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