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