经过一周的时间终于在s3c2440上把sdboot给跑起来了。整个任务是在已有的bootloader上(用usb线从pc下载的方式)修改以支持直接从sd卡上拷贝nk.nb0文件到内存并启动。
    有关sd卡驱动和fat fs的实现用了3个文件来实现。sdboot.c为sd的驱动(可理解为pdd)层,主要实现一些对sd控制器的配置以及一些基本sd命令的实现和对sd卡的操作。sdmmc.c实现了从sd卡读取nk并跳到内存去运行的代码(基本可以理解为sd驱动的mdd层)。sdfat.c文件就是实现fat fs的。mdd层通过fatfs来对pdd层操作以实现读取文件。
    在整个过程中遇到了很多问题,现在列举如下:
1)sd卡初始化问题
    配置gpio有关sd的功能:SDCMD, SDDAT[3:0]。
    使能CLKCON中的SDI位。
    时钟以及计算公式:SDIPRE   = PCLK/(CLK)-1;INICLK=300000;SDCLK=24000000; MMCCLK= 15000000
    cmd0-cmd55-cmd41-cmd2-cmd3-cmd7-cmd6-cmd17
2)对sd卡操作问题
    SD卡包括:一个标识寄存器CID,一个相应地址寄存器RCA,一个其他参数寄存器
CSD。
    对sd卡的操作是驱动通过sd controller来发相应的命令以达到读写等操作的:发送命令通过SDICmdCon[7:0]的除了开始2bit:CmdIndex放置要发送的命令号;SDICmdCon[8]开始发送命令来完成的。
    检测卡的插入,直接用中断引脚的电平来判断。
    判断插入的卡是否是sd卡,用命令cmd55和cmd41,因为mmc卡对cmd55不做回应。
    命令9就是获取sd卡中csd寄存器的值的,该值包括很多sd卡的信息,其中就有sd卡的容量。这个值在sd卡接收到cmd9之后会以response的形式存放在sd控制器的SDI Response Register[0,1,2,3]中。在执行cmd9,cmd10等这样的命令的时候,卡的状态应该是不选中的,或直接在执行它们之前发送cmd7(0)不选中卡,不然的话会timeout。
    用cmd17来读取单个block的数据,该命令要带地址参数(该参数通过cmd3命令来获取),然后根据SDIDSTA和SDIFSTA状态值来从sd控制器的SDIDAT寄存器中读出要读的数据。该命令与cmd9相反,在执行它之前要选中卡。读完一个block之后要做一些善后工作,为下次读取做好准备,不然的话checkcmdend就要一直循环了。因为用的是每次都读一个block,并地址要以block对齐,这样就要考虑要读取的地址是否是block对齐的,长度是否够一个block。
    SDIDCON这个数据控制寄存器也很重要,一些对数据的操作形式就是在这里设置的。
3)fat文件系统问题
    根据MBR找到分区表,根据分区表找到该分区MBR[446B+4个分区表(每个16B)+2B结束符)
    分区表中的第9-12字节为该分区的启始地址(单位没sector),第13-16字节为分区的长度(单位也是sector)