<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 在mini2440上面搞定CC2500物理層驅(qū)動

          在mini2440上面搞定CC2500物理層驅(qū)動

          作者: 時間:2016-11-19 來源:網(wǎng)絡(luò) 收藏
          1. 寫在前面

          最近基本搞定了CC2500在linux下面的驅(qū)動,在這個過程中遇到了好多問題,特此總結(jié)出來和大家分享。但是需要注意的事情是:
          第一,本文不負(fù)責(zé)程序的具體講解,諸如每一行程序都講什么:這個在程序的里面有注釋。本篇文章更側(cè)重于從整體結(jié)構(gòu)上讓大家對于linux下的CC2500DE驅(qū)動有一個整體的了解,如果到時候需要深入研究的時候,再來看具體的代碼;
          第二,很多師弟師妹沒有習(xí)慣在linux下編程,或曰,在操作系統(tǒng)下面寫程序;并且,對于本專業(yè)的東西理解并不扎實。但是,文章中不可能就每一個涉及到的概念都大加講解。因此,這篇文章還是需要有一些基礎(chǔ)才能來閱讀的,如果遇到什么不明白的地方,請及時來問我,或者跟帖,或者自己查資料。畢竟,這個驅(qū)動花費了我半個多月的時間,其中遇到的問題,不可能在一篇文章中就講得清清楚楚。


          1. 背景知識

          如果大家看過實驗室的WSN方面的程序,可能會被其中的架構(gòu)搞得天昏地暗。這里,簡單的幫助大家把實驗室的WSN的軟件、硬件方面捋一捋。
          說到軟件,就不能不說硬件。我們的節(jié)點由兩部分組成,一個是單片機(jī),一個是CC2500的射頻模塊。射頻模塊通過SPI接口和單片機(jī)進(jìn)行通信。除了SPI模塊用到的4條線,實際上CC2500還需要告訴單片機(jī)“我接收到一個數(shù)據(jù)”,這個地方CC2500可以通過配置GDO來實現(xiàn)。我們這里采用的CC2500的GDO0作為單片機(jī)的一個外部中斷,當(dāng)接收到數(shù)據(jù)的時候,GDO0就會變?yōu)榈碗娖?,然后觸發(fā)CC2500的中斷,從而接收數(shù)據(jù)。
          那么,CC2500究竟是如何來進(jìn)行數(shù)據(jù)發(fā)送、接收的呢?其實很簡單。如果大家稍微用過一點可以控制的芯片就會知道,很多芯片內(nèi)部都有寄存器,CC2500之所以能夠完成發(fā)送、接收的功能,就是通過配置寄存器來完成的。比較重要的配置有信道、波特率、信號強(qiáng)度等等,另外,CC2500還有64bytes的RXFIFO和64bytes的TXFIFO,他們的作用就是用來發(fā)送和接收。當(dāng)配置CC2500結(jié)束之后,如果用來發(fā)送,那么就把數(shù)據(jù)放在TXFIFO里面,然后把CC2500的狀態(tài)變?yōu)榘l(fā)射狀態(tài),數(shù)據(jù)就自動發(fā)送出去了。同樣的道理,當(dāng)RXFIFO里面接收到了數(shù)據(jù)之后,CC2500就會如前所說,發(fā)出一個中斷,通知單片機(jī)來讀取數(shù)據(jù)。
          單片機(jī)通過SPI接口讀出了CC2500中的數(shù)據(jù),就需要進(jìn)行簡單的處理了。我們的節(jié)點是遵循802.15.4協(xié)議的,如果有興趣,大家可以去看一看這個協(xié)議的內(nèi)容。對于我們來說,比較重要的就是幀的結(jié)構(gòu)。下面這個是物理層幀的結(jié)構(gòu):
          字節(jié):4
          1
          1
          可變
          先導(dǎo)碼
          幀定界符

          幀長度(7位)

          保留位(1位)
          負(fù)載內(nèi)容

          同步頭

          PHY頭

          PHY負(fù)載

          簡單的講,因為是無線通信,沒有一個時鐘的存在,因此本質(zhì)上所有的無線通信都是一個異步的通信。那么,就需要發(fā)送和接收的雙方首先對數(shù)據(jù)進(jìn)行同步——這個就是同步頭的作用。隨后的是PHY的頭,很簡單,就是一個長度。換句話說,每個幀不能夠超過2的8次方減一個數(shù)據(jù)(127個)。隨后就是負(fù)載的內(nèi)容了,簡單吧?另外,由于CC2500是一個802.15.4兼容的芯片,這一部分內(nèi)容都已經(jīng)固化在芯片里面了,像同步頭這種東西,都是芯片幫我們完成(當(dāng)然也可以自行配置)。我們只需要把寫入的數(shù)據(jù)大小和數(shù)據(jù)內(nèi)容寫入即可。
          雖然簡單,但是還有一個問題:每次從CC2500中讀取了數(shù)據(jù),存放到哪里呢?有的同學(xué)可能想的比較簡單,比如建立一個大數(shù)組,收到多少個數(shù),放在里面就行了。但是,這樣就會遇到問題:如果收到了兩個包,上層來不及處理怎么辦?建立兩個大數(shù)組?更多的包呢?當(dāng)然,我們可以通過建立好多個數(shù)組來解決這個問題。但是,從效率上講,這個是非常笨的一個辦法。因此,我們建立了一個環(huán)形緩沖區(qū)PHY_RX_BUFFER,來解決這個問題。環(huán)形緩沖區(qū)的具體原理不過多涉及,可以自行百度。
          另外一個問題就是,如果我們從CC2500中接收到了數(shù)據(jù),那么應(yīng)該怎樣才能告訴上層來進(jìn)行處理呢?這里就要用到操作系統(tǒng)的消息機(jī)制了。如果確定接收到了一個數(shù)據(jù),那么就給上層發(fā)送一個消息,來通知上層。上層接收到這個消息,就會知道接收到了數(shù)據(jù)。
          當(dāng)從CC2500讀取到了數(shù)據(jù),因為物理層沒有什么東西,我們就直接通知MAC層來處理數(shù)據(jù)。MAC層的結(jié)構(gòu)如下:
          字節(jié):2
          1
          0/2
          0/2/8
          0/2
          0/2/8
          可變
          2
          幀控制域
          序列號
          目的PAN標(biāo)示符
          目的地址
          源PAN標(biāo)示符
          源地址
          幀負(fù)載
          FCS
          地址域
          MAC幀頭
          MAC負(fù)載
          MFR

          具體內(nèi)容可以參見老師的《無線傳感器網(wǎng)絡(luò)技術(shù)與工程應(yīng)用》這本書,這里不再詳細(xì)的講,大概內(nèi)容就是,會有一系列的幀頭,然后是幀數(shù)據(jù),最后有校驗。而我們最關(guān)心的就是幀的內(nèi)容。但是,幀頭也比較麻煩,因此我們需要首先對幀頭進(jìn)行處理,把數(shù)據(jù)給“剝離”出來,這也是基本上所有的協(xié)議棧解析協(xié)議的方法。


          1. 硬件結(jié)構(gòu)

          硬件上,我們采用的是mini2440開發(fā)板,和實驗室的CC2500節(jié)點(把單片機(jī)焊掉,然后把mini2440的相應(yīng)管腳接到上面)。


          Mini2440方面,我們用的是CON8這個引腳,具體連線如下:
          EINT8對應(yīng)S3C2440的GPG0引腳,連接到了CC2500的GDO2
          EINT11對應(yīng)S3C2440的GPG3引腳,連接到了CC2500的CSN
          EINT13對應(yīng)S3C2440的GPG5引腳,連接到了CC2500的SO
          EINT14對應(yīng)S3C2440的GPG6引腳,連接到了CC2500的SI
          EINT15對應(yīng)S3C2440的GPG7引腳,連接到了CC2500的CLK
          EINT19對應(yīng)S3C2440的GPG11引腳,連接到了CC2500的GDO0
          除此之外,還有3.3V電源和GND


          1. Linux下驅(qū)動編寫

          為什么要用驅(qū)動呢?簡單的說,就是為了在linux下完成用戶空間和內(nèi)核空間的交互。本質(zhì)上,驅(qū)動就是完成了兩件事情:第一,初始化SPI接口,并且通過SPI和CC2500完成通信。第二,完成讀寫函數(shù),read和write,通過讀寫函數(shù)的接口來對CC2500進(jìn)行操作。
          附件里面有幾個文件,這里簡單講解一下:
          Common.h主要是包含了很多l(xiāng)inux的頭文件,并且對一些數(shù)據(jù)類型做了定義
          CC2500.h里面主要是對CC2500的寄存器做了一些定義,沒啥東西
          Driver.h主要是定義了很多和CC2500進(jìn)行通信,并且利用CC2500進(jìn)行發(fā)送和接收的內(nèi)容
          Phy.h主要是完成了一些諸如信道設(shè)定、通信速率等功能,并且把CC2500里的數(shù)據(jù)讀到環(huán)形緩沖區(qū)里面
          CC2500.c這個就是完成設(shè)備注冊、讀寫函數(shù)、iocontrol等功能
          這樣有了一個整體的把握之后,不用看很多代碼,學(xué)會使用就好。


          1. 驅(qū)動接口使用

          那么,這個驅(qū)動怎樣使用呢?主要是通過read/write/ioctl三個接口來實現(xiàn)的。
          在應(yīng)用程序中read/dev/CC2500這個文件,如果有數(shù)據(jù),會返回相應(yīng)的數(shù)據(jù)。其中,返回的數(shù)據(jù)中第一個字節(jié)為數(shù)據(jù)的長度(不包括該字節(jié)本身),后面為相應(yīng)的數(shù)據(jù)。
          如果是寫文件的話,只需要向/dev/CC2500中寫入相應(yīng)的數(shù)據(jù)即可。寫入的時候需要注意,第一個字節(jié)同樣為數(shù)據(jù)長度(不包括該字節(jié)本身),后面跟相應(yīng)的數(shù)據(jù)。當(dāng)寫入的字節(jié)合適的時候,驅(qū)動會自動執(zhí)行發(fā)送函數(shù)。如果寫入的字節(jié)數(shù)量和寫入的數(shù)據(jù)第一個字節(jié)不匹配的時候,會返回錯誤。
          ioctl主要有這樣幾種命令:


          CC2500_IOC_PHY_DETECT_STATUS
          表示將CC2500的狀態(tài)變?yōu)镽X
          CC2500_IOC_PHY_GET_BAUDRATE
          讀取CC2500的波特率,返回的是1,2,3,4,分別是2.4k,10k,250k,500k的波特率
          CC2500_IOC_PHY_SET_BAUDRATE
          設(shè)定CC2500的波特率,后面的參數(shù)是1,2,3,4,分別是2.4k,10k,250k,500k的波特率
          CC2500_IOC_PHY_GET_TXPOWER
          獲取發(fā)送功率,返回的是在發(fā)送功率表{0x00, 0x50, 0x44, 0xC0, 0x84, 0x81, 0x46, 0x93, 0x55, 0x8D, 0xC6,0x97, 0x6E, 0x7F, 0xA9, 0xBB, 0xFE, 0xFF }中的數(shù)組下標(biāo)
          CC2500_IOC_PHY_SET_TXPOWER
          設(shè)定發(fā)送功率,參數(shù)的是在發(fā)送功率表{0x00, 0x50, 0x44, 0xC0, 0x84, 0x81, 0x46, 0x93, 0x55, 0x8D, 0xC6,0x97, 0x6E, 0x7F, 0xA9, 0xBB, 0xFE, 0xFF }中的數(shù)組下標(biāo)
          CC2500_IOC_PHY_GET_CHANNEL
          獲取頻段,參數(shù)是頻段表{0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0,0xB0, 0xC0, 0xD0, 0xE0, 0xF0 }中的數(shù)組下標(biāo)
          CC2500_IOC_PHY_SET_CHANNEL
          設(shè)定頻段,參數(shù)是頻段表{0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0,0xB0, 0xC0, 0xD0, 0xE0, 0xF0 }中的數(shù)組下標(biāo)


          1. 應(yīng)用層程序編寫

          這里的應(yīng)用層主要是將mac層實現(xiàn)了。其實,mac層的作用也很簡單,主要是對要發(fā)送的包進(jìn)行封裝,接收回來的包進(jìn)行包的解析。這一部分的內(nèi)容還不全面,僅僅是將原來的程序移植過來,還有很多需要改動的地方,有待補充。因此,這里只是提供源代碼,具體的說明請參見程序內(nèi)部


          1. 如何配置內(nèi)核文件

          1首先修改/opt/FriendlyARM/mini2440/linux-2.6.32.2/drivers/char/Kconfig
          加入如下幾句話:
          config CC2500_DRIVER


          tristate "CC2500 driverfor FriendlyARM Mini2440 development boards"


          depends on MACH_MINI2440


          default m if MACH_MINI2440


          help


          this is CC2500 driver forFriendlyARM Mini2440 development boards




          2修改Makefile,讓CC2500的驅(qū)動可以編譯。
          加入如下幾句話:


          obj-$(CONFIG_CC2500_DRIVER) +=CC2500inuse.o


          CC2500inuse-objs :=./CC2500.in_use/cc2500.o ./CC2500.in_use/phy.o./CC2500.in_use/driver.o


          其中,CONFIG_CC2500_DRIVER需要和Kconfig中的configCC2500_DRIVER
          保持一致。
          CC2500inuse-objs這句話,意思是CC2500inuse.ko是由哪幾個文件組成的。這樣就實現(xiàn)了模塊化的處理。
          需要注意的是,CC2500inuse-objs和冒號之間需要有個空格,不然會出錯誤。這個地方我搞了好久。
          具體的Makefile的格式也可以參考這兩篇文章:
          http://blog.csdn.net/tommy_wxie/article/details/7282463
          http://hi.baidu.com/wjq_qust/blog/item/97ddbdfdfb2e541309244d30.html


          1. 調(diào)試過程中的一些問題

          CC2500驅(qū)動調(diào)試的過程中,遇到的一些問題
          第一,在調(diào)試的過程中,發(fā)現(xiàn)板子和2500沒有辦法進(jìn)行通信。一開始懷疑是2500芯片的問題,后來確認(rèn)2500芯片沒有問題之后,用示波器看了一下波形,發(fā)現(xiàn)SPI引腳上沒有輸出。進(jìn)而發(fā)現(xiàn),對SPI寄存器進(jìn)行讀寫的時候,無論寫入是什么,讀出的都是0。后來發(fā)現(xiàn),原來是PCLK(也就是SPI模塊的時鐘)沒有使能,囧。設(shè)置了寄存器之后,問題就解決了。
          第二,CC2500驅(qū)動沒有辦法自動在/dev/目錄下面創(chuàng)建節(jié)點。這個問題可以參考下面幾篇文章:
          http://blog.csdn.net/cjok376240497/article/details/6848536
          整體來說,創(chuàng)建節(jié)點的工作是這樣的:
          我們通過udev來創(chuàng)建節(jié)點。但是,udev是應(yīng)用層的東東,不要試圖在內(nèi)核的配置選項里找到它;加入對udev的支持很簡單,只要在驅(qū)動初始化的代碼里調(diào)用class_create為該設(shè)備創(chuàng)建一個class,再為每個設(shè)備調(diào)用class_device_create創(chuàng)建對應(yīng)的設(shè)備。
          換句話說,首先要為每一個設(shè)備創(chuàng)建一個類。然后用這個類去申請一個設(shè)備節(jié)點。
          第三,在調(diào)試的過程中,發(fā)現(xiàn)只要一啟動CC2500,那么液晶屏就熄滅了。調(diào)試了半天也沒有找到原因。
          最后發(fā)現(xiàn),在配置S3C2440中GPGCON寄存器的時候,對寄存器直接進(jìn)行了覆蓋性的修改;而該寄存器還管理著LCD的電源...于是,對寄存器進(jìn)行覆蓋性修改的時候,悲劇了...
          總結(jié)一下吧,在linux下2500驅(qū)動編寫的過程中,如果涉及到寄存器級別的操作,和單片機(jī)一樣,必須十分注意各個模塊之間的關(guān)系,以及相關(guān)模塊的寄存器配置,不要認(rèn)為linux會全部給你配好!


          關(guān)鍵詞: mini2440CC2500物理層驅(qū)

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();