乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      CC3000驅(qū)動(dòng)移植中的幾個(gè)陷阱

       細(xì)寒 2014-04-12

      1. 文檔中的一個(gè)小錯(cuò)誤

      CC3000驅(qū)動(dòng)移植中的幾個(gè)大坑 - 月下獨(dú)酌 - The Bloom of Youth
      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)體定義如下:
      1. typedef struct _wlan_full_scan_results_args_t 
      2.     /* 
      3.         4 Bytes: number of networks found 
      4.         4 Bytes: The status of the scan: 0 - agged results, 1 - results valid, 2 - no results 
      5.         { 
      6.             1 bit isValid - is result valid or not 
      7.             7 bits rssi - RSSI value; 
      8.         } 
      9.         { 
      10.             2 bits: securityMode - security mode of the AP: 0 - Open, 1 - WEP, 2 WPA, 3 WPA2 
      11.             6 bits: SSID name length 
      12.         } 
      13.         2 bytes: the time at which the entry has entered into scans result table 
      14.         32 bytes: SSID name 
      15.         6 bytes: BSSID 
      16.     */ 
      17.     uint32_t ap_count; 
      18.     uint32_t ap_state; 
      19.     uint32_t ap_vaild    : 1; 
      20.     uint32_t ap_rssi     : 7; 
      21.     uint32_t ap_security : 2; 
      22.     uint32_t ap_ssidlen  : 6; 
      23.     uint16_t ap_time; 
      24.     char     ap_ssid[32]; 
      25.     uint8_t  ap_bssid[6]; 
      26.     uint8_t  reserved[2]; //for memory align 
      27. } wlan_scan_result; 
      另外,這個(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)如下
      1. void SpiPauseSpi(void) 
      2. //    if(IRQ_INT_CHANNEL >= 0 && IRQ_INT_CHANNEL <= 31) 
      3. //    { 
      4. //        //NVIC->ICER[0] = (1 << IRQ_INT_CHANNEL); 
      5. //    } 
      6. //    else if(IRQ_INT_CHANNEL >= 32 && IRQ_INT_CHANNEL <= 63) 
      7. //    { 
      8.     NVIC->ICER[1] = (1 << (IRQ_INT_CHANNEL - 32)); 
      9. //    } 
      10. //    else if(IRQ_INT_CHANNEL >= 64 && IRQ_INT_CHANNEL <= 67) 
      11. //    { 
      12. //        //NVIC->ICER[2] = (1 << (IRQ_INT_CHANNEL - 64)); 
      13. //    } 
      14. //    else 
      15. //    { 
      16. //        while(1); //Should not be here. Macro IRQ_INT_CHANNEL might be invalid. 
      17. //    } 
      18.  
      19. void SpiResumeSpi(void) 
      20. //    if(IRQ_INT_CHANNEL >= 0 && IRQ_INT_CHANNEL <= 31) 
      21. //    { 
      22. //        //NVIC->ISER[0] = (1 << IRQ_INT_CHANNEL); 
      23. //    } 
      24. //    else if(IRQ_INT_CHANNEL >= 32 && IRQ_INT_CHANNEL <= 63) 
      25. //    { 
      26.     NVIC->ISER[1] = (1 << (IRQ_INT_CHANNEL - 32)); 
      27. //    } 
      28. //    else if(IRQ_INT_CHANNEL >= 64 && IRQ_INT_CHANNEL <= 67) 
      29. //    { 
      30. //        //NVIC->ISER[2] = (1 << (IRQ_INT_CHANNEL - 64)); 
      31. //    } 
      32. //    else 
      33. //    { 
      34. //        while(1); //Should not be here. Macro IRQ_INT_CHANNEL might be invalid. 
      35. //    } 
      另外一組的實(shí)現(xiàn)是
      1. void WlanInterruptEnable() 
      2.     EXTI_ClearITPendingBit(IRQ_INT_LINE); 
      3.     EXTI_InitTypeDef exti; 
      4.     exti.EXTI_Line = IRQ_INT_LINE; 
      5.     exti.EXTI_Mode = EXTI_Mode_Interrupt; 
      6.     exti.EXTI_Trigger = EXTI_Trigger_Falling; 
      7.     exti.EXTI_LineCmd = ENABLE; 
      8.     EXTI_Init(&exti); 
      9.  
      10. void WlanInterruptDisable() 
      11.     EXTI_ClearITPendingBit(IRQ_INT_LINE); 
      12.     EXTI_InitTypeDef exti; 
      13.     exti.EXTI_Line = IRQ_INT_LINE; 
      14.     exti.EXTI_Mode = EXTI_Mode_Interrupt; 
      15.     exti.EXTI_Trigger = EXTI_Trigger_Falling; 
      16.     exti.EXTI_LineCmd = DISABLE; 
      17.     EXTI_Init(&exti); 
      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. 供電
      CC3000驅(qū)動(dòng)移植中的幾個(gè)大坑 - 月下獨(dú)酌 - The Bloom of Youth
      這 個(gè)是一個(gè)硬件問(wèn)題,一個(gè)不應(yīng)該犯的錯(cuò)誤。目前大家用的最多的CC3000模塊還是Jorjin的WG1300,而Jorjin的文檔中并未給出該模塊工作 時(shí)所需的電流。在一些追求體積最小化的應(yīng)用中,大家也普遍使用了SOT23-5封裝的小型LDO,這類(lèi)LDO的電流通常只有100mA左右。一個(gè)單片機(jī)才 幾十毫安的電流,一個(gè)WiFi又能大到哪里去呢?
      看 看德州儀器官方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

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多