嵌入式uClinux下的CAN總線設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)
3)定義驅(qū)動(dòng)程序的文件結(jié)構(gòu)
在LINUX系統(tǒng)中,對(duì)硬件設(shè)備的訪問也是被當(dāng)作文件來操作的。這里定義的文件接口將可以在外部的應(yīng)用程序中被調(diào)用。在CAN驅(qū)動(dòng)程序中,只定義了讀CAN信息(CAN接收)、向CAN節(jié)點(diǎn)寫信息(CAN發(fā)送)、打開CAN設(shè)備、關(guān)閉CAN設(shè)備等4個(gè)文件接口。定義信息如下面的程序所示。在sja1000_fops中所定義的函數(shù)都必須在驅(qū)動(dòng)程序中編寫。
static struct file_operations sja1000_fops = {
read: sja1000_read, //CAN接收數(shù)據(jù)
write: sja1000_write,//CAN發(fā)送
open: sja1000_open, //打開設(shè)備S3C2410 開發(fā)板II(B)+3.5寸帶觸摸TFT液晶屏
release: sja1000_release, };//關(guān)閉設(shè)備
4)定義sja1000_write :CAN發(fā)送函數(shù)(寫函數(shù))
static int sja1000_write(struct file *filp, const char *buf, size_t size,
loff_t *offp){ }
在CAN總線控制器Sja1000初始化完成后,即可設(shè)置CAN發(fā)送,具體對(duì)sja1000寄存器的相關(guān)操作的相關(guān)程序可參閱SJA1000器件的數(shù)據(jù)手冊(cè)。
5)定義sja1000_read :CAN接收函數(shù)(讀函數(shù))
static int sja1000_read(struct file *filp, char *buf, size_t size,
loff_t *offp) { }
該函數(shù)完成對(duì)CAN總線網(wǎng)絡(luò)上相應(yīng)信息的接收。在本系統(tǒng)中CAN接收采用的是查詢方式。
6)編寫sja1000_open:文件打開函數(shù)
static int sja1000_open(struct inode *inode,struct file *file) { }S3C2410 開發(fā)板II(B)+3.5寸帶觸摸TFT液晶屏
進(jìn)程調(diào)用該函數(shù)表示對(duì)設(shè)備的占用。如果返回為-1,表示設(shè)備已被其他進(jìn)程占用,打開非法。如果采用中斷方式,對(duì)中斷的注冊(cè)也可放在本函數(shù)中。
7)編寫sja1000_release:文件關(guān)閉函數(shù)
static int sja1000_release(struct inode *inode, struct file *file) { }
該函數(shù)進(jìn)程完成對(duì)設(shè)備占有權(quán)的釋放,釋放后,其他的進(jìn)程就可以訪問這個(gè)設(shè)備了。
8)編寫sja1000_init(void):void sja1000_init(void) { } CAN設(shè)備初始化函數(shù)
該函數(shù)完成設(shè)備在LINUX內(nèi)核中的登記。并完成對(duì)sja1000初始化。
Sja1000寄存器配置通過調(diào)用上面已寫好的sja_write()函數(shù)完成。驅(qū)動(dòng)函數(shù)登記我們采用的是靜態(tài)加載的方式,通過調(diào)用register_chrdev()完成,程序如下:
if(result = register_chrdev(254,"sja1000",sja1000_fops)) S3C2410 開發(fā)板II(B)+3.5寸帶觸摸TFT液晶屏
printk("S3C4510-sja1000: Error %d registering device sja1000", result);
其中,254是為sja1000設(shè)備分配的主設(shè)備號(hào),“sja1000”是顯示在/dev中的設(shè)備名,sja1000_fops為對(duì)應(yīng)的文件系統(tǒng)指針。返回值小于0表示失敗,大于或等于0表示成功。
9)將驅(qū)動(dòng)程序加到uClinux內(nèi)核中
當(dāng)驅(qū)動(dòng)程序sja1000.c編寫完成后,下面的工作就是將它加到uClinux內(nèi)核中了。這需要修改uClinux的源代碼,然后重新編譯uClinux內(nèi)核。
①將設(shè)備驅(qū)動(dòng)程序文件sja1000.c復(fù)制到/uClinux-dist/linux/drivers/char目錄下。該目錄保存了uClinux字符設(shè)備的設(shè)備驅(qū)動(dòng)程序。修改該目錄下mem.c文件,在Init chrdev_init()函數(shù)中增加如下代碼:
#ifdef CONFIG_SJA1000_DRIVER device_init() #endifS3C2410 開發(fā)板II(B)+3.5寸帶觸摸TFT液晶屏
其中CONFIG_SJA1000_DRIVER是在配置uClinux內(nèi)核時(shí)賦值的。
?、谠趗Clinux/linux/drivers/char目錄下 Makefile中增加如下代碼:
ifeq($(CONFIG_SJA1000_DRIVER,y) L_OBJS+=sja1000.c endif
如果在配置uClinux內(nèi)核的時(shí)候選擇了支持我們定義的設(shè)備,則在編譯內(nèi)核的時(shí)候會(huì)編譯sja1000.c,生成 sja1000.o文件。
?、坌薷?/uClinux-dist/linux/arch/m68knonunu目錄下 config.in文件,在 comment' Character devices’語句下面加上
bool 'support for sja1000 driver'CONFIG_SJA1000_DRIVERS3C2410 開發(fā)板II(B)+3.5寸帶觸摸TFT液晶屏
這樣,在編譯內(nèi)核,運(yùn)行make menuconfig的時(shí)候,且在配置字符設(shè)備時(shí)就會(huì)有選項(xiàng):
support for sja1000 driver 當(dāng)選中這個(gè)選項(xiàng)的時(shí)候,設(shè)備驅(qū)動(dòng)就加到內(nèi)核中了。
?、茉趓omfs中加上設(shè)備驅(qū)動(dòng)程序?qū)?yīng)的設(shè)備文件。設(shè)備文件都被包含在/dev目錄下。uClinux中使用的根文件系統(tǒng)是romfs文件系統(tǒng)。這個(gè)文件系統(tǒng)是一個(gè)只讀文件系統(tǒng),所以設(shè)備文件必須在編譯內(nèi)核的時(shí)候加到romfs文件系統(tǒng)的image中。
不同的硬件系統(tǒng)對(duì)應(yīng)不同的設(shè)備文件,在/uClinux-dist/vendors目錄下,分別定義了它們的Makefile文件。在uClinux-dist/Vendors里S3C4510對(duì)應(yīng)的目錄下找到它的Makefile文件,并找到區(qū)域DEVICES= tty,c,5,0 console,c,5,1 cua0,c,5,64 cual,c,5,65,在后面再加上設(shè)備項(xiàng) sja1000,c,254,1就行了。
?、壑匦戮幾g內(nèi)核;在shell中將當(dāng)前目錄cd到uClinux-dist目錄下,然后:S3C2410 開發(fā)板II(B)+3.5寸帶觸摸TFT液晶屏
#make menuconfig #make dep #make
當(dāng)驅(qū)動(dòng)程序和uClinux內(nèi)核一起編譯鏈接并生成映像下載到目標(biāo)板運(yùn)行以后,可以通過查看/proc/devices,如果已經(jīng)顯示有sja1000,則表明設(shè)備加載成功。如果使用了中斷,也可以查看/proc/interrupts,該文件記錄了當(dāng)時(shí)已經(jīng)完成的所有系統(tǒng)中斷情況。
4、結(jié)束語
實(shí)時(shí)性方面,可以使用進(jìn)程間通信如管道、消息隊(duì)列、共享內(nèi)存等方法將CAN總線的接收中斷與應(yīng)用程序直接關(guān)聯(lián),加快系統(tǒng)對(duì)CAN總線事件的響應(yīng)速度。進(jìn)一步可以通過RTLinux和RTAI(Real Time Application Interface)這兩種方案增強(qiáng)uClinux的實(shí)時(shí)性。
本文作者創(chuàng)新點(diǎn):有效地解決了在沒有MMU的CPU之上開發(fā)一些簡單任務(wù)操作系統(tǒng)或控制程序效率低、程序簡單的缺點(diǎn)。通過使用嵌入式uClinux,它既保存了原先Linux操作系統(tǒng)穩(wěn)定性、功能強(qiáng)大等優(yōu)點(diǎn),又對(duì)內(nèi)核的代碼重新編寫,減少了內(nèi)核容量,提高了效率。同時(shí)也提出了在CAN總線設(shè)備下設(shè)計(jì)驅(qū)動(dòng)程序的方法。
評(píng)論