在这里主要记录下设备在启动过程中存储设备(SD/MMC)所做的一系列操作,在这里我是用的S5PV210主控,以供以后参考。
一般来说,设备有(IRAM IROM DRAM INAND SD)这四种存储设备,在这里主要是分析mboot启动过程中INAND/SD卡的工作情况。
首先我们从0xE0000004这个SFRS这读取设备的启动信息(nand、onenand、sd/mmc、eMMC、nor),默认的设备启动过程中一般是从sd/mmc读取mboot kernel等到DRAM里运行启动设备。首先我们就要判断好设备是从INAND还是SD卡启动,默认的设备是从INAND启动,只有当INAND里没有启动文件时,才会考虑从SD卡启动。
在这里SD/MMC controller 支持8-bit 2 channel, or 4-bit 4 channel,inand采用8-bit模式(对应cha0-cha1),而sd卡则采用4-bit模式(对应cha2);现在判断从哪个设备启动就转变为设备从哪个通道启动,从0xD0037488处我们可以读到设备启动的通道数,从而据此我们可以做出相应的初始化。
接着我们对设备的存储设备进行初步的初始化(inand/sd),首先是对inand进行初始化(无论设备是否从cha0启动),接着再判断设备是否从SD卡启动,若是,则再对SD卡进行初始化。
接着看下这初步的初始化主要做了哪些操作:首先要初始化SD/MMC的时钟和管脚,要确保SD/MMC的工作环境运行正常,接着初始化负责记录SD/MMC信息的结构体
typedef struct { // structure of Extended CSD register
unsigned char reserved180[181];
unsigned char erased_mem_cont; // initial value after erase //operation
unsigned char reserved182;
unsigned char bus_width; // bus width
unsigned char reserved184;
unsigned char hs_timing; // high speed timing
unsigned char reserved186;
unsigned char pow_class; // power class
unsigned char reserved188;
unsigned char cmd_set_rev; // command set revision
unsigned char reserved190;
unsigned char cmdset; // contains a binary code of the command //set
unsigned char ext_csd_rev; // Extended CSD revision
unsigned char reserved193;
unsigned char csd_struct; // CSD structure field in CSD //register
unsigned char reserved195;
unsigned char card_type; // MMC card type
unsigned char reserved197[3];
unsigned char pwr_cl52195;
unsigned char pwr_cl26195;
unsigned char pwr_cl52360;
unsigned char pwr_cl26360; // supported power class by the //card
unsigned char reserved204;
unsigned char min_perf_r_0426; // min. read performance with //4 bit bus width & 26MHz
unsigned char min_perf_w_0426; // min. write performance //with 4 bit bus width & 26MHz
unsigned char min_perf_r_08260452; // min. read performance //with 8 bit bus width & 26MHz
// min. read performance with 4 bit bus width & 52MHz
unsigned char min_perf_w_08260452; // min. write performance //with 8 bit bus width & 26MHz
// min. write performance with 4 bit bus width & 26MHz
unsigned char min_perf_r_0852; // min. read performance with 8 bit bus width & 52MHz
unsigned char min_perf_w_0852; // min. write performance //with 8 bit bus width & 52MHz
unsigned char reserved211;
unsigned long sec_count; // sector count
unsigned char reserved216[288];
unsigned char cmd_set; // command sets are supported by the //card
unsigned char reserved505[7];
}MMC_PARSED_REGISTER_EXTCSD, *P_MMC_PARSED_REGISTER_EXTCSD;
typedef struct{
u32 sector_cnt;
u32 is_sdhc;
u32 mmc_spec42;
u32 while_ocr_check;
u32 is_sd_spec20;
u32 cmd_retry_cnt;
u32 is_mmc;
u32 rca;
u32 sd_spec;
u32 is_high_speed;
MMC_PARSED_REGISTER_EXTCSD ext_csd_register;
void __iomem * ioaddr;/* Mapped address */
}SDHCI_INFO, *P_SDHCI_INFO;
以备后续查询调用。
再接着复位SD/MMC控制器,开中断等......接着就对设备进行发送命令进行通讯(具体要看它们的通讯协议,目前还不是很懂,将来弄懂了再补上),确认设备的类型(SD/MMC)及版本号.然后进行相应的初始化(具体见其SD/MMC通讯协议).
到这里我们已经掌握了启动设备的基本信息及基本初始化好了这些设备,注意这里是基本初始化好,因为还未对inand分好区,所以只能对其进行简单的读写,即对其块进行操作.
分区从实质上说就是对硬盘的一种格式化。当我们创建分区时,就已经设置好了硬盘的各项物理参数,指定了硬盘主引导记录(即Master Boot Record,一般简称为MBR)和引导记录备份的存放位置。而对于文件系统以及其他操作系统管理硬盘所需要的信息则是通过之后的高级格式化,即Format命令来实现.这是硬盘分区的定义,而inand分区也可用其来说明.
内存和NOR型闪存的基本存储单元是bit,用户可以随机访问任何一个bit的信息。而NAND型闪存的基本存储单元是页(Page)(可以看到,NAND型闪存的页就类似硬盘的扇区,硬盘的一个扇区也为512字节)。每一页的有效容量是512字节的倍数。所谓的有效容量是指用于数据存储的部分,实际上还要加上16字节的校验信息,因此我们可以在闪存厂商的技术资料当中看到“(512+16)Byte”的表示方式。目前2Gb以下容量的NAND型闪存绝大多数是(512+16)字节的页面容量,2Gb以上容量的NAND型闪存则将页容量扩大到(2048+64)字节。
NAND型闪存以块为单位进行擦除操作。闪存的写入操作必须在空白区域进行,如果目标区域已经有数据,必须先擦除后写入,因此擦除操作是闪存的基本操作。
现在来看下inand分区情况,如何实现分区.
首先我们自己要先定义好这些分区该如何划分,如boot放在哪几块,kernel又放在哪几块,还有system、ramdisk、logo等,在这里我们的分区都是以块为单位的,在这里会分配好,每个分区的起始地址(第多少个块)及占用几个块大小.
我们知道一般硬盘都有CHS和LBA模式,这里也不例外,我们需要通过inand的总块数来建立相应的模型(inand总容量大于8G时采用LBA模式否则采用CHS模式).
有点要注意的是,一般分区都是从1块开始,第0块要存放MBR,接着第一块存放mboot.还有一点要注意的是当分区为带文件系统的分区时,需要做出相应的调整.要遵循分区不可跨柱面原则.到这里就把分区这块说完啦,当然只是简单的描述,需要完全弄懂还是需要下一番功夫的.