字符設(shè)備驅(qū)動(dòng),如果沒有調(diào)用device_create函數(shù),則表示需要使用mknod命令手動(dòng)創(chuàng)建設(shè)備
下面這個(gè)函數(shù)是字符設(shè)備實(shí)現(xiàn)的led驅(qū)動(dòng),這是最基本的字符設(shè)備驅(qū)動(dòng),設(shè)備文件需要使用手動(dòng)添加:
mknode? /dev/led c 主設(shè)備號(hào) 次設(shè)備號(hào)(可以是0)
這個(gè)驅(qū)動(dòng)加載的過程中出現(xiàn)這么兩個(gè)錯(cuò)誤:
(1)使用insmod加載驅(qū)動(dòng)時(shí):
insmod:can't load led.ko,invalid argument
原因:這是因?yàn)槌绦蛑姓{(diào)用的request_mem_region向內(nèi)核申請(qǐng)內(nèi)存失敗,返回-EINVAL
解決辦法:不使用這個(gè)函數(shù)
(2)出現(xiàn)段錯(cuò)誤
出現(xiàn)段錯(cuò)誤,一般是因?yàn)閷?duì)空指針進(jìn)行了解引用。經(jīng)過排查,報(bào)錯(cuò)原因是在writel函數(shù)中。
writel需要的參數(shù)如下:
writel(value,addr)
但是程序中卻將addr指針誤寫成一個(gè)unsigned int 的數(shù)據(jù),也就是說操作了一個(gè)未知的地址。因此將其修改后成功運(yùn)行。
通過這個(gè)程序,也明白了為什么有的驅(qū)動(dòng)使用alloc_chrdev_region,因?yàn)槭褂眠@個(gè)函數(shù),可以在后續(xù)的代碼中調(diào)用device_create進(jìn)行設(shè)備節(jié)點(diǎn)文件的自動(dòng)創(chuàng)建。
流程如下:
(1)使用alloc_chrdev_region(),申請(qǐng)一個(gè)主設(shè)備號(hào)和相當(dāng)數(shù)量的次設(shè)備號(hào)。
(2)使用class_create()創(chuàng)建自己的設(shè)備類,該函數(shù)在sys/class中定義。
(3)創(chuàng)建一個(gè)struct file_operations實(shí)例,每個(gè)設(shè)備都需要?jiǎng)?chuàng)建。傳遞給cdev_init和cdev_add初始化和注冊(cè)這個(gè)設(shè)備。
????????cdev_init:所需要的參數(shù):
????????(1)struct cdev的實(shí)例的地址。
????????(2)struct file_operations的實(shí)例的地址。
????????cdev_add所需要的參數(shù):
????????(1)struct cdev的實(shí)例的地址。
????????(2)設(shè)備號(hào)(使用MKDEV把主設(shè)備號(hào)與次設(shè)備號(hào)合并得到的數(shù)據(jù))。
????????(3)設(shè)備數(shù)量。
(4)調(diào)用device_create()函數(shù),根據(jù)跟定的設(shè)備文件名在/dev目錄下創(chuàng)建設(shè)備文件。