歡迎您光臨本站 註冊首頁

Davinci DM6446開發攻略——LINUX GPIO驅動源碼移植

←手機掃碼閱讀     火星人 @ 2014-03-09 , reply:0

一、 DM6446 GPIO的介紹

說到LINUX 驅動移植,沒有移植過的朋友,或剛剛進入LINUX領域的朋友,最好去看看《LINUX 設備驅動程序》第三版,有個理論或感性的認識.該版本是基於2.6.10的基礎上描述的,經典讀物,網上有電子版,但是建議花幾十元買本書是值得的. GPIO是嵌入式系統最簡單、最常用的資源了,比如點亮LED,控制蜂鳴器,輸出高低電平,檢測按鍵,等等.GPIO分輸入和輸出,在Montavista linux-2.6.18中,有關GPIO的最底層的寄存器驅動,是在linux-2.6.18_pro500\arch\arm\mach-davinci目錄下的gpio.c,這個是寄存器級的驅動,搞過單片機MCU的朋友應該比較熟悉寄存器級的驅動.根據DM6446的晶元DATASHEET,DM6446的GPIO分為3組BANK,BANK01組包括GPIO0~GPIO31,BANK23組包括GPIO32~GPIO63,BANK45組包括GPIO64~GPIO70,由於硬體資源的原因,DM6446並不是GPIO管腳就是純粹的GPIO腳,GPIO管腳和其他一些標準介面復用相同的引腳,比如SPI和GPIO復用,I2C和GPIO復用等,到底是使用GPIO還是其他介面,在初始化的時候,都需要對PINMUX0和PINMUX1兩個寄存器進行設置(見DM6446的晶元DATASHEET第3章),而軟體設置則在Montavista linux-2.6.18_pro500\arch\arm\mach-davinci目錄下mux_cfg.c和對應的mux.h里.本人這裡使用GPIO10、GPIO12、GPIO28,分別對應控制BUZZER、LED1、LED0,不需要對mux_cfg.c和mux.h進行修改.我們把這些GPIO應用歸入linux字元設備來移植. 二、GPIO源碼移植分析 /* drivers/char/davinci_dm644x_gpios.c*/ #include <linux/device.h> #include <linux/fs.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> #include <linux/types.h> #include <linux/cdev.h> #include <asm/uaccess.h> #include <asm/io.h> #include <asm/arch/hardware.h> #include <asm/arch/gpio.h> #define DEVICE_NAME "dm644x_gpios"

/*定義設備驅動的名字,或設備節點名稱*/ #define GPIO_MAJOR 199 /*使用 cat /proc/devices查看不要和存在的char節點重複*/ /*my app gpio define*/ #define DM644X_GPIO_BUZZER 10 /*GPIO10*/ #define DM644X_GPIO_LED1 12 /*GPIO10*/ #define DM644X_GPIO_LED0 28 /*GPIO10*/ static int davinci_dm644x_gpio_open(struct inode *inode, struct file *file) { return 0;/*該函數可以什麼都不做,也可以加入類似初始化的設置*/ } static int davinci_dm644x_gpio_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { switch(cmd) /*cmd 表示應用程序傳入的led動作,是on 還是off*/ { case 0: //gpio = 0 if(0==arg) /*arg由自己硬體電路決定使用那些GPIO*/ { gpio_direction_output(DM644X_GPIO_LED0, 0);/*調用TI linux-2.6.18寄存器驅動*/ } else if(1==arg) { gpio_direction_output(DM644X_GPIO_LED1, 0); } else if(2==arg) { gpio_direction_output(DM644X_GPIO_BUZZER, 0); } else { return -EINVAL; } break; case 1: //gpio = 1 if(0==arg) { gpio_direction_output(DM644X_GPIO_LED0, 1);

} else if(1==arg) { gpio_direction_output(DM644X_GPIO_LED1, 1); } else if(2==arg) { gpio_direction_output(DM644X_GPIO_BUZZER, 1); } else { return -EINVAL; } break; default: return -EINVAL; } } /*定義驅動設備文件API,在linux系統當中,任何設備都可以當做文件的方式操作,這一點和單片機和MCU有很大差別*/ static const struct file_operations davinci_dm644x_gpio_fileops = { .owner = THIS_MODULE, .open = davinci_dm644x_gpio_open, .ioctl = davinci_dm644x_gpio_ioctl, }; static int __init davinci_dm644x_gpio_init(void) /*內核初始化會調用該函數*/ { int ret; gpio_direction_output(DM644X_GPIO_LED0, 1); //led0 is on udelay(1); gpio_direction_output(DM644X_GPIO_LED1, 1); //led1 is on udelay(1); gpio_direction_output(DM644X_GPIO_BUZZER, 1); //BUZZER is on mdelay(500); /*初始化時,buzzer 發出聲音500ms*/ gpio_direction_output(DM644X_GPIO_BUZZER, 1); //BUZZER is off ret = register_chrdev(GPIO_MAJOR, DEVICE_NAME, &davinci_dm644x_gpio_fileops); if(ret < 0) { printk(DEVICE_NAME " register falid!\n"); return ret; } printk (DEVICE_NAME" initialized\n");

return ret; } static void __exit davinci_dm644x_gpio_exit(void) { unregister_chrdev(GPIO_MAJOR, DEVICE_NAME); } module_init(davinci_dm644x_gpio_init); module_exit(davinci_dm644x_gpio_exit); MODULE_AUTHOR("xxx <>"); MODULE_DESCRIPTION("Davinci DM644x gpio driver"); MODULE_LICENSE("GPL"); 這個驅動源碼是一種比較老的驅動移植,即register_chrdev(GPIO_MAJOR, DEVICE_NAME, &davinci_dm644x_gpio_fileops),靜態分配設備節點,適合linux-2.4.x和linux-2.6.10前的版本,當然也可以在2.6.18及以後的版本使用,現在新的版本char字元設備的移植可以參考davinci_resizer.c、davinci_previewer.c等文件. 上面的初始化函數調用udelay和msdelay,udelay一般適用於一個比較小的delay,如果你填的數大於2000,系統會認為你這個是一個錯誤的delay函數,因此如果需要2ms以上的delay需要使用mdelay函數. 由於這些delay函數本質上都是忙等待,對於長時間的忙等待意味這無謂的耗費著cpu的資源,因此對於毫秒級的延時,內核提供了msleep,ssleep等函數,這些函數將是的調用它的進程睡眠參數指定的時間. 寄存器級的驅動gpio_direction_output()函數是定義在linux-2.6.18_pro500/arch/arm/mach-davinci/下的gpio.c里,裡邊還有gpio_direction_input()和GPIO中斷函數. 三、修改內核配置文件 在linux-2.6.18_pro500/drivers/char目錄下, 修改Kconfig文件,在menu "Character devices"下面,加入 config DAVINCI_DM644X_GPIOS tristate "Davinci DM644x GPIO GPIOs" depends on ARCH_DAVINCI help This option enables support for LEDs and Buzzer connected to GPIO lines on Ti Davinci DM644x CPUs, such as the DM6446. 修改Makefile文件,在128行 obj-$(CONFIG_DAVINCI_DM646X_TSIF)

= tsif_control.o tsif_data.o下面,加入: obj-$( DAVINCI_DM644X_GPIOS) = davinci_dm644x_gpios.o 修改linux-2.6.18 內核menu配置 選上“Character devices”里的“Davinci DM644x GPIOs”,保存修改後的配置,然後make uImage,對內核的編譯; 四、GPIO應用程序源碼 源碼添加: /* dm644x_gpio_test.c*/ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> /* ./dm644x_gpio_test 0 1 */ //led0 on /* ./dm644x_gpio_test 0 0 */ //led0 off /* ./dm644x_gpio_test 1 1 */ //led1 on /* ./dm644x_gpio_test 1 0 */ //led1 off /* ./dm644x_gpio_test 2 1 */ // buzzer on /* ./dm644x_gpio_test 2 0 */ // buzzer off int main(int argc, char **argv) { int on; int gpio_number; int fd; // argv[0]== dm644x_gpio_test // argv[1]== gpio_number // argv[1]== on if (argc != 3 || sscanf(argv[1], "%d", &gpio_number) != 1 || sscanf(argv[2],"%d", &on) != 1 ||on < 0 || on > 1 || gpio _number < 0 || gpio _number > 3) { fprintf(stderr, "Usage:\n"); fprintf(stderr, "\t dm644x_gpio_test gpio_number on|off\n");

fprintf(stderr, "Options:\n"); fprintf(stderr, "\t gpio_number from 0 to 2\n"); fprintf(stderr, "\t on 1 off 0\n"); exit(1); } fd = open("/dev/dm644x_gpios", 0); if (fd < 0) { perror("open device /dev/dm644x_gpios"); exit(1); } ioctl(fd, on, gpio_number); close(fd); return 0; } Makefile添加: #application makefile for dm644x gpio test CROSSCOMPILE = arm_v5t_le- CC=$(CROSSCOMPILE)gcc LD=$(CROSSCOMPILE)ld OBJCOPY=$(CROSSCOMPILE)objcopy OBJDUMP=$(CROSSCOMPILE)objdump INCLUDE = /home/user/linux-2.6.18_pro500/include/*指向你的內核include*/ all: dm644x_gpio_test dm644x_gpio_test: dm644x_gpio_test.c $(CROSSCOMPILE)gcc -Wall -O2 dm644x_gpio_test.c -I $(INCLUDE) -o dm644x_gpio_test $(CROSSCOMPILE)strip dm644x_gpio_test cp -f dm644x_gpio_test /home/user/nfs/target/opt/app/ clean: @rm -vf dm644x_gpio_test *.o *~ 五、文件系統節點添加 文件系統里,/etc/init.d/rcS文件 #

Run /etc/rc.d/rc.local if it exists [ -x /etc/rc.d/rc.local ] && /etc/rc.d/rc.local 前面加mknod /dev/dm644x_gpios c 199 0或在shell命令行下執行mknod /dev/dm644x_gpios c 199 0;這就是靜態分配設備節點的做法. 運行系統,進入shell命令下, #cd / opt/app/ #./ dm644x_gpio_test 0 1可以控制點亮LED0 等等,有平台的朋友可以試試. 六、總結

本人拿一個比較簡單的設備驅動移植的例子來講解,目的讓大家理解davinci dm6446系統架構.由於時間倉促,以上可能會有不完善的地方,還請各位網友指點.Davinci dm6446 開發攻略到本章節,基本上一個完整的DM6446系統的框架基本介紹完了,感謝各位網友的支持,dm6446 開發攻略的文章也接近尾聲.由於很長一段時間忙著給購買我們產品的客戶搭建開發環境、codec環境,開發驅動,調試3G產品等等,更新博客的速度放慢下來,畢竟客戶的要求才是最重要的.同時也趕在51CTO 5周年紀念日到來之前,結束DM6446開發攻略的主體文章,算是告一個段落,以便為51CTO 5周年紀念寫篇感想文章做好鋪墊,畢竟來這個圈子也快一年了,有些東西總是需要總結的.


[火星人 ] Davinci DM6446開發攻略——LINUX GPIO驅動源碼移植已經有888次圍觀

http://coctec.com/docs/linux/show-post-50367.html