1. SD卡介紹
- SD卡是帶有控制器和封裝的NANDFLASH,各種型號(hào)SD卡的接口都是通用的。
- SD卡支持SD協(xié)議和SPI協(xié)議,支持SPI協(xié)議可以方便單片機(jī)的使用。雖然支持兩種協(xié)議,但是用相同的硬件接口(兩根地線,一根電源線,六根信號(hào)線)。
- SD卡是一種ROM,不能按地址讀寫,只能按塊讀寫。(塊/扇區(qū):Block, 一個(gè)扇區(qū)一般包含512B的內(nèi)容,使用塊來(lái)存儲(chǔ)的設(shè)備稱作塊設(shè)備)
- SD卡、TF卡、MMC卡之間的區(qū)別。MMC卡是支持MMC協(xié)議的卡,MMC協(xié)議出現(xiàn)地比SD協(xié)議早,現(xiàn)在基本被淘汰,但SD協(xié)議兼容MMC協(xié)議。TF卡與SD卡大同小異,體積小一些。
2. SD卡啟動(dòng)流程
以bootloader的啟動(dòng)為例說(shuō)明。

- 首先S5PV210內(nèi)置的iROM上電直接運(yùn)行(能直接上電運(yùn)行不需初始化的是Norflash),執(zhí)行一系列初始化操作,最重要的是將會(huì)根據(jù)OM引腳判別出啟動(dòng)方式,然后初始化外部的存儲(chǔ)器(圖中的“Booting Device”),并將其中bootloader的前16KB(即BL1)復(fù)制到內(nèi)部的SRAM中執(zhí)行。這一步,就是三星的啟動(dòng)方式“Steppingstone技術(shù)”。
- 然后BL1就為所欲為,將bootlaoder全部(即BL2)復(fù)制到SDRAM中進(jìn)行執(zhí)行。完成啟動(dòng)過(guò)程。(與圖中所畫有不同之處。)
在上面的講述中,有兩個(gè)地方值得注意:
- BL2是bootloader的全部?jī)?nèi)容,而不是除了BL1之外的其他內(nèi)容,這將在下面講述SD卡的分散加載與整體加載時(shí)說(shuō)道。
- 上面操作的第二步可以看到跟圖上的不同,圖上是把剩下的bootloader加載到SRAM中的,而我說(shuō)的則是把bootloader整體加載到內(nèi)存SDRAM中,這是因?yàn)楝F(xiàn)在bootloader實(shí)際上已經(jīng)遠(yuǎn)大于96K了,SRAM中放不下!
- 上述操作的第二步是將程序從外部的“Booting Device”復(fù)制到SDRAM中,這一過(guò)程使用的是IROM中提供的 Device Copy Function來(lái)完成的。
3. SD卡啟動(dòng)方式-分散加載
這里我要討論的情況是需要大于96K的情況(一定要分為兩部分的情況)。
分散加載的意思就是把一個(gè)程序分成完全獨(dú)立的兩個(gè)部分,注意是完全獨(dú)立,兩個(gè)文件夾,各自有各自的makefile,如下圖所示。

為了編譯鏈接方便,在頂層文件夾有一個(gè)總的makefile:
all:
make -C ./BL1
make -C ./BL2
clean:
make clean -C ./BL1
make clean -C ./BL2
-
BL1與BL2燒寫到SD卡的不同位置。一般BL1(16K)是1-32扇區(qū)(16K = 32*512B),BL2則選擇留一點(diǎn)空隙,從49等扇區(qū)開始燒寫。注意,BL1不是從扇區(qū)0開始燒寫的,因?yàn)槿怯幸?guī)定,如下所示。
SD卡內(nèi)存分配 - 程序在實(shí)際執(zhí)行時(shí),執(zhí)行BL1,將BL2復(fù)制到SDRAM中,然后就跳轉(zhuǎn)到SDRAM中去執(zhí)行,這個(gè)跳轉(zhuǎn)指令很有意思。由于BL1和BL2是兩個(gè)程序,不能再用諸如
ldr pc, = main這種跳轉(zhuǎn)指令來(lái)跳轉(zhuǎn),而是需要直接使用BL2在SDRAM中的地址,以函數(shù)指針的形式來(lái)使用。
4. SD啟動(dòng)方式-整體加載
同樣這里討論程序大于96K時(shí)的情況。
整體加載是相對(duì)于上面的分散加載而言的,在這里不再將程序分為兩個(gè)部分,而是作為一個(gè)整體。

- 由于在這里BL1和BL2是一個(gè)程序的,所以在執(zhí)行完BL1之后可以使用
ldr pc, = main這樣的代碼跳轉(zhuǎn)到BL2中執(zhí)行。
以上3、4部分就是SD卡啟動(dòng)兩種方式,目前使用的基本為方式4,因?yàn)楦?jiǎn)潔方便。
5. Device Copy Function
設(shè)備復(fù)制函數(shù)可以在三星的iROM的Application Note中找到,以SD卡的為例。

/**
* This Function copy MMC(MoviNAND/iNand) Card Data to memory.
* Always use EPLL source clock.
* This function works at 20Mhz.
* @z : 這個(gè)參數(shù)是SD卡的通道號(hào),在我的開發(fā)板中通道0連接的是內(nèi)部的iNAND,通道2是我要用的。
* @a : param u32 StartBlkAddress : Source card(MoviNAND/iNand MMC)) Address.(It must block address.) 起始的block號(hào)。
* @b : param u16 blockSize : Number of blocks to copy. 共復(fù)制的block數(shù)目。
* @c : param u32* memoryPtr : Buffer to copy from. 復(fù)制到SDRAM中的地址。
* @e : param bool with_init : determined card initialization. 一般置0,不做處理。
* @return bool(u8) - Success or failure.
*/
#define CopySDMMCtoMem(z,a,b,c,e)(((bool(*)(int, unsigned int, unsigned short, unsigned int*, bool))(*((unsigned int *)0xD0037F98)))(z,a,b,c,e))
上面給出了SD卡復(fù)制函數(shù)的宏定義,以及相關(guān)參數(shù)的含義。
分析一下上面的宏定義右邊的內(nèi)容,0xD0037F98是函數(shù)指針的指針,這基于兩個(gè)事實(shí),一個(gè)是0xD0037F98是iRAM上的地址,而塊設(shè)備復(fù)制函數(shù)本體一定是寫在iROM中的,所以(*((unsigned int *)0xD0037F98) 代表的就是設(shè)備復(fù)制函數(shù)的指針,(bool(*)(int, unsigned int, unsigned short, unsigned int*, bool))是函數(shù)指針類型的強(qiáng)制數(shù)據(jù)類型轉(zhuǎn)換。
