一、驅動測試源碼
platform_device_final.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
MODULE_LICENSE("GPL");
// LED2
#define GPL2CON 0x11000100
#define GPL2DAT 0x11000104
// LED3
#define GPK1CON 0x11000060
#define GPK1DAT 0x11000064
struct resource res[] = {
[0] = {
.start = GPL2CON,
.end = GPL2CON+3,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = GPL2DAT,
.end = GPL2DAT+3,
.flags = IORESOURCE_MEM,
},
[2] = {
.start = GPK1CON,
.end = GPK1CON+3,
.flags = IORESOURCE_MEM,
},
[3] = {
.start = GPK1DAT,
.end = GPK1DAT+3,
.flags = IORESOURCE_MEM,
},
};
static void platform_led_device_release(struct device *dev)
{
printk("%s,%d\n", __func__, __LINE__);
return ;
}
static struct platform_device pdevice = {
.name = "platform_led",
.num_resources = ARRAY_SIZE(res),
.resource = res,
.dev = {
.release = platform_led_device_release,
},
};
static int __init platform_led_device_init(void)
{
printk("%s,%d\n", __func__, __LINE__);
platform_device_register(&pdevice);
return 0;
}
static void __exit platform_led_device_exit(void)
{
printk("%s,%d\n", __func__, __LINE__);
platform_device_unregister(&pdevice);
return ;
}
module_init(platform_led_device_init);
module_exit(platform_led_device_exit);
platform_driver_final.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/platform_device.h>
MODULE_LICENSE("GPL");
struct resource *res0;
struct resource *res1;
static int platform_driver_final_probe(struct platform_device * pdevice) // 探測函數,一旦設備與驅動匹配成功,就回調此函數
{
printk("***************probe ok!***************\n");
res0 = platform_get_resource(pdevice, IORESOURCE_MEM, 0);
if(res0 == NULL)
{
printk("Failed to platform_get_resource.\n");
return -1;
}
printk("res0:%#x , %#x\n", (unsigned int)res0->start, (unsigned int)res0->end);
res1 = platform_get_resource(pdevice, IORESOURCE_MEM, 1);
if(res1 == NULL)
{
printk("Failed to platform_get_resource.\n");
return -1;
}
printk("res1:%#x , %#x\n", (unsigned int)res1->start, (unsigned int)res1->end);
return 0;
}
static int platform_driver_final_remove(struct platform_device * pdevice) // 移除函數
{
printk("%s,%d\n", __func__, __LINE__);
return 0;
}
static struct platform_device_id ids[] = {
{.name = "platform_driver0", },
{.name = "platform_driver1", },
{/*Nothing to be done.*/},
};
static struct platform_driver pdriver = {
.probe = platform_driver_final_probe,
.remove = platform_driver_final_remove,
.driver = {
.name = "platform_driver0",
},
.id_table = ids,
};
//module_platform_driver(pdriver);
//以上一句話展開爲下面的內容
#if 1
static int __init pdriver_init(void)
{
printk("%s,%d\n", __func__, __LINE__);
platform_driver_register(&pdriver);
return 0;
}
module_init(pdriver_init);
static void __exit pdriver_exit(void)
{
printk("%s,%d\n", __func__, __LINE__);
platform_driver_unregister(&pdriver);
return ;
}
module_exit(pdriver_exit);
#endif
二、Makefile
$(warning KERNELRELEASE = $(KERNELRELEASE))
ifeq ($(KERNELRELEASE),)
#內核的源碼路徑, ?= 條件賦值, uname -r 得到內核版本號
#KERNELDIR ?= /lib/modules/$(shell uname -r)/build
KERNELDIR ?= /home/mint/itop/linux_3.0
# := 立即賦值, 得到當前的絕對路徑
PWD := $(shell pwd)
# -C 切換工作路徑, $(MAKE) = make
modules:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module* modules*
.PHONY: modules clean
else
# 生成模塊
obj-m := platform_device_final.o platform_driver_final.o
endif
install:
cp *.ko ~/nfs/fs/
三、測試
1、加載驅動
insmod platform_device_final.ko
insmod platform_driver_final.ko
2、卸載驅動
rmmod platform_device_final
rmmod platform_driver_final
dmesg -c