隨身碟現在已經逐漸取代了PC時代磁碟片的角色,而SD卡加上讀卡機不僅等同於隨身碟,在應用上尤其彈性且方便,由於它體積小容量大的特性,更是容易使用在很多電子3C產品上。之於MCU而言,資料的儲存從過去存在內建EEPROM的方式,現在也可以選用可抽換的SD卡來當作大量資料的儲存媒體,這無非是讓MCU在記憶系統擴充上如虎添翼。
我用MCU寫SD卡的應用程式已經好多年了,早期用一顆含有SD介面的Enhance 8051 MCU用組合語言寫出SD card reader程式,讀寫程式做到最佳化,讀寫的速度比起當時的card reader毫不遜色。一直以來MCU程式都是學習使用SD mode來寫SD的應用,幾乎沒什麼機會去認識SD的SPI mode。
近來學習了一顆ARM Cortex M0的MCU,發現它的SPI介面功能很強,還另有CCITT CRC16的快速演算功能,因為這兩個要件讓我覺得現在可以開始研究SD的SPI mode。
在過去,正統的SD卡應用,例如 card reader都是使用講求高速的SD mode。但也偶爾聽到一些人有應用SD SPI mode的問題。但我一直認為SD mode 4 bit速度快,為何會有人要去用1 bit 的SPI mode,但在一番研究之後,現在我終於有所理解。
原來一般低價位或泛用型的MCU大多沒有內嵌SD介面功能,如果要用這些普通的MCU來做SD卡應用,那通常只能適合用SPI mode來讀寫SD。但我過去在無知的情況下,竟然先學會用普通的8051 的GPIO功能來寫比較複雜的SD mode程式。因為已經經驗豐富,所以現在更可以比較出SD卡的SD mode跟SPI mode之間的應用差異。
我認為SD卡的技術規範裡(SD protocol SPEC)是以SD mode為主,SPI mode為輔,所以SD mode的技術資訊寫得相當詳細且複雜,而相對的SPI mode篇幅就顯得簡單許多。SD mode可以有1bit跟4bit data的讀寫模式,最主要的是SD mode在command string結尾要加CRC7驗證碼,在data string要在結尾加CRC16驗證碼,但command string是1bit要弄CRC7還算簡單,但512byte 4bit data的寫入卻需要提供4 channel的CRC16同步演算,這若沒有硬體CRC logic來處理,普通的MCU是很難搞的,縱使用很複雜的演算程式寫出512byte 4 channel的CRC,那最後的寫入速度也只能用牛步來形容。而且SD mode強制要使用CRC,但SPI mode則可以選擇要或不要CRC。這也就是為何普通MCU應用SD卡會採用SPI mode的最大因素。
雖然SD的SPI mode的4隻訊號腳CLK, DO, DI, CS不完全等同於一般通訊用的SPI介面,但仍被規範成如同SPI介面用的CLK, MISO, MOSI, SS的使用模式,只要程式能夠技巧性地處理SPI mode data string的start bit跟end bit就可以了。基本上進入SD SPI mode後,CRC檢查功能是disable的。但也可以發CMD59 command去enable CRC檢查功能,但我想沒人會自找麻煩,用SPI mode又去enable CRC檢查功能。
另外SPI mode也簡化了一些command及SD mode複雜的command state結構,這也讓User不需去理解複雜的SD mode command應用。像是SD mode有個CMD3要讀RCA,CMD7用來轉換state,之後在許多command argument都要帶有RCA才行。還有SD mode的CMD信號腳是雙向I/O,也就是說host發commnad到SD卡後CMD腳就要馬上轉向為input接收SD response,且這48bit response也比SPI mode的8bit response複雜許多。
最後經過一番研究跟程式的實驗,我終於用一般8051 MCU的SPI功能玩出了SD SPI mode的讀寫程式,技術資料裡的一些SD SPI mode敘述簡單到有點語焉不詳,實際上還是要參照一些寫在SD mode的資訊,要不是之前有研究過SD mode的經驗,真的是沒有下過一番功夫仔細研究還真是不容易搞定。如果可以把MCU SPI程式寫得很漂亮,SPI clock做到最大化,其實沒有SD介面的MCU也可以用1bit SPI mode做出很不錯的SD讀寫效率。最後在Megawin的MG84FG516可以跑8MHz SPI clock,在ARM Cortex M0的MG32F02A072可以跑12MHz SPI clock,兩者都表現了最佳化的讀寫效率。