標籤:des class blog code http tar
★總體介紹
LED驅動程式主要實現了TQ2440開發板上的4個LED燈的硬體驅動,實現了對引腳GPIOB5、GPIOB6、GPIOB7、GPIOB8的高低電平設定(common-smdk.c中已經實現了對引腳的配置),利用測試程式調用該驅動程式,通過命令控制LED燈的亮滅。
★詳細介紹1、驅動程式代碼:My_led.c
#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/irq.h>#include <mach/regs-gpio.h>#include <mach/hardware.h>#include <linux/device.h>#define DEVICE_NAME "My_led" /**載入模組後執行cat/proc/devices中看到的裝置名稱**/#define Led_MAJOR 103 /**主裝置號**/#define LED_ON 1#define LED_OFF 0 /**Led的控制引腳**/static unsigned long led_table[ ] ={ S3C2410_GPB5, S3C2410_GPB6,S3C2410_GPB7,S3C2410_GPB8,};static int My_led_open(struct inode *inode,struct file *file){ printk("My_led open\n"); return 0;}static int My_led_ioctl(struct inode * inode, struct file * file,unsigned int cmd,unsigned long arg){if(arg > 4){return -1; }switch(cmd){ case LED_ON:s3c2410_gpio_setpin(led_table[arg], 0);//設定指定引腳為輸出電平為0 return 0; case LED_OFF: s3c2410_gpio_setpin(led_table[arg], 1);//設定指定引腳為輸出電平為1 return 0; default:return -1;}}static struct file_operations My_led_fops ={.owner = THIS_MODULE,.open = My_led_open,.ioctl = My_led_ioctl,};static struct class *led_class;static int __init My_led_init(void){int ret;printk("My_led start\n"); /**註冊字元裝置驅動程式**/ /**參數為主裝置號、裝置名稱字、file_operations結構**/ /**這樣主裝置號就與file_operations聯絡起來**/ ret = register_chrdev(Led_MAJOR, DEVICE_NAME, &My_led_fops); if(ret < 0) {printk("can't register major number\n");return ret; }//註冊一個類,使mdev可以在"/dev/目錄下建立裝置節點"led_class = class_create(THIS_MODULE, DEVICE_NAME);if(IS_ERR(led_class)){printk("failed in My_led class.\n");return -1;}device_create(led_class, NULL, MKDEV(Led_MAJOR,0), NULL, DEVICE_NAME);printk(DEVICE_NAME "initialized\n");return 0;}static void __exit My_led_exit(void){ unregister_chrdev(Led_MAJOR, DEVICE_NAME); device_destroy(led_class, MKDEV(Led_MAJOR,0));//登出裝置節點 class_destroy(led_class);//登出類}module_init(My_led_init);module_exit(My_led_exit);MODULE_LICENSE("GPL");
2、宏定義
#define DEVICE_NAME "My_led" //載入模組後執行cat/proc/devices中看到的裝置名稱
#define Led_MAJOR 103 //主裝置號
#define LED_ON 1
#define LED_OFF 0 My_led_ioctl函數中要輸入的參數命令,LED_ON會執行開啟燈的命令、LED_OFF執行關閉燈的命令
3、Led燈的引腳控制
定義一個led_table[ ] 數組,在後面調用時要方便些。
詳細說明一下S3C2410_GPB5是什麼意思:
如所示,是關於S3C2410_GPB5相關的所有代碼。通過上面的代碼可以得出S3C2410_GPB5為37。實際上S3C2410_GPB5就是連接埠的編號,bank是分組的基號碼,offset是組內的位移量。TQ2440開發板的GPIOB的第五個引腳為37。
4、My_led_ioctl()函數
此函數主要負責響應應用程式的相關命令,然後根據命令執行相關的代碼。cmd命令包括宏定義的LED_ON、LED_OFF。
s3c2410_gpio_setpin()函數
自認為這是本驅動程式最重要的一個函數,它的作用是:將指定的引腳設定為低電平或者高電平。本驅動程式中只是用了核心提供的這一個介面來實現對引腳的控制,但是肯定會研究一下這個函數。
5、註冊一個類
如果不註冊這個類,那麼當在開發板上掛載驅動之後,還要做的一件事是手動“產生裝置節點”,就是利用mknod命令。但是驅動程式都是隨作業系統的運行而開始工作的,因此產生裝置節點要讓它自動產生,而並非手動。所以才會註冊這樣一個類,在掛載驅動之後,自動將裝置節點產生。註冊類的核心代碼:
led_class = class_create(THIS_MODULE, DEVICE_NAME);if(IS_ERR(led_class)){printk("failed in My_led class.\n");return -1;}device_create(led_class, NULL, MKDEV(Led_MAJOR,0), NULL, DEVICE_NAME);
6、測試程式
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main() { int fd,i,cmd; fd=open("/dev/My_led",0); if (fd<0) { printf("open led_driver error"); exit(1); } while(1) { scanf("%d",&cmd); switch(cmd) {case 0: printf("All off\n"); for(i = 0;i < 4;i ++) ioctl(fd,0,i); break;case 1: printf("light first led\n"); ioctl(fd,1,0); break;case 2: printf("light second led\n"); ioctl(fd,0,0); ioctl(fd,1,1); break;case 3: printf("light third led\n"); ioctl(fd,0,1); ioctl(fd,1,2); break;case 4: printf("light fourth led\n"); ioctl(fd,0,2); ioctl(fd,1,3); break;case 5: printf("All light \n"); for(i = 0;i < 4;i ++) ioctl(fd,1,i); break;default: i = 10; break; } if (i == 10) break; } return 0; }
★遇到的錯誤
1、找不到檔案
這個錯誤的主要原因很可能是核心的版本不同,不同核心的標頭檔存放的路徑不相同。因此,當編譯驅動程式報錯“找不到檔案”時,檢查標頭檔的路徑是否正確
2、Makefile檔案指定交叉編譯器
下面是驅動程式的Makefile檔案
#LED_makefileKERNELDIR := /home/xg/linux_arm/linux-2.6.30.4/PWD :=$(shell pwd)all:make -C $(KERNELDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=/opt/opt/EmbedSky/4.3.3/bin/arm-linux-test:/opt/opt/EmbedSky/4.3.3/bin/arm-linux-gcc -o test test.cclean:rm -rf *.o *koobj-m :=My_led.o
當時出的錯誤就是編譯器的路徑沒有搞清楚。