https://blog.csdn.net/dearsq/article/details/53318887
[Android6.0][RK3399] SDIO 介面 Wifi 驅動流程分析 (AP6354)
Platform: RockChip
OS: Android 6.0
Kernel: 4.4
WiFi/BT/FM 模組: AP6354
前面的基本概念搜羅於網路;
後面的驅動流程分析是根據 RockChip 3399 的 Kernel 部分來進行分析的。
本博客唯一地址:http://blog.csdn.net/dearsq/article/details/53318887
歡迎轉載,轉載請注明作者 Younix~ 謝謝~
wifi 英文全稱是 WIreless-FIdelity,翻譯成中文就是無線保真,英文簡稱WiFi。
wlan 英文全名:Wireless Local Area Networks, 無線區域網路。
wifi 是實現 wlan 的一種技術。
AP模式: Access Point,提供無線接入服務,允許其它無線設備接入,提供資料訪問,一般的無線路由/橋接器工作在該模式下。AP和AP之間允許相互連接。
Sta模式: Station, 類似於無線終端,sta本身並不接受無線的接入,它可以連接到AP,一般無線網卡即工作在該模式。
STA(工作站)啟動初始化、開始正式使用AP傳送資料幀前,要經過三個階段才能夠接入(802.11MAC層負責用戶端與AP之間的通訊,功能包括掃描、接入、認證、加密、漫遊和同步等功能):
1)掃描階段(SCAN)
2)認證階段 (Authentication)
3)關聯(Association)
更詳細的 wifi 相關介紹可以參考這篇文章 WiFi基礎知識解析
後面介紹 Wifi 的介面 SDIO 的基本概念。
SD (Secure Digital) 與 MMC (Multimedia Card)
MMC 是較早的一種記憶卡標準,目前已經被 SD 標準取代。
SD 是一種 flash memory card 的標準,也就是一般常見的 SD 記憶卡。
SDIO 就是 SD 的 I/O 介面的意思。
更具體的說,SD 本來是記憶卡的標準,但是現在也可以把 SD 拿來插上一些週邊介面使用,這樣的技術便是 SDIO。
SDIO 通過 SD 的 I/O 管腳來連接外部的週邊 device 並傳輸資料。這些週邊設備,我們稱為 SDIO 卡,常見的有:
- Wi-Fi card(無線網路卡)
- CMOS sensor card(照相模組)
- GPS card
- GSM/GPRS modem card
- Bluetooth card
- Radio/TV card
SD卡使用的是SD卡協定,而SDIO卡使用的是SDIO協定!
協定不一樣,初始化/讀寫方式也不一樣!
SDIO-Wifi 模組是基於 SDIO 介面的符合 wifi 無線網路標準的嵌入式模組,內置無線網路通訊協定IEEE802.11協定棧以及TCP/IP協定棧,能夠實現用戶主平臺資料通過SDIO口到無線網路之間的轉換。
SDIO 具有傳輸資料快,相容SD、MMC介面等特點。
對於SDIO介面的wifi,首先,它是一個sdio的卡的設備,然後具備了wifi的功能。
所以,註冊的時候還是先以sdio的卡的設備去註冊的。然後檢測到卡之後就要驅動他的wifi功能。
SDIO匯流排 和 USB匯流排 類似,SDIO也有兩端,其中一端是HOST端,另一端是device端。所有的通信都是由HOST端 發送 命令 開始的,Device端只要能解析命令,就可以相互通信。
CLK信號:HOST給DEVICE的 時鐘信號,每個時鐘週期傳輸一個命令。
CMD信號:雙向 的信號,用於傳送 命令 和 反應。
DAT0-DAT3 信號:四條用於傳送的資料線。
VDD信號:電源信號。
VSS1,VSS2:電源地信號。
SDIO匯流排上都是HOST端發起請求,然後DEVICE端回應請求。
SDIO 命令由6個位元組組成。
a – Command:用於開始傳輸的命令,是由HOST端發往DEVICE端的。其中命令是通過CMD信號線傳送的。
b – Response:回應是DEVICE返回的HOST的命令,作為Command的回應。也是通過CMD線傳送的。
c – Data:資料是雙向的傳送的。可以設置為1線模式,也可以設置為4線模式。資料是通過DAT0-DAT3信號線傳輸的。
SDIO的每次操作都是由HOST在CMD線上發起一個CMD,對於有的CMD,DEVICE需要返回Response,有的則不需要。
對於讀命令,首先HOST會向DEVICE發送命令,緊接著DEVICE會返回一個握手信號,此時,當HOST收到回應的握手信號後,會將資料放在4位元的資料線上,在傳送資料的同時會跟隨著CRC校驗碼。當整個讀傳送完畢後,HOST會再次發送一個命令,通知DEVICE操作完畢,DEVICE同時會返回一個響應。
對於寫命令,首先HOST會向DEVICE發送命令,緊接著DEVICE會返回一個握手信號,此時,當HOST收到回應的握手信號後,會將資料放在4位元的資料線上,在傳送資料的同時會跟隨著CRC校驗碼。當整個寫傳送完畢後,HOST會再次發送一個命令,通知DEVICE操作完畢,DEVICE同時會返回一個響應。
對於 Wifi 模組的 Android 上層的分析,這篇文章講的非常不錯:
http://blog.csdn.net/ylyuanlu/article/details/7711433
這篇文章將下圖藍色的和綠色的部分講的非常詳細。
我這個板子上所採用的 WiFi 模組是 AP6354, 它是一個 Wifi / BT4.0 / FM 三合一模組。介面是 SDIO。
本文主要分析 Kernel Driver 部分。所以先從 SDIO 介面的驅動來切入。
SDIO 介面的 wifi,首先,它是一個 sdio 卡 設備,然後具備了 wifi 的功能,所以 SDIO 介面的 WiFi 驅動就是在 wifi 驅動 外面套上了一個 SDIO 驅動 的外殼。
SDIO 驅動部分代碼結構如下
drivers/mmc 下有 mmc卡、sd卡、sdio 卡驅動。
SDIO驅動仍然符合設備驅動的分層與分離思想。
設備驅動層(wifi 設備):
|
核心層(向上向下提供介面)
|
主機驅動層(實現 SDIO 驅動)
我們主要關心 core 目錄(CORE 層),其中是媒體卡的通用代碼。包括 core.c host.c stdio.c。
CORE 層完成了
1. 不同協定和規範的實現
2. 為 HOST 層的驅動提供了介面函數
3. 完成了 SDIO 匯流排註冊
4. 對應 ops 操作
5. 以及支持 mmc 的代碼
host 目錄(HOST 層)是根據不通平臺而編寫的 host 驅動。
rockchip_wifi_init_module_rkwifi //創建了一個內核執行緒 wifi_init_thread
—wifi_init_thread //->
——dhd_module_init
———dhd_wifi_platform_register_drv // 查找設備,註冊 wifi 驅動,註冊成功調用後面的 bcmdhd_wifi_plat_dev_drv_probe
————wifi_ctrlfunc_register_drv
————|—bus_find_device //查找 wifi 設備
————|—platform_driver_register(&wifi_platform_dev_driver) //註冊 wifi 驅動
————bcmdhd_wifi_plat_dev_drv_probe //->
—————dhd_wifi_platform_load //兩個操作
——————wl_android_init //1. wlan 初始化
——————dhd_wifi_platform_load_sdio //2. 根據 介面類別型 usb、sdio、pcie 選擇不同的操作
———————dhd_bus_register // 註冊成功就調用 dhd_sdio.dhdsdio_probe
————————bcmsdh_register(&dhd_sdio)
————————|—bcmsdh_register_client_driver
————————|——sdio_register_driver(&bcmsdh_sdmmc_driver) //註冊成功調用 bcmsdh_sdmmc_probe
————————|———bcmsdh_sdmmc_probe //->
————————|———sdioh_probe
————————dhdsdio_probe
參考文章
在全志平臺調試博通的wifi驅動(類似ap6212)
wifi 詳解(三)
1.確保配置無誤
dts檔的配置wifi部分是在net/rfkill-wlan.c中進行配置;先通過內核開機記錄確認相關配置是否有正常解析,如果解析過程出現異常,確認是所配置的gpio是否存在衝突;
2.檢查供電是否正常
確認wifi的供電控制是否受控
Echo 0 > /sys/class/rkwifi/power //對wifi模組掉電
Echo 1 > /sys/class/rkwifi/power//對wifi模組上電
如果執行上面命令對模組進行上下電,而 實際測量對應管腳不受控,可以通過io 命令讀取對應的寄存器,確認是否寫入,如果正確寫入但是實際測量不受控請檢查硬體部分;
3. 掃描模組初始化模組
檢查內核中是否配置
CONFIG_WIFI_LOAD_DRIVER_WHEN_KERNEL_BOOTUP=y;
調測wifi時請把該巨集配置為 n;
執行 echo 1 > /sys/class/rkwifi/driver 命令會調用模組的驅動的初始化操作,初始化成功後看到wlan0 節點;
如何判斷是否識別到模組
* Usb介面的模組:出現如下 log
* SDIO 介面的模組
對於sdio介面的模組,執行” echo 1 > /sys/class/rkwifi/driver”命令 ,正常情況下 sdio_clk 和sdio_cmd 能夠測量到相關波形,內核列印上能夠看到如下列印,如果沒有測量到波形也沒有看到如下列印,根據配置文檔檢查是否正確配置sdio;
Wifi驅動會根據掃描到的sdio模組的vid pid 進行驅動匹配,rtl的驅動會根據讀取到的vid,pid進行驅動匹配;其中正基系列的模組會根據後面從data資料線上讀取到F1 function 讀取的數值進行 驅動與固件匹配(正基目前的驅動相容所有sdio介面正基模組,根據F1 function 讀取的值 匹配固件);
如果能夠掃描模組但是初始化過程看到data fifo error,檢查下 sdio介面電平是否一致;方法如下:
echo 1 > /sys/class/rkwifi/power
測量 VDDIO sdio_clk sdio_cmd sdio_data0~sdio_data3 的電壓;正常情況下 sdio_clk 為 0V,sdio其他五根線與vddio電壓一致;
如果電壓不一致:312x平臺確認下 sdio介面的內部上下拉是否禁掉,參看文檔RK Kernel 3.10平臺WiFi BT不工作異常排查.pdf Part C;其他平臺考慮加外部上拉(注clk絕對不要加外部上拉);
同時測量執行echo 1 > /sys/class/rkwifi/driver 時 外部晶體是否有起振,如果掃描時沒有起振檢查下硬體;同時建議測量外部晶體頻偏,頻偏比較大情況下,會出現能掃描到模組但是初始化失敗;除檢查晶振外,正基系列還需要外部32k,測量32k的峰峰值(峰峰值>=0.7*VDDIO && 峰峰值 <= 1*VDDIO);【注:頻偏和峰峰值一定要測量檢查,頻偏過大峰峰值不對會影響wifi(掃描連接熱點)和藍牙(掃描連接設備))】
電壓一致情況下,晶振頻偏和32k的峰峰值沒有問題(正基系列的要考慮晶振頻偏與32k峰峰值,具體結合自己電路實際情況)但是初始化依然出問題;
考慮降低sdio_clk ,重新測試;如果降低clk可以,考慮硬體上走線;
如果降低clk依然不行,考慮使用sdio單線模式方法如下
&sdio {
...
bus-width = <1>;
...
};
使用 sdio 單線模式。如果單線模式可以而使用4線模式不行,檢查硬體上sdio_data0~sdio_data3 四根線的線序是否弄錯;
如果降低clk,使用單線模式均不可以檢查下是否是使用最新的sdk代碼和最新的wifi驅動(ftp伺服器上有相關patch);
上述檢查均無結果,check 圖紙 是否周圍器件有貼錯器件;
4.檢查模組能否處於工作狀態
netcfg wlan0 up 或busybox ifconfig wlan0 up //執行完成後檢查 wlan0 是否處於up狀態;如果沒有處於up狀態;做如下檢查確認
1 確認相關固件是否存在(正基系列,通過看內核日誌可以看到),固件不存在考慮到ftp下載固件;此時如果還報其他錯誤從兩個方面排查1 上電時序,2檢查sdio部分走線;
2 嘗試使用原始最新的sdk代碼做測試;(有客戶出現過,上層做了相關修改導致wifi初始化成功,但是執行netcfg wlan0 up 報告無法識別 ioctl 命令等奇怪錯誤,原生sdk生成的sysytem.img 沒有問題)
執行iwlist wlan0 scanning ,測試掃描熱點是否正常(3368平臺下執行iwlist 命令有問題,忽略此步驟)
5. 確認Android層是否能夠打開
述檢查各個步驟可以工作,而通過上層settings介面打開失敗;以下幾個方面排查
1 dts中的wifi_type配置是否正確;cat /sys/class/rkwifi/chip 確認 下 列印的結果和你的模組是否匹配
2 確認 wpa_supplicant 相關服務是否生成,libhardware_leacy 啟動的wpa服務是否正確;
3 抓取logcat 日誌上傳readmine
- pcb檢查,一定要讓模組原廠檢查確認 pcb是否存在問題
- RF指標確認是否ok
- 天線是否做過匹配
- Sdio 介面的可以考慮 提到sdio的clk 啟用sdio3.0【前提 平臺支援 sdio3.0 ,模組支援sdio3.0】
無法連接熱點
1.無法連接熱點,正基系列模組檢查確認晶振頻偏和32k峰峰值;
rtl模組考慮驅動配置是否正確,是否匹配;
2.檢查確認p2p wlan0 的mac位址是否一致如果檢查是否有調用rockchip_wifi_mac_addr讀取mac地址,如果有考慮直接在該函數中return -1;
3.檢查確認是否有做RF指標測試以及天線匹配測試
4.上述檢查沒有問題,做如下測試 (首先用給手機連接所測試的熱點做確認)
1 連接無加密熱點 2 連接加密熱點 測試能否連接成功,並記錄對應的logcat 日誌與內核日誌(開機到打開wifi以及連接熱點的整個過程)
softap 無法打開(正基系列的)
1.查看打開熱點時的內核日誌,確認下 下載固件是否正確 ,正基系列的模組 softap 下載的固件一般是帶ap尾碼結尾的;
2.固件下載沒有問題 ,考慮使用原始的sdk代碼做測試
P2P 問題
P2p 無法打開:確認是否有p2p節點,有p2p節點的檢查確認mac地址是否與wlan0 一樣,如果一樣按照熱點問題中的step 2 處理;
第一次開機能夠打開,重啟後無法打開:考慮檢查上電時序,目前遇到都是rtl的模組出現過,問題在於chipen 腳不受控,建議做成受控,在重啟時對chipen腳下電;可以通過如下方法實現net/rfkill-wlan.c中的rfkill_wlan_driver 中增加shutdown函數 在該函數中對chip_en 下電;
休眠喚醒出現wifi無法打開:
1 對比檢查休眠喚醒前後 sdio 的iomux 是否發生變更
2 對比 休眠前後以及休眠中 wifi的週邊供電是否發生變更