日韩床上生活一级视频|能看毛片的操逼网站|色悠悠网站在线观看视频|国产免费观看A淫色免费|国产av久久久久久久|免费A级视频美女网站黄|国产毛片av日韩小黄片|热久久免费国产视频|中文字幕无码色色|成人在线视频99久久久

機(jī)電之家資源網(wǎng)
單片機(jī)首頁(yè)|單片機(jī)基礎(chǔ)|單片機(jī)應(yīng)用|單片機(jī)開(kāi)發(fā)|單片機(jī)文案|軟件資料下載|音響制作|電路圖下載 |嵌入式開(kāi)發(fā)
培訓(xùn)信息
贊助商
CAN能信卡的Linux設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)實(shí)現(xiàn)
CAN能信卡的Linux設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)實(shí)現(xiàn)
 更新時(shí)間:2008-8-16 21:10:34  點(diǎn)擊數(shù):24
【字體: 字體顏色


    2.2 CAN通信卡設(shè)備驅(qū)動(dòng)程序的中斷處理部分

Linux中斷處理程序可以分為上半部和下半部。上半部即一般的中斷服務(wù)程序,由硬件中斷觸發(fā),它一般運(yùn)行在關(guān)中斷的方式下,應(yīng)當(dāng)盡可能短小,處理盡可能快;而下半部是單獨(dú)的一段處理程序,一般將其掛入立即隊(duì)列中以便快速執(zhí)行。立即隊(duì)列中的任務(wù)在退出系統(tǒng)調(diào)用或調(diào)度器獲得運(yùn)行時(shí),將最優(yōu)先地被執(zhí)行。下半部運(yùn)行在一個(gè)安全的環(huán)境,即開(kāi)中斷和任務(wù)串行化,可以處理一些較花時(shí)間的任務(wù)。

這樣,驅(qū)動(dòng)程序上半部在處理完實(shí)時(shí)性很強(qiáng)的任務(wù)后,用queue_task()函數(shù)將下半部處理函數(shù)持入立即隊(duì)列,并用mark_bh()函數(shù)來(lái)激活立即隊(duì)列,則下半部可以最優(yōu)先地被執(zhí)行。

當(dāng)有接收中斷時(shí),CAN通信卡設(shè)備驅(qū)動(dòng)程序的中斷處理程序上半部首先獲取驅(qū)動(dòng)程序接收緩存中的空閑塊,將CAN通信卡上的接收緩沖器中數(shù)據(jù)復(fù)制到驅(qū)動(dòng)程序的接收緩存中,釋放CAN通信卡接收緩沖器,然后將下半部處理函數(shù)掛入立即隊(duì)列,最后激活立即隊(duì)列。

當(dāng)有發(fā)送中斷時(shí),CAN通信卡設(shè)備驅(qū)動(dòng)程序的中斷處理程序上半部首先獲取發(fā)送緩沖隊(duì)列中的數(shù)據(jù),將需要發(fā)送的數(shù)據(jù)寫入CAN控制器的發(fā)送緩沖器,最后請(qǐng)求發(fā)送。

CAN通信卡設(shè)備驅(qū)動(dòng)程序的中斷處理程序下半部使用Hilon A協(xié)議對(duì)要傳送到CAN網(wǎng)絡(luò)上的數(shù)據(jù)打包,并對(duì)從CAN網(wǎng)絡(luò)上接收到的數(shù)據(jù)進(jìn)行解包和組幀。這樣中斷處理程序的上半部只需要從CAN通信卡的緩沖器中將數(shù)據(jù)復(fù)制到驅(qū)動(dòng)程序的緩沖區(qū),系統(tǒng)開(kāi)銷很小,但很費(fèi)CPU時(shí)間;系統(tǒng)開(kāi)銷較大的打包、解包和組幀處理則放在中斷處理程序的下半部,使用系統(tǒng)非中斷時(shí)間調(diào)度,可以使系統(tǒng)響應(yīng)中斷更快,通信更穩(wěn)定。

2.3 緩沖區(qū)管理

在CAN通信卡設(shè)備驅(qū)動(dòng)程序中,為了增強(qiáng)CAN通信卡的通信能力、提高通信效率,根據(jù)CAN的特點(diǎn),使用兩級(jí)緩沖區(qū)結(jié)構(gòu),即直接面向CAN通信卡的收發(fā)緩沖區(qū)和直接面向系統(tǒng)調(diào)用的接收幀緩沖區(qū)。

通訊中的收發(fā)緩沖區(qū)一般采用環(huán)形隊(duì)列(或稱為FIFO隊(duì)列),使用環(huán)形的緩沖區(qū)可以使得讀寫并發(fā)執(zhí)行,讀進(jìn)程和寫進(jìn)程可以采用“生產(chǎn)者和消費(fèi)者”的模型來(lái)訪問(wèn)緩沖區(qū),從而方便了緩存的使用和管理。然而,環(huán)形緩沖區(qū)的執(zhí)行效率并不高,每讀一個(gè)字節(jié)之前,需要判斷緩沖區(qū)是否為空,并且移動(dòng)尾指針時(shí)需要進(jìn)行“折行處理”(即當(dāng)指針指到緩沖區(qū)內(nèi)存的末尾時(shí),需要新將其定向到緩沖區(qū)的首地址);每寫一個(gè)字節(jié)之前,需要判斷緩區(qū)是否為,并且移動(dòng)尾指針時(shí)同樣需要進(jìn)行“折行處理”。程序大部分的執(zhí)行過(guò)程都是在處理個(gè)別極端的情況。只有小部分在進(jìn)行實(shí)際有效的操作。這就是軟件工程中所謂的“8比2”關(guān)系。結(jié)合CAN通訊實(shí)際情況,在本設(shè)計(jì)中對(duì)環(huán)形隊(duì)列進(jìn)行了改進(jìn),可以較大地提高數(shù)據(jù)的收發(fā)效率。

由于CAN通信卡上接收和發(fā)送緩沖器每次只接收一幀CAN數(shù)據(jù),而且根據(jù)CAN的通訊協(xié)議,CAN控制器的發(fā)送數(shù)據(jù)由1個(gè)字節(jié)的標(biāo)識(shí)符、一個(gè)字節(jié)的RTR和DLC位及8個(gè)字節(jié)的數(shù)據(jù)區(qū)組成,共10個(gè)字節(jié);接收緩沖器與之類似,也有10個(gè)字節(jié)的寄存器。所以CAN控制器收的數(shù)據(jù)是短小的定長(zhǎng)幀(數(shù)據(jù)可以不滿8字節(jié))。

于是,采用度為10字節(jié)的數(shù)據(jù)塊業(yè)分配內(nèi)存比較方便,即每次需要內(nèi)存緩沖區(qū)時(shí),直接分配10個(gè)字節(jié),由于這10個(gè)字節(jié)的地址是線性的,故不需要進(jìn)行“折行”處理。更重要的是,在向緩沖區(qū)中寫數(shù)據(jù)時(shí),只需要判斷一次是否有空閑塊并獲取其塊首指針就可以了,從而減少了重復(fù)性的條件判斷,大大提高了程序的執(zhí)行效率;同樣在從緩沖隊(duì)列中讀取數(shù)據(jù)時(shí),也是一次讀取10字節(jié)的數(shù)據(jù)塊,同樣減少了重復(fù)性的條件判斷。

在CAN卡驅(qū)動(dòng)程序中采用如下所示的稱為“Block_Ring_t”的數(shù)據(jù)結(jié)構(gòu)作為收發(fā)數(shù)據(jù)的緩沖區(qū):

typedef struct {

log signature;

unsigned char *head_p;

unsigned char *tail_p;

unsigned char *begin_p;

unsigned char *end_p;

unsigned char buffer [BLOCK_RING_BUFFER_SIZE];

int usedbytes;

}Block_Ring_t;

該數(shù)據(jù)結(jié)構(gòu)在通用的環(huán)形隊(duì)列上增加了一個(gè)數(shù)據(jù)成員usedbytes,它表示當(dāng)前緩沖區(qū)中有多少字節(jié)的空間被占用了。使用usedbytes,可以比較方便地進(jìn)行緩沖區(qū)滿或空的判斷。當(dāng)usedbytes=0時(shí),緩沖區(qū)空;當(dāng)usedbytes=BLOCK_RING_BUFFER_SIZE時(shí),緩沖區(qū)滿。

本驅(qū)動(dòng)程序除了收發(fā)緩沖區(qū)外,還有一個(gè)接收幀緩沖區(qū),接收幀隊(duì)列負(fù)責(zé)管理經(jīng)Hilon A協(xié)議解包后得到的數(shù)據(jù)幀。由于有可能要同接收多個(gè)數(shù)據(jù)幀,而根據(jù)CAN總線遙通信協(xié)議,高優(yōu)先級(jí)的報(bào)文將搶占總線,則有可能在接收一個(gè)低優(yōu)先級(jí)且被分為好幾段發(fā)送的數(shù)據(jù)幀時(shí),被一個(gè)優(yōu)先級(jí)高的數(shù)據(jù)幀打斷。這樣會(huì)出現(xiàn)同時(shí)接收到多個(gè)數(shù)據(jù)幀中的數(shù)據(jù)包,因而需要有個(gè)接收隊(duì)列對(duì)同時(shí)接收的數(shù)據(jù)幀進(jìn)行管理。

當(dāng)有新的數(shù)據(jù)包到來(lái)時(shí),應(yīng)根據(jù)addr(通訊地址),mode(通訊方式),index(數(shù)據(jù)包的序號(hào))來(lái)判斷是否是新的數(shù)據(jù)幀。如果是,則開(kāi)辟新的frame_node;否則如果已有相應(yīng)的幀節(jié)點(diǎn)存地,則將數(shù)據(jù)附加到該幀的末尾;在插入數(shù)據(jù)的同時(shí),應(yīng)該檢查接收包的序號(hào)是否正確,如不正確將丟棄這包數(shù)據(jù)。

每次建立新的frame_node時(shí),需要向frame_queue申請(qǐng)內(nèi)存空間;當(dāng)frame_queue已滿時(shí),釋放掉隊(duì)首的節(jié)點(diǎn)(最早接收的但未完成的幀)并返回該節(jié)點(diǎn)的指針。

當(dāng)系統(tǒng)調(diào)用讀取了接收幀后,釋放該節(jié)點(diǎn)空間,使設(shè)備驅(qū)動(dòng)程序可以重新使用該節(jié)點(diǎn)。

2.4 服務(wù)于I/O請(qǐng)求的設(shè)備驅(qū)動(dòng)程序部分

這部分實(shí)際上是應(yīng)用程序唯一可見(jiàn)的,應(yīng)用程序通過(guò)系統(tǒng)來(lái)調(diào)用這部分程序,是設(shè)備驅(qū)動(dòng)程序?qū)?yīng)用程序的接口。本驅(qū)動(dòng)程序提供文件操作接口。Linux系統(tǒng)中,字符型設(shè)備驅(qū)動(dòng)程序提供的文件操作入口點(diǎn)由一個(gè)結(jié)構(gòu)來(lái)向系統(tǒng)說(shuō)明,此結(jié)構(gòu)定義為:

struct file_operations {

int (*lseek)(strut inode *inode,struct file *file,off_toff,int pos);

int (*read)(struct inode *inode,struct file *filp,char *buf,int count);

int (*write)(struct inode *inode,struct file *file,char *buf,int count);

int (*readdir)(struct inode *inode,struct file *filp,struct dirent *dirent,int count);

int (*select)(struct inode *inode,struct file *filp,int sel_type,select_table *wait);

int (*ioctl)(struct inode *inode,struct file *filp,unsigned int cmd,unsigned int arg);

int (*mmap)(void);

int (*open)(struct inode *inode,struct file *filp);

void (*release)(struct inode *inode,struct file filp);int (fsync) (struct inode *inode,struct file *filp);

};

該結(jié)構(gòu)定義為10個(gè)操作入口點(diǎn),但是驅(qū)動(dòng)程序沒(méi)有必要對(duì)每個(gè)入口點(diǎn)進(jìn)行定義。根據(jù)需要,本驅(qū)動(dòng)程序定義了如下的入口點(diǎn)。

can_open(struct inode *inode,struct file *filp)入口點(diǎn)負(fù)責(zé)打開(kāi)can設(shè)備,檢查can卡是否已被打開(kāi),完成can卡的初始化,設(shè)備設(shè)備的占用標(biāo)志。can_release(struct inode *inode,struct file *filp)入口點(diǎn)負(fù)責(zé)關(guān)閉can設(shè)備。

can_read(struct inode *,struct file , off_t,int)入口點(diǎn)負(fù)責(zé)檢查設(shè)備有沒(méi)有接收到完整的幀,can_read函數(shù)只是判斷是否有完整的數(shù)據(jù)幀可讀。要獲取數(shù)據(jù)幀,可以使用ioctl的CAN_READFRAME命令。can_write(struct inode,struct file *,const char *,int)入口點(diǎn)負(fù)責(zé)向CAN發(fā)送數(shù)據(jù)。如果發(fā)送隊(duì)列有足夠的空間,則向設(shè)備傳送數(shù)據(jù),也可以使用ioctl的CAN_WRITEFRAME命令來(lái)實(shí)現(xiàn)can_write。

Can_inoctl(struct inode *,struct file *,unsigned int cmd,unsigned long arg)入口點(diǎn)負(fù)責(zé)向CAN設(shè)備下發(fā)各種操作命令,命令代碼通過(guò)cmd參數(shù)傳送,命令參數(shù)通過(guò)arg參數(shù)傳送。本驅(qū)動(dòng)程序提供了一些命令,配合can_read()和can_write()可以實(shí)現(xiàn)對(duì)CAN通信卡的控制。CAN_IOCREADFFRAME命令可以從CAN通信卡上讀取數(shù)據(jù)幀;CAN_IOCWRITEFRAME命令可以向CAN通信卡發(fā)送數(shù)據(jù);CAN_IOCSETCONF命令可以設(shè)備CAN通信卡的運(yùn)行參數(shù);CAN_IOCGETCONF命令可以獲取CAN控制器的運(yùn)行參數(shù);CAN_IOCQUERY-BUSSTATE命令可以查詢CAN總線狀態(tài);CAN_INCCLEARBUF命令可以清除CAN通信卡的收發(fā)緩沖區(qū)。

本設(shè)備驅(qū)動(dòng)程序考慮到CAN通信卡的特點(diǎn)如CAN網(wǎng)絡(luò)傳輸數(shù)據(jù)的特點(diǎn),設(shè)計(jì)了合理的數(shù)據(jù)結(jié)構(gòu)和緩存管理方法,使得當(dāng)有大量數(shù)據(jù)進(jìn)出CAN通信卡時(shí),既可以保證數(shù)據(jù)幀丟失和出錯(cuò)幾率在允許范圍內(nèi),又可以保證數(shù)據(jù)幀能被快速下發(fā)和接收,實(shí)現(xiàn)應(yīng)用中性能很好。Linux擅長(zhǎng)通信,支持大多數(shù)以太網(wǎng)卡。如果將CAN通信卡的設(shè)備驅(qū)動(dòng)程序加入到Linux系統(tǒng),由于Linux的可裁減性和對(duì)硬件資源要求低的特點(diǎn),可以用小硬盤、小內(nèi)存和低檔CPU構(gòu)成通信機(jī)連接高速以太網(wǎng)和低速現(xiàn)場(chǎng)總線CAN網(wǎng)絡(luò),經(jīng)濟(jì)實(shí)惠而且實(shí)用。

  • 上一篇: DTMF信號(hào)收、發(fā)芯片在微機(jī)通信中的應(yīng)用
  • 下一篇: 一種電力線擴(kuò)頻載波通訊節(jié)點(diǎn)的具體實(shí)現(xiàn)
  • 發(fā)表評(píng)論   告訴好友   打印此文  收藏此頁(yè)  關(guān)閉窗口  返回頂部
    熱點(diǎn)文章
     
    推薦文章
     
    相關(guān)文章
    網(wǎng)友評(píng)論:(只顯示最新5條。)
    關(guān)于我們 | 聯(lián)系我們 | 廣告合作 | 付款方式 | 使用幫助 | 機(jī)電之家 | 會(huì)員助手 | 免費(fèi)鏈接

    點(diǎn)擊這里給我發(fā)消息66821730(技術(shù)支持)點(diǎn)擊這里給我發(fā)消息66821730(廣告投放) 點(diǎn)擊這里給我發(fā)消息41031197(編輯) 點(diǎn)擊這里給我發(fā)消息58733127(審核)
    本站提供的機(jī)電設(shè)備,機(jī)電供求等信息由機(jī)電企業(yè)自行提供,該企業(yè)負(fù)責(zé)信息內(nèi)容的真實(shí)性、準(zhǔn)確性和合法性。
    機(jī)電之家對(duì)此不承擔(dān)任何保證責(zé)任,有侵犯您利益的地方請(qǐng)聯(lián)系機(jī)電之家,機(jī)電之家將及時(shí)作出處理。
    Copyright 2007 機(jī)電之家 Inc All Rights Reserved.機(jī)電之家-由機(jī)電一體化網(wǎng)更名-聲明
    電話:0571-87774297 傳真:0571-87774298
    杭州濱興科技有限公司提供技術(shù)支持

    主辦:杭州市高新區(qū)(濱江)機(jī)電一體化學(xué)會(huì)
    中國(guó)行業(yè)電子商務(wù)100強(qiáng)網(wǎng)站

    網(wǎng)站經(jīng)營(yíng)許可證:浙B2-20080178-1