前面,我們基本已經學會怎么去編寫一個簡單的字符設備驅動程序了,這節,我們來看看友善之臂中提供的led驅動。
參考之前寫的文章,我們已經知道LED的GPIO口,和一些配置信息:
http://blog.csdn.net/morixinguan/article/details/50619675
在友善之臂提供的內核中,已經有一個文件對這些GPIO做了對應的封裝,
在drivers/gpio/gpio_dvs/exynos4x12_gpio_dvs.c中:
我們打開這個文件,找到LED對應的四個IO口的宏如下:
EXYNOS4212_GPM4(0),EXYNOS4212_GPM4(1),EXYNOS4212_GPM4(2),EXYNOS4212_GPM4(3),
操作GPIO,我們需要這三個.h的頭文件,
#include <linux/gpio.h>#include <mach/gpio.h>#include <plat/gpio-cfg.h>
這幾個頭文件有通用的,也有與平臺相關的。
需要以下幾個函數:
gpio_request
gpio_set_value
s3c_gpio_cfgpin
gpio_set_value
gpio_free
接下來看源碼的注釋分析:
#include <linux/kernel.h>#include <linux/module.h>#include <linux/miscdevice.h>#include <linux/fs.h>#include <linux/types.h>#include <linux/moduleparam.h>#include <linux/slab.h>#include <linux/ioctl.h>#include <linux/cdev.h>#include <linux/delay.h> #include <linux/gpio.h>#include <mach/gpio.h>#include <plat/gpio-cfg.h>#define DEVICE_NAME "leds"//找到LED管腳對應的宏static int led_gpios[] = { EXYNOS4212_GPM4(0), EXYNOS4212_GPM4(1), EXYNOS4212_GPM4(2), EXYNOS4212_GPM4(3),};#define LED_NUM ARRAY_SIZE(led_gpios)//操作LED燈//傳入1,亮燈//傳入0,滅燈static long tiny4412_leds_ioctl(struct file *filp, unsigned int cmd, unsigned long arg){ switch(cmd) { case 0: case 1: if (arg > LED_NUM) { return -EINVAL; } //LED是低電平點亮的,傳入1亮,傳入0滅,是因為cmd做了取反的操作 //gpio_set_value這個函數是對IO賦值 gpio_set_value(led_gpios[arg], !cmd); //PRintk(DEVICE_NAME": %d %d/n", arg, cmd); break; default: return -EINVAL; } return 0;}//led操作文件結構體static struct file_Operations tiny4412_led_dev_fops = { .owner = THIS_MODULE, .unlocked_ioctl = tiny4412_leds_ioctl,};//雜類設備結構體static struct miscdevice tiny4412_led_dev = { .minor = MISC_DYNAMIC_MINOR, .name = DEVICE_NAME, .fops = &tiny4412_led_dev_fops,};//led驅動加載static int __init tiny4412_led_dev_init(void) { int ret; int i; for (i = 0; i < LED_NUM; i++) { //對GPIO注冊與申請內存,并給設備驅動取名為LED ret = gpio_request(led_gpios[i], "LED"); if (ret) { printk("%s: request GPIO %d for LED failed, ret = %d/n", DEVICE_NAME, led_gpios[i], ret); return ret; } //調用該函數,將所有的IO設置為輸出狀態 s3c_gpio_cfgpin(led_gpios[i], S3C_GPIO_OUTPUT); //默認情況下所有的IO初始化都亮 gpio_set_value(led_gpios[i], 1); } //雜類設備注冊 ret = misc_register(&tiny4412_led_dev); printk(DEVICE_NAME"/tinitialized/n"); return ret;}static void __exit tiny4412_led_dev_exit(void) { int i; for (i = 0; i < LED_NUM; i++) { //釋放申請的IO和內存 gpio_free(led_gpios[i]); } //注銷雜類設備驅動 misc_deregister(&tiny4412_led_dev);}module_init(tiny4412_led_dev_init);module_exit(tiny4412_led_dev_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("FriendlyARM Inc.");有了這個框架,我們就可以拿來修改了,我們還可以往tiny4412_led_dev_fops中繼續添加read,write,close,lseek函數,來實現LED的其它操作,有興趣的同學可以試一試,這些驅動在以前我已經測試過了,這里僅僅只是對這些知識點進行再次總結。
新聞熱點
疑難解答