rfid4-写成platform驱动
生活随笔
收集整理的這篇文章主要介紹了
rfid4-写成platform驱动
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
適應時代發(fā)展,將misc驅(qū)動封裝到platfrom總線里面去,
platform平臺總線模型,把設備和驅(qū)動分開,即一個東東要分成兩個部分去寫和去insmod,是不是有點麻煩。--對于固定于一個cpu平臺的用戶確實感覺比較麻煩,但是linux的目標是兼容所有的cpu平臺,在換cpu平臺時就會發(fā)現(xiàn)這種設計的優(yōu)點。
先看一個platform的簡單例子
先把Makefile列出
ifneq ($(KERNELRELEASE),) obj-m := platform_dev.o platform_drv.o else KDIR := /opt/FriendlyARM/mini2440/linux-2.6.32.2 #KDIR := /lib/modules/`uname -r`/build all: make -C $(KDIR) M=$(PWD) modules clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers endif 以下是設備
/******************platfrom_dev.c***************************/ #include <linux/module.h> #include <linux/device.h> #include <linux/platform_device.h> #include <linux/string.h> #include <linux/init.h> #include <linux/kernel.h>#define DEVICE_NAME "song_rfid"static struct resource my_resource[] = {[0] = {.start = 0x56000050,.end = 0x56000050 + 0x10 - 1,.flags = IORESOURCE_MEM,}, /* 設備內(nèi)存資源 GPFCON 0X56000050 GPFDAT 0X56000054 GPFUP 0X56000058 */ /*[1] = {.start = 25,.end = 25,.flags = IORESOURCE_IRQ,}*/ };static struct platform_device my_device = {.name = DEVICE_NAME,//此處指定的名字要和驅(qū)動中的名字匹配,song_rfid.id = -1,.num_resources = ARRAY_SIZE(my_resource),.resource = my_resource, };static int __init my_init(void) {int ret=0;ret = platform_device_register(&my_device); /*注冊設備,即想虛擬總線上添加此設備 也可以用platform_device_alloc分配一個現(xiàn)成的設備和用platform_device_add添加到總線上 */if (ret == 0) {printk("Register %s\n",DEVICE_NAME);} else {printk("Register error.\n");}return ret; }static void __exit my_exit(void) {platform_device_unregister(&my_device);printk("Unregister %s\n",DEVICE_NAME); }module_init(my_init); module_exit(my_exit);MODULE_LICENSE("GPL"); MODULE_VERSION("1.5"); 以下是驅(qū)動
/******************platfrom_drv.c***************************/ #include <linux/module.h> #include <linux/device.h> #include <linux/platform_device.h> #include <linux/string.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/io.h>#define DRIVER_NAME "song_rfid" static void __iomem *my_kv_base;//內(nèi)核虛擬地址 static struct resource *my_mem;static int my_probe(struct platform_device *pdev) {struct resource *res;int size;printk("driver find device : %s which can handle\n",DRIVER_NAME);res = platform_get_resource(pdev, IORESOURCE_MEM, 0); /*獲取內(nèi)存資源 如果先insmod設備內(nèi)核就會把設備掛到平臺總線上,之后在insmod驅(qū)動時,平臺核心會遍歷整個平臺總線上的設備名字,找到和該驅(qū)動名字匹配的設備, 然后調(diào)用驅(qū)動的probe函數(shù)同時把該設備的struct platform_device當做參數(shù)pdev傳遞給probe函數(shù), 這樣驅(qū)動就可以使用platform_get_resource(pdev,,)獲取設備的各個資源如果先insmod驅(qū)動,情況與上類似如果找到總線上某個設備可以和該驅(qū)動匹配,會成功調(diào)用驅(qū)動的probe */if (res == NULL) {printk("no memory resource specified\n");return -ENOENT;}size = (res->end - res->start) + 1;my_mem = request_mem_region(res->start, size, pdev->name);//向內(nèi)核申請內(nèi)存資源if (my_mem == NULL) {printk("failed to get memory region\n");return -ENOENT;}my_kv_base = ioremap(res->start, size);//得到虛擬地址,之后再去操作...return 0; }static int my_remove(struct platform_device *pdev) {printk("driver found device : %s unpluged\n",DRIVER_NAME);return 0; }static struct platform_driver my_driver = {.probe = my_probe,.remove = my_remove,.driver = {.owner = THIS_MODULE,.name = DRIVER_NAME,//此處指定的名字要和設備中的名字匹配,song_rfid}, };static int __init my_init(void) {printk("Register my_driver.\n");return platform_driver_register(&my_driver); /*注冊驅(qū)動 即向平臺總線上添加一個驅(qū)動*/ }static void __exit my_exit(void) {printk("Unregister my_driver.\n");platform_driver_unregister(&my_driver); }module_init(my_init); module_exit(my_exit);MODULE_LICENSE("GPL");
驅(qū)動代碼my_exit()函數(shù)里面還需要釋放資源-------2011-11-18
release_resource(my_mem);
kfree(my_mem) ;
[root@FriendlyARM plg]# insmod platform_dev.ko //插入設備 Register song_rfid [root@FriendlyARM plg]# cat /proc/iomem //insmo設備后就會在iomem有了登記 .... 56000050-5600005f : song_rfid56000050-5600005f : song_rfid ... [root@FriendlyARM plg]# insmod platform_drv.ko //插入驅(qū)動 Register my_driver. driver find device : song_rfid which can handle[root@FriendlyARM plg]# ls /sys/bus/platform/devices/ dm9000 s3c2410-rtc s3c2440-sdi s3c24xx_uda134x.0 regulatory.0 s3c2410-spi.0 s3c2440-uart.0 soc-audio s3c2410-iis s3c2410-wdt s3c2440-uart.1 song_rfid s3c2410-lcd s3c2440-i2c s3c2440-uart.2 s3c2410-ohci s3c2440-nand s3c2440-usbgadget [root@FriendlyARM plg]# ls /sys/bus/platform/drivers dm9000 s3c2410-ohci s3c2440-uart song_rfid s3c-i2c s3c2410-rtc s3c24xx-nand s3c-sdi s3c2410-spi s3c24xx_uda134x s3c2410-lcd s3c2412-lcd soc-audio
/* 另外,已經(jīng)有許多按照平臺模式寫的驅(qū)動設備被編譯進內(nèi)核,在march-mini2440.c中 static struct platform_device *mini2440_devices[] __initdata = {&s3c_device_usb,&s3c_device_rtc,&s3c_device_lcd,&s3c_device_wdt,&s3c_device_i2c0,&s3c_device_spi0,&s3c_device_iis,&mini2440_device_eth,&s3c24xx_uda134x,&s3c_device_nand,&s3c_device_sdi,&s3c_device_usbgadget, }; 這些都是設備,大部分定義在arch/arm/plat-s3c24xx/Devs.c中 比如 Watchdog static struct resource s3c_wdt_resource[] = {[0] = {.start = S3C24XX_PA_WATCHDOG,.end = S3C24XX_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1,.flags = IORESOURCE_MEM,},[1] = {.start = IRQ_WDT,.end = IRQ_WDT,.flags = IORESOURCE_IRQ,}};struct platform_device s3c_device_wdt = {.name = "s3c2410-wdt",.id = -1,.num_resources = ARRAY_SIZE(s3c_wdt_resource),.resource = s3c_wdt_resource, };內(nèi)核啟動時會執(zhí)行這個函數(shù),在mach-mini2440.c中,將這些設備掛到平臺總線上。platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));至于這些平臺設備對應的驅(qū)動,則分散在drivers目錄下各個文件中(如果有的話,但大部分都有)。如果有,則可以在make memuconfig時配置,或者編譯進內(nèi)核或者 編譯成模塊;如果沒有則要自己寫了。 */
platform平臺總線模型,把設備和驅(qū)動分開,即一個東東要分成兩個部分去寫和去insmod,是不是有點麻煩。--對于固定于一個cpu平臺的用戶確實感覺比較麻煩,但是linux的目標是兼容所有的cpu平臺,在換cpu平臺時就會發(fā)現(xiàn)這種設計的優(yōu)點。
先看一個platform的簡單例子
先把Makefile列出
ifneq ($(KERNELRELEASE),) obj-m := platform_dev.o platform_drv.o else KDIR := /opt/FriendlyARM/mini2440/linux-2.6.32.2 #KDIR := /lib/modules/`uname -r`/build all: make -C $(KDIR) M=$(PWD) modules clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers endif 以下是設備
/******************platfrom_dev.c***************************/ #include <linux/module.h> #include <linux/device.h> #include <linux/platform_device.h> #include <linux/string.h> #include <linux/init.h> #include <linux/kernel.h>#define DEVICE_NAME "song_rfid"static struct resource my_resource[] = {[0] = {.start = 0x56000050,.end = 0x56000050 + 0x10 - 1,.flags = IORESOURCE_MEM,}, /* 設備內(nèi)存資源 GPFCON 0X56000050 GPFDAT 0X56000054 GPFUP 0X56000058 */ /*[1] = {.start = 25,.end = 25,.flags = IORESOURCE_IRQ,}*/ };static struct platform_device my_device = {.name = DEVICE_NAME,//此處指定的名字要和驅(qū)動中的名字匹配,song_rfid.id = -1,.num_resources = ARRAY_SIZE(my_resource),.resource = my_resource, };static int __init my_init(void) {int ret=0;ret = platform_device_register(&my_device); /*注冊設備,即想虛擬總線上添加此設備 也可以用platform_device_alloc分配一個現(xiàn)成的設備和用platform_device_add添加到總線上 */if (ret == 0) {printk("Register %s\n",DEVICE_NAME);} else {printk("Register error.\n");}return ret; }static void __exit my_exit(void) {platform_device_unregister(&my_device);printk("Unregister %s\n",DEVICE_NAME); }module_init(my_init); module_exit(my_exit);MODULE_LICENSE("GPL"); MODULE_VERSION("1.5"); 以下是驅(qū)動
/******************platfrom_drv.c***************************/ #include <linux/module.h> #include <linux/device.h> #include <linux/platform_device.h> #include <linux/string.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/io.h>#define DRIVER_NAME "song_rfid" static void __iomem *my_kv_base;//內(nèi)核虛擬地址 static struct resource *my_mem;static int my_probe(struct platform_device *pdev) {struct resource *res;int size;printk("driver find device : %s which can handle\n",DRIVER_NAME);res = platform_get_resource(pdev, IORESOURCE_MEM, 0); /*獲取內(nèi)存資源 如果先insmod設備內(nèi)核就會把設備掛到平臺總線上,之后在insmod驅(qū)動時,平臺核心會遍歷整個平臺總線上的設備名字,找到和該驅(qū)動名字匹配的設備, 然后調(diào)用驅(qū)動的probe函數(shù)同時把該設備的struct platform_device當做參數(shù)pdev傳遞給probe函數(shù), 這樣驅(qū)動就可以使用platform_get_resource(pdev,,)獲取設備的各個資源如果先insmod驅(qū)動,情況與上類似如果找到總線上某個設備可以和該驅(qū)動匹配,會成功調(diào)用驅(qū)動的probe */if (res == NULL) {printk("no memory resource specified\n");return -ENOENT;}size = (res->end - res->start) + 1;my_mem = request_mem_region(res->start, size, pdev->name);//向內(nèi)核申請內(nèi)存資源if (my_mem == NULL) {printk("failed to get memory region\n");return -ENOENT;}my_kv_base = ioremap(res->start, size);//得到虛擬地址,之后再去操作...return 0; }static int my_remove(struct platform_device *pdev) {printk("driver found device : %s unpluged\n",DRIVER_NAME);return 0; }static struct platform_driver my_driver = {.probe = my_probe,.remove = my_remove,.driver = {.owner = THIS_MODULE,.name = DRIVER_NAME,//此處指定的名字要和設備中的名字匹配,song_rfid}, };static int __init my_init(void) {printk("Register my_driver.\n");return platform_driver_register(&my_driver); /*注冊驅(qū)動 即向平臺總線上添加一個驅(qū)動*/ }static void __exit my_exit(void) {printk("Unregister my_driver.\n");platform_driver_unregister(&my_driver); }module_init(my_init); module_exit(my_exit);MODULE_LICENSE("GPL");
驅(qū)動代碼my_exit()函數(shù)里面還需要釋放資源-------2011-11-18
release_resource(my_mem);
kfree(my_mem) ;
[root@FriendlyARM plg]# insmod platform_dev.ko //插入設備 Register song_rfid [root@FriendlyARM plg]# cat /proc/iomem //insmo設備后就會在iomem有了登記 .... 56000050-5600005f : song_rfid56000050-5600005f : song_rfid ... [root@FriendlyARM plg]# insmod platform_drv.ko //插入驅(qū)動 Register my_driver. driver find device : song_rfid which can handle[root@FriendlyARM plg]# ls /sys/bus/platform/devices/ dm9000 s3c2410-rtc s3c2440-sdi s3c24xx_uda134x.0 regulatory.0 s3c2410-spi.0 s3c2440-uart.0 soc-audio s3c2410-iis s3c2410-wdt s3c2440-uart.1 song_rfid s3c2410-lcd s3c2440-i2c s3c2440-uart.2 s3c2410-ohci s3c2440-nand s3c2440-usbgadget [root@FriendlyARM plg]# ls /sys/bus/platform/drivers dm9000 s3c2410-ohci s3c2440-uart song_rfid s3c-i2c s3c2410-rtc s3c24xx-nand s3c-sdi s3c2410-spi s3c24xx_uda134x s3c2410-lcd s3c2412-lcd soc-audio
/* 另外,已經(jīng)有許多按照平臺模式寫的驅(qū)動設備被編譯進內(nèi)核,在march-mini2440.c中 static struct platform_device *mini2440_devices[] __initdata = {&s3c_device_usb,&s3c_device_rtc,&s3c_device_lcd,&s3c_device_wdt,&s3c_device_i2c0,&s3c_device_spi0,&s3c_device_iis,&mini2440_device_eth,&s3c24xx_uda134x,&s3c_device_nand,&s3c_device_sdi,&s3c_device_usbgadget, }; 這些都是設備,大部分定義在arch/arm/plat-s3c24xx/Devs.c中 比如 Watchdog static struct resource s3c_wdt_resource[] = {[0] = {.start = S3C24XX_PA_WATCHDOG,.end = S3C24XX_PA_WATCHDOG + S3C24XX_SZ_WATCHDOG - 1,.flags = IORESOURCE_MEM,},[1] = {.start = IRQ_WDT,.end = IRQ_WDT,.flags = IORESOURCE_IRQ,}};struct platform_device s3c_device_wdt = {.name = "s3c2410-wdt",.id = -1,.num_resources = ARRAY_SIZE(s3c_wdt_resource),.resource = s3c_wdt_resource, };內(nèi)核啟動時會執(zhí)行這個函數(shù),在mach-mini2440.c中,將這些設備掛到平臺總線上。platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));至于這些平臺設備對應的驅(qū)動,則分散在drivers目錄下各個文件中(如果有的話,但大部分都有)。如果有,則可以在make memuconfig時配置,或者編譯進內(nèi)核或者 編譯成模塊;如果沒有則要自己寫了。 */
轉(zhuǎn)載于:https://www.cnblogs.com/-song/archive/2011/10/25/3331942.html
總結(jié)
以上是生活随笔為你收集整理的rfid4-写成platform驱动的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: rfid6-写成platform驱动
- 下一篇: rfid5-写成platform驱动