轉:: http://lwj8666.blog.163.com/blog/static/18966939200932864331567/
之前的我還不知道該如何寫init函數和exit函數,所以就嘗試着,借鑑一些已有的驅動,想歸納一下,有不同的版本所以,後來就我就Google了好幾篇文章,現在就藉助網上的資料在這裏總結一下:在這裏因爲linux2.4和linux2.6有區別,所以在這裏就如下書寫:
2.4內核註冊驅動要用:
int register_chrdev (unsigned int major, const char *name, struct
file_operations *fops);
2.4內核註銷驅動要用:
int unregister_chrdev( unsigned int major, const char *name
);
2.4內核驅動註冊完後,要用以下代碼創建設備文件
static devfs_handle_t
devfs_handle;
devfs_handle = devfs_register(
NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,
BUTTON_MAJOR,&sbc2410_buttons_fops, NULL);
2.4內核驅動要用以下代碼移除設備文件:
devfs_unregister( devfs_handle);
-----------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------
2.6驅動i註冊設備號要用:
(1)如果主設備號事先知道,要用:
int register_chrdev_region( dev_t first, unsigned int count, char
*name );
(2)如果主設備號爲0,則要用動態分配:
int alloc_chrdev_region( dev_t *dev, unsigned int firstminor,
unsigned
int count, char *name );
2.6釋放設備號要用:
void unregister_chrdev_region( dev_t first, unsigned int count
);
2.6內核字符設備驅動註冊要用:
struct cdev *my_cdev = cdev_alloc();
my_cdev->ops = &chr_fops;
void cdev_init( struct cdev *cdev, struct file_operations
*fops);
int cdev_add( struct cdev *dev, dev_t num, unsigned int
count);
2.6內核字符設備驅動移除要用:
void cdev_del( struct cdev *dev );
2.6內核驅動註冊完後,要用以下代碼創建設備文件
devfs_mk_cdev( MKDEV(LED_MAJOR, LED_MINOR),
S_IFCHR
| S_IRUSR | S_IWUSR | S_IRGRP, DEVICE_NAME);
2.6內核驅動要用以下代碼移除設備文件:
devfs_remove(DEVICE_NAME);
-----------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------
以上也可以用命令創建設備文件:
mknod /dev/設備文件名
字符設備(c是字符設備,b是塊設備) 主設備號
次設備號
例如:mknod /dev/testChar c 100
0
刪除設備入口:
rm
/dev/testChar
-----------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------
2.4驅動總體編寫框架:
static int __init my_init(void)
{
//註冊設備驅動
register_chrdev (unsigned int major, const char *name, struct
file_operations *fops);
//創建設備文件
static devfs_handle_t devfs_handle;
devfs_handle = devfs_register(
NULL, DEVICE_NAME, DEVFS_FL_DEFAULT,
BUTTON_MAJOR,&sbc2410_buttons_fops, NULL);
}
static int __exit my_exit(void)
{
//移除設備文件
devfs_unregister( devfs_handle);
//註銷設備驅動
unregister_chrdev( unsigned int major, const char *name );
}
module_init( my_init );
module_exit( my_exit );
-----------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------
2.6驅動總體編寫框架:
static int __init my_init(void)
{
//分配設備編號
if(主設備號)
{
sbc2440_leds_dev = MKDEV
(LED_MAJOR, LED_MINOR);
result = register_chrdev_region
(sbc2440_leds_dev, count, DEVICE_NAME);
}
else
{
result = alloc_chrdev_region
(&sbc2440_leds_dev, LED_MINOR, count,
DEVICE_NAME);
LED_MAJOR = MAJOR
(sbc2440_leds_dev);
}
//註冊字符設備驅動
sbc2440_leds_cdev = cdev_alloc();
if (sbc2440_leds_cdev != NULL)
{
cdev_init (sbc2440_leds_cdev,
&sbc2440_leds_fops);
sbc2440_leds_cdev->ops
= &sbc2440_leds_fops;
sbc2440_leds_cdev->owner
= THIS_MODULE;
if (cdev_add
(sbc2440_leds_cdev, sbc2440_leds_dev, count) )
printk (KERN_NOTICE "Someting
wrong when adding sbc2440_leds_cdev!\n");
else
printk ("Success adding
sbc2440_leds_cdev!\n");
}
//創建設備文件
devfs_mk_cdev(MKDEV(LED_MAJOR, 0), S_IFCHR | S_IRUSR | S_IWUSR |
S_IRGRP, DEVICE_NAME);
}
static int __exit my_exit(void)
{
//移除設備文件
devfs_remove(DEVICE_NAME);
//註銷字符設備
cdev_del (sbc2440_leds_cdev);
//釋放設備編號:
unregister_chrdev_region (sbc2440_leds_dev, count);
}
module_init( my_init );
module_exit( my_exit );
------------------------
驅動程序的編譯:
驅動程序在編譯之前,所使用的內核必須要經過編譯,否則驅動程序不能編譯。
驅動有用函數
set_irq_type函數
在set_irq_type(irq,type)中的type如下:
#define IRQT_NOEDGE (0)
#define IRQT_RISING (__IRQT_RISEDGE) 上升沿有效
#define IRQT_FALLING (__IRQT_FALEDGE) 下升沿有效
#define IRQT_BOTHEDGE (__IRQT_RISEDGE|__IRQT_FALEDGE) 雙邊沿有效
#define IRQT_LOW (__IRQT_LOWLVL) 低電平有效
#define IRQT_HIGH
(__IRQT_HIGHLVL) 高電平有效
#define IRQT_PROBE (1 << 4)
按鍵驅動總結:
set_gpio_mode_user(k->gpio_port, GPIO_MODE_IN
);
up = read_gpio_bit(k->gpio_port);
s3c2410_gpio_cfgpin(k->gpio_port,
k->gpio_set);
set_irq_type( k->irq_no, IRQT_RISING );
以上這段代碼的功能是:
第一條是設置GPIO端口的使用模式,在此爲輸入模式,總共有4種模式,分別爲:
1,GPIO_MODE_IN(輸入模式)
2,GPIO_MODE_OUT(輸出模式)
3,GPIO_MODE_ALT0(第三功能)
4,GPIO_MODE_ALT1(第四功能)
第二條是讀取gpio端口的信號。
第三條是初始化端口
第四條是設置中斷觸發方式。
實現了從io口讀取信號,在此爲上升沿讀取有效。
在申請中斷之前,必須對端口進行初始化,否則端口不能使用。在中斷處理程序的最後,還要對端口進行復位,即恢復到申請中斷前初始化時的狀態。
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP
S_IRUSR
Permits(允許) the file's owner to
read it.
S_IWUSR
Permits the file's owner to
write to it.
S_IRGRP
Permits the file's group to
read it.
S_IWGRP
Permits the file's group to
write to it.
歷史上的今天
相關文章
- Tq2440 驅動學習(2)-beep驅動2011-08-10 15:34:49
- 驅動模塊加載問題2011-01-09 00:38:02
- 自己--觸摸屏驅動2011-10-02 18:19:34
- i2c設備驅動2011-09-29 16:37:12
- 2410中斷驅動程序(轉)2011-01-07 21:13:18