1. 文檔中的一個(gè)小錯(cuò)誤 ![]() wlan_ioctl_get_scan_results 函數(shù)用于返回WLAN掃描的結(jié)果,每調(diào)用一次返回一個(gè)結(jié)果。返回的數(shù)據(jù)結(jié)構(gòu)在文檔中給出,但是這里文檔寫(xiě)錯(cuò)了。。。Result entry前的56bytes應(yīng)該是42bytes,而每次的結(jié)果總有有4+4+42=50(bytes)。把下面的結(jié)果加起來(lái),也會(huì)發(fā)現(xiàn)各項(xiàng)的和是42 而不是56. 這本來(lái)只是手冊(cè)上的一個(gè)筆誤,但在編程時(shí),大家通常會(huì)使用一個(gè)結(jié)構(gòu)體來(lái)接收返回的數(shù)據(jù),如果這個(gè)字節(jié)數(shù)不對(duì)的話(huà),就會(huì)影響內(nèi)存對(duì)齊,從而導(dǎo)致返回的結(jié)果錯(cuò)誤。這里,我使用的結(jié)構(gòu)體定義如下:
另外,這個(gè)函數(shù)讀到最后一條結(jié)果時(shí),再讀會(huì)返回一個(gè)長(zhǎng)度為0的結(jié)果,即前四個(gè)字節(jié)(number of networks found)為零,然后再讀才會(huì)讀出下一次掃描的結(jié)果。這一點(diǎn)手冊(cè)上并沒(méi)有指出,是我們?cè)诰幊虒?shí)踐中自己發(fā)現(xiàn)的。
2. SpiPause - SpiResume與WlanInterruptDisable - WlanInterruptEnable的實(shí)現(xiàn)
如 果前面一條是一個(gè)小坑的話(huà),這一條絕對(duì)是一個(gè)大坑。目前為止,我見(jiàn)過(guò)的CC3000的驅(qū)動(dòng)實(shí)現(xiàn)中,不論是開(kāi)源的、產(chǎn)品正在開(kāi)發(fā)而尚未開(kāi)源的實(shí)現(xiàn),除了官方 的例程以外,還沒(méi)有人將這兩組函數(shù)寫(xiě)對(duì)。甚至有人能通過(guò)降低SPI速率、修改IO中斷方式等等辦法,使得整個(gè)程序得以正常運(yùn)行,將錯(cuò)誤帶到了產(chǎn)品中。只要 有人說(shuō):“我的CC3000驅(qū)動(dòng)有點(diǎn)問(wèn)題,調(diào)了很久都不行。。?!敝?lèi)的話(huà),不用等他說(shuō)完,就可以猜想他是把這兩組函數(shù)寫(xiě)錯(cuò)了。
這兩組函數(shù)非常容易錯(cuò),錯(cuò)了又非常難以發(fā)現(xiàn)。這兩組函數(shù)的實(shí)現(xiàn)已經(jīng)成為了CC3000驅(qū)動(dòng)移植的主要障礙。其主要原因如下:
(1)是官方的Porting Guide沒(méi)有明確指出這兩組函數(shù)的區(qū)別。很多人則想當(dāng)然地認(rèn)為這兩組函數(shù)是一樣的。甚至是一組中調(diào)用另一組。再看官方的實(shí)現(xiàn),又有點(diǎn)不知所云,所以就忽略了這個(gè)問(wèn)題。
(2) 忽略這個(gè)問(wèn)題后,CC3000模塊可以正常初始化,還可以正常掃描WiFi熱點(diǎn),有人還能正常進(jìn)行Smart config,甚至有人還能正常打開(kāi)socket并使用UDP協(xié)議發(fā)送數(shù)據(jù)!開(kāi)發(fā)者根據(jù)CC3000驅(qū)動(dòng)自下而上分層的架構(gòu)來(lái)看,看到SPI已經(jīng)可以進(jìn)行 正常通信,從而直接在心理上排除了SPI驅(qū)動(dòng)實(shí)現(xiàn)有誤的可能性,錯(cuò)誤查來(lái)查去還是在原地兜圈子。
(3)由于這兩組函數(shù)實(shí)現(xiàn)有誤導(dǎo)致的錯(cuò)誤幾乎成了一個(gè)人品問(wèn)題,在不同速度MCU上的錯(cuò)誤實(shí)現(xiàn)會(huì)導(dǎo)致不同的錯(cuò)誤現(xiàn)象,以至于大家的描述不統(tǒng)一,很難從現(xiàn)象判斷到底是哪兒錯(cuò)了,即使在網(wǎng)上根據(jù)錯(cuò)誤現(xiàn)象搜索或者發(fā)帖求助,也很難得到有針對(duì)性的答案。
為什么這兩組函數(shù)寫(xiě)錯(cuò)了,會(huì)有這么神奇的問(wèn)題呢?答案就是,這里的錯(cuò)誤會(huì)導(dǎo)致程序的“競(jìng)態(tài)問(wèn)題”,類(lèi)似于數(shù)字電路基礎(chǔ)中的“競(jìng)爭(zhēng)冒險(xiǎn)”。SPI速率、AP的品質(zhì)和信號(hào)強(qiáng)度、IO口翻轉(zhuǎn)速度、延時(shí)的誤差等無(wú)關(guān)緊要的問(wèn)題,都可能讓競(jìng)態(tài)問(wèn)題出現(xiàn)不同的現(xiàn)象。因此,出現(xiàn)的錯(cuò)誤現(xiàn)象千奇百怪,貌似跟人品有關(guān)就不難解釋了。說(shuō)了這么多,下面就來(lái)解釋一下這兩組函數(shù)到底有什么區(qū)別:
WlanInterruptDisable的作用是關(guān)閉IO口的外部中斷,也就是IRQ的下降沿中斷。關(guān)閉以后,IRQ下降沿的中斷將被丟棄,在調(diào)用WlanInterruptEnable時(shí),會(huì)重新使能中斷,之后發(fā)生在該IO上的外部中斷又再次可以響應(yīng)。而中斷被禁用期間,發(fā)生的中斷都被丟棄,永遠(yuǎn)不再響應(yīng)。這個(gè)函數(shù)一般人都寫(xiě)對(duì)了。
SpiPauseSpi函數(shù)是暫時(shí)掛起IO口外部中斷,也就是IRQ下降沿中斷,如果在SpiPauseSpi調(diào)用之后,IRQ線(xiàn)上再有下降沿,該中斷將一直保持Pending狀態(tài),暫時(shí)不調(diào)用中斷服務(wù)程序,該中斷必須在調(diào)用SpiResumeSpi被重新響應(yīng),而不能被丟棄。這里,很多很多很多人,都,寫(xiě)錯(cuò)了。。。
這種中斷的響應(yīng)方式比較特殊,像STM32就沒(méi)有在標(biāo)準(zhǔn)驅(qū)動(dòng)庫(kù)中實(shí)現(xiàn)相應(yīng)的API,而必須通過(guò)操作寄存器的方式來(lái)手工實(shí)現(xiàn)。相應(yīng)寄存器的定義,既不在芯 片Datasheet里,也不在那份大家熟知的STM32F1系列Reference Manual(RM0008)里,而是在很多STM32開(kāi)發(fā)者都沒(méi)有聽(tīng)說(shuō)過(guò)的一份文檔PM0056——STM32F10xxx/20xxx/21xxx/L1xxxx Cortex-M3 programming manual里。有很多MCU,甚至包括TI的MSP430,在硬件上根本就不支持這種響應(yīng)方式,因此只能用一些猥瑣的方法來(lái)實(shí)現(xiàn)。MSP430該函數(shù)的代碼居然是向一個(gè)配置為輸入的IO口寫(xiě)數(shù)據(jù),足以讓不熟悉MSP430的開(kāi)發(fā)者撓頭了。
STM32F103上的實(shí)現(xiàn)如下
另外一組的實(shí)現(xiàn)是
3. TI提供的CC3000 Host Driver假設(shè)char類(lèi)型是無(wú)符號(hào)的
這個(gè)問(wèn)題可能很多人都不會(huì)遇到,因?yàn)樵?a href="http://www./a/index_em.html" target="_blank">嵌入式開(kāi)發(fā)中char通常都是無(wú)符號(hào)的,基本所有的用于嵌入式平臺(tái)的編譯器默認(rèn)情況下都會(huì)這樣設(shè)定。而我則比較習(xí)慣PC上有符號(hào)的char,所以我手賤給GCC加了一個(gè)編譯參數(shù)-fsigned-char......
TI 的Host Driver就比較扯淡,它假設(shè)char是無(wú)符號(hào)的,并且在char有符號(hào)時(shí)就會(huì)因符號(hào)位在強(qiáng)制轉(zhuǎn)換中的行為不同而出錯(cuò)。這個(gè)問(wèn)題不容易排查,因?yàn)樾枰?蹤到TI實(shí)現(xiàn)的Host Driver里,而大家通常都會(huì)假設(shè)這個(gè)實(shí)現(xiàn)是沒(méi)錯(cuò)的,能跟進(jìn)去就是一種勇氣了……我當(dāng)時(shí)遇到這個(gè)問(wèn)題時(shí),不知道是哪兒的錯(cuò)誤,就在很多回調(diào)函數(shù)中添加了 串口打印的語(yǔ)句,通過(guò)串口輸出,觀察各個(gè)函數(shù)被調(diào)用的情況,結(jié)合現(xiàn)象,再加以大膽的猜想,才解決了這個(gè)問(wèn)題。
4. 供電
![]() 看 看德州儀器官方WiFi模塊(TI的WiFi模塊封裝尺寸和引腳定義與WG1300完全相同,本人咨詢(xún)Jorjin總代理后得知TI的官方模塊正是由 Jorjin設(shè)計(jì)并制造的,與WG1300相比在硬件上也是完全一樣的,只是外殼上的字不同而已) 的文檔后,不禁大吃一驚!發(fā)送電流峰值275mA,接收峰值103mA,合起來(lái)有接近400mA的峰值電流!正是因?yàn)槿绱?,?20mA的LDO被瞬間秒 殺,電壓從3.3V拉到了2.6V……我居然還不知道!因?yàn)镾TM32可以在2.6V下正常工作,我的還是在各種加斷點(diǎn)、各種單步跟蹤,完全沒(méi)有意識(shí)到模 塊已經(jīng)因電壓過(guò)低死機(jī)了。。??戳艘幌耂parkcore的電路圖,發(fā)現(xiàn)它用的LDO型號(hào)是MIC5219,一個(gè)SOT23-5封裝,500mA的 LDO,哈哈~
另外還有一個(gè)不算是坑,或者說(shuō)只是一個(gè)小坑~就是security.h文件最后少了一段代碼,在用C++編譯時(shí)可能導(dǎo)致編譯出錯(cuò),并且把錯(cuò)誤報(bào)到別的文件里,讓人很困惑。。。缺少的代碼如下,大家一看就懂了~
#ifdef __cplusplus
}
#endif
|
|
來(lái)自: 細(xì)寒 > 《待分類(lèi)1》