鄭翔,岳浩嶺
(杭州電子科技大學(xué)電子信息學(xué)院,杭州310018)
CC1101是TI公司推出的一款低于1GHz的高性能射頻收發(fā)器,設(shè)計(jì)旨在用于極低功耗RF 應(yīng)用,其主要針對(duì)工業(yè)、科研、醫(yī)療(ISM),以及短距離無(wú)線通信設(shè)備(SRD)。CC1101在各高校電子類實(shí)驗(yàn)室中得到了廣泛的應(yīng)用,在市場(chǎng)上也有良好的應(yīng)用前景。目前,從網(wǎng)絡(luò)資料及學(xué)術(shù)論文上來(lái)看,國(guó)內(nèi)對(duì)于CC1101的應(yīng)用有兩方面的不足:第一,CC1101在各類低端單片機(jī)有著廣泛應(yīng)用,但是在嵌入式處理器上的應(yīng)用卻相對(duì)較少;第二,在通信信號(hào)不穩(wěn)定的情況下,需要考慮到“面向連接”的通信模式,即需要保證通信質(zhì)量的可靠性。本文較為詳細(xì)地闡述了CC1101在ARM9處理器及嵌入式Linux系統(tǒng)下的開發(fā)過程,提出了一種簡(jiǎn)單可靠的主從無(wú)線通信協(xié)議模型。
在CC1101的通信過程中,因距離、障礙物等其他環(huán)境因素的影響,發(fā)送的數(shù)據(jù)并不一定能被確認(rèn)接收,即可能出現(xiàn)丟包現(xiàn)象。因此,有必要設(shè)計(jì)一個(gè)簡(jiǎn)單的通信協(xié)議以保證CC1101通信過程的可靠性,避免丟包現(xiàn)象的出現(xiàn)。
在通信協(xié)議模型的設(shè)計(jì)上,借鑒了TCP協(xié)議“面向連接”的通信機(jī)制,簡(jiǎn)單地說就是在每次發(fā)送之后都需要等待一個(gè)應(yīng)答,以保證本次發(fā)送數(shù)據(jù)的正確接收。
為了清晰地闡述“面向連接”的通信過程,將通信雙方區(qū)分為server端與client端。在每次通信過程中,發(fā)送方為server,接收方為client,其主要通信過程如下:
①在server端保存一全局變量seqno(sequence number),seqno的作用是標(biāo)識(shí)發(fā)送的數(shù)據(jù)報(bào)文在server端的編號(hào),在每次發(fā)送數(shù)據(jù)后seqno都要增加,同時(shí)區(qū)分報(bào)文為SEND 與ACK 兩種狀態(tài),SEND 標(biāo)識(shí)本報(bào)文為正常發(fā)送報(bào)文,ACK 標(biāo)識(shí)為應(yīng)答報(bào)文。
②server端發(fā)送數(shù)據(jù)給client時(shí),server端將要發(fā)送的數(shù)據(jù)主體與對(duì)應(yīng)的seqno組成一個(gè)數(shù)據(jù)報(bào)文,并標(biāo)識(shí)報(bào)文狀態(tài)為SEND,繼而調(diào)用CC1101發(fā)送接口進(jìn)行數(shù)據(jù)發(fā)送。
③server端在發(fā)送后,啟動(dòng)一定時(shí)器,等待由client端回應(yīng)的應(yīng)答報(bào)文。
若client端接收到server端發(fā)送的報(bào)文,則client端會(huì)發(fā)送相應(yīng)的應(yīng)答報(bào)文給server端,client端應(yīng)答報(bào)文中的seqno要等于從server端接收的seqno,并且報(bào)文狀態(tài)標(biāo)識(shí)為ACK。server端接收到應(yīng)答報(bào)文后比較收到的seqno與自身的seqno是否相等,若相等,則說明本次發(fā)送成功,否則說明本次發(fā)送失敗,進(jìn)行數(shù)據(jù)報(bào)文的重發(fā)。
若client端未接收到server端的報(bào)文,client端不會(huì)發(fā)送應(yīng)答報(bào)文給server端,server端在定時(shí)器超時(shí)前無(wú)法接收到應(yīng)答報(bào)文,則說明本次發(fā)送失敗,繼而進(jìn)行報(bào)文重發(fā),在超過重發(fā)次數(shù)后,通知server端數(shù)據(jù)不可達(dá)。
④client端的處理較為簡(jiǎn)單,在接收到server端發(fā)送的SEND報(bào)文后,檢測(cè)其中的seqno,將其提取出來(lái)并構(gòu)建ACK 報(bào)文,直接發(fā)送回server端。
圖1描述了server端面向連接發(fā)送的過程。
圖1 面向連接通信模型
在芯片的控制上,CC1101芯片通過SPI總線的方式與外部控制器通信,這種簡(jiǎn)單的串行通信方式使得CC1101可以和大部分的MCU 直接相連,即使在沒有SPI控制器的MCU 上也可以采取I/O 口模擬SPI的方式來(lái)通信。而且從網(wǎng)絡(luò)資料上看,大部分驅(qū)動(dòng)CC1101芯片的代碼也是采用通過I/O 口模擬SPI的方式,這種I/O 口模擬方式的優(yōu)點(diǎn)在于屏蔽了不同類型MCU 在SPI控制器設(shè)置上的不同,將驅(qū)動(dòng)代碼移植到各個(gè)MCU 時(shí),只需要按照I/O 口的連接方式修改代碼中SPI對(duì)應(yīng)的接口信號(hào)SCK、MOSI、MISO 和CSN。當(dāng)然其缺點(diǎn)也很明顯,SPI通信有一定的時(shí)序要求,在I/O 模擬SPI時(shí)序時(shí),不同MCU對(duì)應(yīng)的驅(qū)動(dòng)代碼在時(shí)序模擬這部分需要適配。
除了4線SPI總線對(duì)應(yīng)的SCK、MOSI、MISO 和CSN引腳外,CC1101 具有兩個(gè)專用的可配置引腳(GDO0 和GDO2),這些引腳可以用來(lái)對(duì)MCU 產(chǎn)生中斷。例如,當(dāng)設(shè)置IOCFG0.GDO0_CFG=0x06時(shí),接收/發(fā)送一個(gè)數(shù)據(jù)包,在RX和TX模式下GDO0引腳會(huì)分別產(chǎn)生下降沿電平信號(hào),可作為MCU 的外部中斷。
一個(gè)典型的CC1101與MCU連接的方式如圖2所示。
在嵌入式Linux系統(tǒng)的硬件平臺(tái)上,選擇的是三星公司的S3C2440/ARM9處理器,這款處理器在高校實(shí)驗(yàn)室有著廣泛的應(yīng)用;嵌入式Linux內(nèi)核版本采用的是穩(wěn)定的2.6版本。CC1101與S3C2440 的連接方式如圖3所示,本文采用的是S3C2440 的GPIO 模擬SPI時(shí)序的方法,CC1101的GDO0作為外部中斷引腳連接至S3C2440 的EINT15引腳。
圖2 CC1101與MCU連接典型電路
圖3 CC1101與S3C2440的連接
Linux下的設(shè)備可以分為字符設(shè)備、塊設(shè)備和網(wǎng)絡(luò)設(shè)備,在實(shí)際應(yīng)用中CC1101一般只需要提供發(fā)送與接收接口,并且可以按照字節(jié)流讀取,所以本文將CC1101 歸類為字符設(shè)備。
字符設(shè)備開發(fā)過程中最主要的數(shù)據(jù)結(jié)構(gòu)為fop(file_operation)結(jié)構(gòu),它包括了一系列文件操作接口。和CC1101字符設(shè)備開發(fā)相關(guān)的主要部分包括CC1101 的初始化、CC1101的發(fā)送/接收接口,以及CC1101各種狀態(tài)寄存器修改接口等。需要實(shí)現(xiàn)上述fop結(jié)構(gòu)中的接口包括:
①open:設(shè)置SCK、MOSI、CSN、GDO2對(duì)應(yīng)的GPIO為輸出方式,MISO 對(duì)應(yīng)GPIO 為輸入方式,GDO0對(duì)應(yīng)的引腳為外部中斷(EINT15)方式,完成通過GPIO 模擬SPI初始化CC1101的工作,申請(qǐng)外部中斷資源,由于采用了中斷方式,在CC1101接收到數(shù)據(jù)時(shí)觸發(fā)中斷,在中斷程序中進(jìn)行CC1101接收緩存數(shù)據(jù)的讀取,設(shè)置可讀取標(biāo)志位rcv_flag。
②write:CC1101的發(fā)送接口,用戶態(tài)應(yīng)用程序調(diào)用write系統(tǒng),調(diào)用發(fā)送數(shù)據(jù)。
③read:無(wú)阻塞地讀取CC1101 接收到的數(shù)據(jù),重置可讀取標(biāo)志位。
④poll:poll函數(shù)是為了配合用戶態(tài)的select系統(tǒng)調(diào)用,只有在上述可讀取標(biāo)志位被設(shè)置的情況下,返回POLLIN。
⑤ioctl:用于設(shè)置CC1101的其他狀態(tài),設(shè)置其內(nèi)部寄存器。
⑥r(nóng)elease:釋放中斷資源,關(guān)閉字符設(shè)備。
在上述CC1101內(nèi)核驅(qū)動(dòng)完成之后,即可以在用戶態(tài)程序中打開設(shè)備并使用它。為了實(shí)現(xiàn)第一部分介紹的面向連接通信過程cc1101_link_send,在每次發(fā)送數(shù)據(jù)之后,都要啟動(dòng)一個(gè)定時(shí)器,等待由對(duì)端發(fā)送而來(lái)的ACK 報(bào)文,具體在Linux用戶態(tài)程序中采用了select系統(tǒng)調(diào)用。此系統(tǒng)最終調(diào)用內(nèi)核態(tài)fop中的poll函數(shù),select函數(shù)原型為:
readfds 表示讀文件集。在timeout 時(shí)間段內(nèi),若readfds讀文件集沒有變化,則select函數(shù)超時(shí);readfds讀文件集有變化則表示CC1101收到數(shù)據(jù),此時(shí)再調(diào)用read系統(tǒng)函數(shù)讀取CC1101接收的數(shù)據(jù),比較seqno和報(bào)文狀態(tài)即可以完成上述的面向連接通信機(jī)制。
面向連接的發(fā)送接口cc1101_link_send部分代碼如下:
上述程序只是簡(jiǎn)單地實(shí)現(xiàn)了前述的面向連接通信機(jī)制,當(dāng)然,用戶可以參照現(xiàn)有的TCP/IP、ZigBee等成熟的通信協(xié)議,在應(yīng)用程序?qū)佣ㄖ坪?jiǎn)單實(shí)用的通信協(xié)議,定義與修改C1101通信的報(bào)文格式,如增加地址、命令字等,以完成其他更加豐富的功能。
將CC1101內(nèi)核驅(qū)動(dòng)編譯成module模塊加載至嵌入式Linux系統(tǒng)中,并運(yùn)行用戶態(tài)應(yīng)用程序,圖4(a)左側(cè)顯示了發(fā)送超時(shí)的情形,可見在發(fā)送超時(shí)后會(huì)繼續(xù)發(fā)送直至最大發(fā)送次數(shù),圖4(b)則顯示了正常的面向連接發(fā)送過程。經(jīng)驗(yàn)證,在面向連接的通信模型下CC1101可保證通信質(zhì)量。
圖4 用戶態(tài)應(yīng)用程序
為了解決CC1101通信質(zhì)量不穩(wěn)定的問題,提出了一種面向連接的通信模型。在嵌入式Linux系統(tǒng)下開發(fā)了CC1101的驅(qū)動(dòng),并基于上述的通信模型編寫了應(yīng)用程序,驗(yàn)證了驅(qū)動(dòng)及應(yīng)用程序的正確性。本文在一定程度上彌補(bǔ)了關(guān)于嵌入式Linux系統(tǒng)下應(yīng)用CC1101資料不豐富的不足,也為CC1101的無(wú)線通信協(xié)議開發(fā)提供參考。
[1]廖建尚.ARM9和Linux的DS18B20驅(qū)動(dòng)程序研究[J].單片機(jī)與嵌入式系統(tǒng)應(yīng)用,2013(4):53-56.
[2]DanielP,Bovet.Understanding the Linux Kernel[M].北京:中國(guó)電力出版社,2007.
[3]Jonathan Corbet.Linux Device Drivers[M].北京:中國(guó)電力出版社,2006.
[4]Texas Instruments.CC1101 Low-Cost Low-Power Sub-1GHz RF TransceiverDatasheet[EB/OL].[2013-08-05].http://www.alldatasheet.com/datasheet-pdf/pdf/191432/TI/CC1101.html.
[5]Neil Matthew,Richard Stones.Linux程序設(shè)計(jì)[M].北京:人民郵電出版社,2010.
[6]曹桂平.Linux內(nèi)核網(wǎng)絡(luò)棧源代碼情景分析[M].北京:人民郵電出版社,2010.