2008年9月1日 星期一

The fix for the SD controller driver

前一陣子在測試新加入的 SD 驅動程式時,發現了一個怪異的問題:某些卡可以正確偵測,某些卻不行。目前我所可以拿來測試的 SD 卡有兩塊;一塊是 512MB,SD 1.1 標準的卡,另一塊則是 256MB,SD 2.0 的卡。第一張卡沒有問題,但第二張卡卻出現以下的錯誤訊息:

s3c2440-sdi s3c2440-sdi: running at 0kHz (requested: 0kHz).
s3c2440-sdi s3c2440-sdi: running at 265kHz (requested: 264kHz).
s3c2440-sdi s3c2440-sdi: running at 265kHz (requested: 264kHz).
s3c2440-sdi s3c2440-sdi: running at 265kHz (requested: 264kHz).
s3c2440-sdi s3c2440-sdi: CMDSTAT: error CMDTIMEOUT
s3c2440-sdi s3c2440-sdi: CMDSTAT: error CMDTIMEOUT
s3c2440-sdi s3c2440-sdi: CMDSTAT: error CMDTIMEOUT
s3c2440-sdi s3c2440-sdi: CMDSTAT: error CMDTIMEOUT
s3c2440-sdi s3c2440-sdi: running at 265kHz (requested: 264kHz).
s3c2440-sdi s3c2440-sdi: running at 265kHz (requested: 264kHz).
s3c2440-sdi s3c2440-sdi: running at 265kHz (requested: 264kHz).
s3c2440-sdi s3c2440-sdi: running at 265kHz (requested: 264kHz).
s3c2440-sdi s3c2440-sdi: mci_setup_data() transfer stillin progress.
s3c2440-sdi s3c2440-sdi: CMDSTAT: error CMDTIMEOUT
s3c2440-sdi s3c2440-sdi: powered down.
mmc0: error -110 whilst initialising SD card
s3c2440-sdi s3c2440-sdi: powered down.
倒數第四行出現了 command timeout 的訊息,再仔細查看,發生錯誤的命令是 CMD6 (switch card function),而之前的命令是 ACMD51 (read SCR),該命令需要設定資料傳輸來讀取 SCR 的值。怪就怪在,當資料已傳輸完成,下個指令 (CMD6) 要重新設定資料傳輸時,卻發現狀態暫存器中的旗標仍然指示資料在傳輸中,因而驅動程式強迫終止資料傳輸,並重設 (reset) 控制器。重設的結果,便是所有暫存器中的內容回復為初始化前的預設值,同時關閉了控制器送給 SD 卡的時脈輸出。當然緊接在後的命令也都跟著錯誤。

雖然我並不非常熟悉 SD 的 protocol,但我覺得應該不是上層 protocol stack 的問題,畢竟第一張卡是可以正確運作的;由於 S3C2440 的使用手冊上載明這個控制器只有符合 SD 1.0 的規範,是故猜想可能是控制器的問題,所以我送了一個 patch,主要是在重設控制器以後,重新打開 SD 的時脈輸出,以便使後續的命令可以繼續運作。

即使手上有晶片使用手冊,並仔細研讀,但在面對這種在文件上毫無著墨的怪異行為時,仍是不免讓人感到挫折。

PS.
MMC protocol stack 的維護者 Pierre Ossman 提醒我,不要在 SD 卡的電源關閉時開啟 SD 時脈訊號,此舉有可能會導致 SD 卡的損壞。不過我認為應該不會發生這種情況;會執行到這段程式碼時,表示 SD 卡的電源已被開啟,並且已經開始接受命令了。又控制器重設時並沒有動到對應於 SD 時脈的 GPIO 針腳的狀態,是故應該不會有損壞的問題。

沒有留言: