platform: s3c2440 + linux 2.6.18
在linux2.6.18 中,sd卡的驅動有不少的bug.例如,沒有寫保護的功能.
在驅動的模塊中預留了寫保護的函數,但是沒有實現,代碼也只有幾行,只要加上去編譯一下就OK了.
static struct mmc_host_ops s3c2410sdi_ops = { .request = s3c2410sdi_request, .set_ios = s3c2410sdi_set_ios, .get_ro = s3c2440_get_ro, //sd card ReadOnly Flag. }; |
實現函數如下:
static int s3c2440_get_ro(struct mmc_host *mmc) { struct s3c2410sdi_host *host = mmc_priv(mmc); unsigned long flags; int present; spin_lock_irqsave(&host->complete_lock, flags); present = read_gpio_bit(S3C2410_GPB0); present &= 0x01; spin_unlock_irqrestore(&host->complete_lock, flags); return present; } |
還有一些就是熱插拔的和中斷檢測口,只要設置一下就可以用了.
比較麻煩的是對SD卡寫操作,只要寫稍微大點的文件到SD卡就會出錯,打印出如下信息:
[IRQ] csta=00000a19 dsta=00000002 fsta=00002200 dcnt=00008000 [IRQ] csta=00000a19 dsta=00000002 fsta=00002200 dcnt=00007000 [IRQ] csta=00000a19 dsta=00000002 fsta=00002200 dcnt=00007000 [IRQ] csta=00000a19 dsta=00000002 fsta=00002200 dcnt=00007000 |
對比正常傳送打印出來的信息,很明顯程序是在這裏掛掉了.
後來跟蹤代碼發現,當寫一個 4096(512*8)的數據時,只寫了第一個512byte就不往下寫了,所以dcnt一直爲 7000,出現這個現象的原因是因爲程序對 host->pio_words 這個變量賦的值爲128,通過 host->pio_words-- 遞減到0時就不進入
while(sdi_fsta & S3C2410_SDIFSTA_TFDET && host->pio_words)這個循環了,
所以 host->pio_words=sdi_bsize>>2; 這一行應改爲
host->pio_words = mrq->data->blocks * (sdi_bsize>>2);
這樣對SD卡的寫操作就解決了.但寫的速度不是很快.
還有一個問題,比如 cp 一個文件到SD卡上,是不是首先先將這個文件寫到SDRAM上,然後umount的時候再將SDRAM中的內容真正寫SD卡上??我umount的時候會過多一會纔出現終端的提示符,根據寫入文件的大小確定 umount的時間?
後來查了一下資料,Linux文件系統更新是一個複雜的過程,當用戶程序對文件系統進行修改以後,例如進行了寫操作,文件數據把修改記錄在內核緩衝中,在數據沒有寫到磁盤的時候,依然能夠執行用戶進程,所有數據的改變都在inode的內容中得到反映。磁盤的數據更新實際上是異步進行的,很有可能在寫操作已經完成很長時間以後才真正對磁盤的數據進行更新。sync命令強制把磁盤緩衝的所有數據寫入磁盤,如果在沒有把磁盤緩衝區的信息寫入磁盤之前終止系統,則磁盤的文件系統就會處在一個不穩定的狀態。而在正常模式下即使沒有對分區進行umount的操作,在重啓之前系統會調用sync命令強制把磁盤緩衝的所有數據寫入磁盤,而在急救模式下必須對所掛的分區進行umount的操作,系統纔會調用sync命令強制把磁盤緩衝的所有數據寫入磁盤,請在急救模式下的朋友注意這個問題。其實“reboot -n(Don’t sync before reboot or halt)”在重啓之前不用sync命令強制把磁盤緩衝的所有數據寫入磁盤,就很能說明問題。
所以要 cp 完之後要執行 sync 命令將緩衝區的內容寫到磁盤中,然後再umount 就不會出現延時了.
s3c2440 SD卡(for LINUX)驅動代碼下載地址:
http://handhelds.org/cgi-bin/cvsweb.cgi/linux/kernel26/drivers/mmc/s3c2440mci.c