一、uboot中SD卡的初始化
二、读取扇区
三、 写变量到SD卡中
四、
一、uboot中SD卡的初始化
1.1 硬件连线
1.2 uboot中初始化过程
uboot lib_arm/board.c中
a. 设置为sector mode
b.以扇区为单位,设置BL1,ENV,BL2,kernel,rootfs的位置
c. SD控制器初始化
cpu/s3c64xx/hs_mmc.c
为了区别SD卡是2.0还是1.0,或是MMC卡,这里根据协议向上兼容的原理,首先发送只有SD2.0才有的命令CMD8,如果CMD8返回无错误,则初步判断为2.0卡,进一步发送命令循环发送CMD55+ACMD41,直到返回0x00,确定SD2.0卡初始化成功,进入Ready状态,再发送CMD58命令来判断是HCSD还是SCSD,到此SD2.0卡初始化成功。如果CMD8返回错误则进一步判断为1.0卡还是MMC卡,循环发送CMD55+ACMD41,返回无错误,则为SD1.0卡,到此SD1.0卡初始成功,如果在一定的循环次数下,返回为错误,则进一步发送CMD1进行初始化,如果返回无错误,则确定为MMC卡,如果在一定的次数下,返回为错误,则不能识别该卡,初始结束。
二、读取扇区
SDMK6410> fatload mmc 0:1 50008000 zImage
以读取MBR为例
do_fat_fsload
--> fat_register_device(dev_desc,part);
--> dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *)buffer);
1. 初始化时
hsmmc_init() //初始化mmc_dev的函数指针
{
mmc_dev.if_type = IF_TYPE_MMC;
mmc_dev.part_type = PART_TYPE_DOS;
mmc_dev.dev = 0;
mmc_dev.blksz = MMC_BLOCK_SIZE;
mmc_dev.block_read = mmc_bread;
}
2. 正式进入读取部分
cpu/s3c64xx/hs_mmc.c L1337
/*
dev_num: 第几个mmc设备
blknr: 开始的扇区
blkcnt: 要读取的扇区数
dst: 数据保存到的dst_buffer
*/
static ulong mmc_bread (int dev_num, ulong blknr, ulong blkcnt, ulong* dst)
{
if (dst >= 0xc0000000)
dst = virt_to_phys(dst); //取物理地址
if (blkcnt != 0) //连dev_num都不要了,看来只能支持1个SD设备
movi_read((uint) dst, (uint) blknr, (uint) blkcnt);
return blkcnt;
}
void movi_read (uint addr, uint start_blk, uint blknum)
{
}
三、写入扇区
SMDK6410> saveenv
二、读取扇区
三、 写变量到SD卡中
四、
一、uboot中SD卡的初始化
1.1 硬件连线
- MMC0_CDN --> GPG6 --> SD卡检测引脚
- MMC0_WPN --> GPGL13 --> SD卡写保护引脚
- MMC0_DATA[0-3] --> GPG[2-5] -->
- MMC0_CMD --> GPG1 --> SD命令线
- MMC0_CLK --> GPG0 --> SDIO/SD卡时钟线
uboot lib_arm/board.c中
- void start_armboot (void)
- {
- #if defined(CONFIG_BOOT_MOVINAND)
- puts ("SD/MMC: ");
- if ((0x24564236 == magic[0]) && (0x20764316 == magic[1])) {
- printf("Boot up for burningn");
- } else {
- movi_set_capacity();
- movi_set_ofs(MOVI_TOTAL_BLKCNT);
- movi_init();
- }
- #endif
- }
- movi_set_capacity();
- {
- if (MOVI_HIGH_CAPACITY & 0x1) //in sector mode, this value will be set
- movi_hc = 1; //全局变量movi_hc=1
- }
- movi_set_ofs(MOVI_TOTAL_BLKCNT);
- {
- if (ofsinfo.last != last) {
- ofsinfo.last = last - (eFUSE_SIZE / MOVI_BLKSIZE);
- ofsinfo.bl1 = ofsinfo.last - MOVI_BL1_BLKCNT;
- ofsinfo.env = ofsinfo.bl1 - MOVI_ENV_BLKCNT;
- ofsinfo.bl2 = ofsinfo.bl1 - (MOVI_BL2_BLKCNT + MOVI_ENV_BLKCNT);
- ofsinfo.kernel = ofsinfo.bl2 - MOVI_ZIMAGE_BLKCNT;
- ofsinfo.rootfs = ofsinfo.kernel - MOVI_ROOTFS_BLKCNT;
- changed = 1;
- }
- }
- movi_init();
- {
- hsmmc_set_gpio();
- {
- reg = readl(GPGCON) & 0xf0000000;
- writel(reg | 0x02222222, GPGCON); //设置 GPG为MMC模式
- reg = readl(GPGPUD) & 0xfffff000;
- writel(reg, GPGPUD); //上拉电阻disable
- }
- hsmmc_reset();
- {
- s3c_hsmmc_writeb(0x3, HM_SWRST); //data_line && cmd_line reset
- }
- if (hsmmc_init()) {
- printf("nCard Initialization failed.n");
- return -1;
- }
- return 1;
- }
- int hsmmc_init (void)
- {
- hsmmc_clock_onoff(0); //关闭SDCLK
- {
- a. CLKCON0[2]:0 //SD Clock diaable
- }
-
- a. SCLK_GATE-->0x7E00_F038[27]:
- SCLK_MMC0_48 [27] Gating special clock for MMC0 (0: mask, 1: pass)
-
- b.
- set_clock(SD_EPLL, 0x80);
- {
- //CONTROL2_0 0x7C200080 R/W Control register 2 (Channel 0)
- //[5:4]: Base Clock Source Select--> EPLL
- //[14]:1 Feedback Clock Enable for Rx Data/Command Clock
- //[30]:1 Command Conflict Mask Enable
- //[31]:1 Write Status Clear Async Mode Enable
- s3c_hsmmc_writel(0xC0004100 | (clksrc << 4), HM_CONTROL2);
-
- s3c_hsmmc_writel(0x00008080, HM_CONTROL3);
- s3c_hsmmc_writel(0x3 << 16, HM_CONTROL4);
- //下3条: SDCLK Frequency Select
- //div=80h base clock divided by 256
- //
- //最后的for The SD Host Driver shall wait to set SD Clock Enable until this bit is set to 1.
- s3c_hsmmc_writew(s3c_hsmmc_readw(HM_CLKCON) & ~(0xff << 8), HM_CLKCON);
- s3c_hsmmc_writew(((div<<8) | 0x1), HM_CLKCON);
- for(i=0; i<0x10000; i++) ; //wait stable
-
- hsmmc_clock_onoff(1);
- }
- c. s3c_hsmmc_writeb(0xe, HM_TIMEOUTCON);
- TIME_OUT_CNT=1110b TMCLK x 2的27
- }
二、读取扇区
SDMK6410> fatload mmc 0:1 50008000 zImage
以读取MBR为例
do_fat_fsload
--> fat_register_device(dev_desc,part);
--> dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *)buffer);
1. 初始化时
hsmmc_init() //初始化mmc_dev的函数指针
{
mmc_dev.if_type = IF_TYPE_MMC;
mmc_dev.part_type = PART_TYPE_DOS;
mmc_dev.dev = 0;
mmc_dev.blksz = MMC_BLOCK_SIZE;
mmc_dev.block_read = mmc_bread;
}
2. 正式进入读取部分
cpu/s3c64xx/hs_mmc.c L1337
/*
dev_num: 第几个mmc设备
blknr: 开始的扇区
blkcnt: 要读取的扇区数
dst: 数据保存到的dst_buffer
*/
static ulong mmc_bread (int dev_num, ulong blknr, ulong blkcnt, ulong* dst)
{
if (dst >= 0xc0000000)
dst = virt_to_phys(dst); //取物理地址
if (blkcnt != 0) //连dev_num都不要了,看来只能支持1个SD设备
movi_read((uint) dst, (uint) blknr, (uint) blkcnt);
return blkcnt;
}
void movi_read (uint addr, uint start_blk, uint blknum)
{
}
三、写入扇区
SMDK6410> saveenv