天天看點

[Android6.0][RK3399] SDIO 接口 Wifi 驅動流程分析 (AP6354)

Platform: RockChip

OS: Android 6.0

Kernel: 4.4

WiFi/BT/FM 模組: AP6354

前面的基本概念搜羅于網絡;

後面的驅動流程分析是根據 RockChip 3399 的 Kernel 部分來進行分析的。

    • 基本概念
      • Wifi
      • WLAN
      • 關系
      • STA 模式 和 AP 模式
      • 無線接入過程的三個階段
      • SD 和 MMC
      • SDIOSecure Digital IO
      • SDIO 卡 和 SD 卡 的差別
      • SDIO-Wifi 子產品
      • SDIO 總線
      • SDIO 指令
    • WIFI 子產品解析和啟動流程
    • SDIO 接口驅動
    • WIFI 驅動流程分析
    • 調試問題
      • 調試步驟
        • 確定配置無誤
        • 檢查供電是否正常
        • 掃描子產品初始化子產品
        • 檢查子產品能否處于工作狀态
        • 确認Android層是否能夠打開
      • 吞吐率問題
      • 其他問題
        • 無法連接配接熱點
        • softap 無法打開正基系列的
        • P2P 問題

本部落格唯一位址:http://blog.csdn.net/dearsq/article/details/53318887

歡迎轉載,轉載請注明作者 Younix~ 謝謝~

基本概念

Wifi

wifi 英文全稱是 WIreless-FIdelity,翻譯成中文就是無線保真,英文簡稱WiFi。

WLAN

wlan 英文全名:Wireless Local Area Networks, 無線區域網路絡。

關系

wifi 是實作 wlan 的一種技術。

STA 模式 和 AP 模式

AP模式: Access Point,提供無線接入服務,允許其它無線裝置接入,提供資料通路,一般的無線路由/網橋工作在該模式下。AP和AP之間允許互相連接配接。

Sta模式: Station, 類似于無線終端,sta本身并不接受無線的接入,它可以連接配接到AP,一般無線網卡即工作在該模式。

無線接入過程的三個階段

STA(工作站)啟動初始化、開始正式使用AP傳送資料幀前,要經過三個階段才能夠接入(802.11MAC層負責用戶端與AP之間的通訊,功能包括掃描、接入、認證、加密、漫遊和同步等功能):

1)掃描階段(SCAN)

2)認證階段 (Authentication)

3)關聯(Association)

[Android6.0][RK3399] SDIO 接口 Wifi 驅動流程分析 (AP6354)

更詳細的 wifi 相關介紹可以參考這篇文章 WiFi基礎知識解析

後面介紹 Wifi 的接口 SDIO 的基本概念。

SD 和 MMC

SD (Secure Digital) 與 MMC (Multimedia Card)

MMC 是較早的一種記憶卡标準,目前已經被 SD 标準取代。

SD 是一種 flash memory card 的标準,也就是一般常見的 SD 記憶卡。

SDIO(Secure Digital I/O)

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

SDIO 卡 和 SD 卡 的差別

SD卡使用的是SD卡協定,而SDIO卡使用的是SDIO協定!

協定不一樣,初始化/讀寫方式也不一樣!

SDIO-Wifi 子產品

SDIO-Wifi 子產品是基于 SDIO 接口的符合 wifi 無線網絡标準的嵌入式子產品,内置無線網絡協定IEEE802.11協定棧以及TCP/IP協定棧,能夠實作使用者主平台資料通過SDIO口到無線網絡之間的轉換。

SDIO 具有傳輸資料快,相容SD、MMC接口等特點。

對于SDIO接口的wifi,首先,它是一個sdio的卡的裝置,然後具備了wifi的功能。

是以,注冊的時候還是先以sdio的卡的裝置去注冊的。然後檢測到卡之後就要驅動他的wifi功能。

SDIO 總線

SDIO總線 和 USB總線 類似,SDIO也有兩端,其中一端是HOST端,另一端是device端。所有的通信都是由HOST端 發送 指令 開始的,Device端隻要能解析指令,就可以互相通信。

CLK信号:HOST給DEVICE的 時鐘信号,每個時鐘周期傳輸一個指令。

CMD信号:雙向 的信号,用于傳送 指令 和 反應。

DAT0-DAT3 信号:四條用于傳送的資料線。

VDD信号:電源信号。

VSS1,VSS2:電源地信号。

SDIO 指令

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 子產品解析和啟動流程

對于 Wifi 模組的 Android 上層的分析,這篇文章講的非常不錯:

http://blog.csdn.net/ylyuanlu/article/details/7711433

這篇文章将下圖藍色的和綠色的部分講的非常詳細。

[Android6.0][RK3399] SDIO 接口 Wifi 驅動流程分析 (AP6354)

我這個闆子上所采用的 WiFi 模組是 AP6354, 它是一個 Wifi / BT4.0 / FM 三合一模組。接口是 SDIO。

本文主要分析 Kernel Driver 部分。是以先從 SDIO 接口的驅動來切入。

SDIO 接口驅動

SDIO 接口的 wifi,首先,它是一個 sdio 卡 裝置,然後具備了 wifi 的功能,是以 SDIO 接口的 WiFi 驅動就是在 wifi 驅動 外面套上了一個 SDIO 驅動 的外殼。

SDIO 驅動部分代碼結構如下

[Android6.0][RK3399] SDIO 接口 Wifi 驅動流程分析 (AP6354)

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 驅動。

WIFI 驅動流程分析

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.確定配置無誤

[Android6.0][RK3399] SDIO 接口 Wifi 驅動流程分析 (AP6354)

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

[Android6.0][RK3399] SDIO 接口 Wifi 驅動流程分析 (AP6354)

* SDIO 接口的子產品

對于sdio接口的子產品,執行” echo 1 > /sys/class/rkwifi/driver”指令 ,正常情況下 sdio_clk 和sdio_cmd 能夠測量到相關波形,核心列印上能夠看到如下列印,如果沒有測量到波形也沒有看到如下列印,根據配置文檔檢查是否正确配置sdio;

[Android6.0][RK3399] SDIO 接口 Wifi 驅動流程分析 (AP6354)

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 = <>;
        ...
};
           

使用 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

吞吐率問題

  1. pcb檢查,一定要讓子產品原廠檢查确認 pcb是否存在問題
  2. RF名額确認是否ok
  3. 天線是否做過比對
  4. 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的外圍供電是否發生變更

繼續閱讀