bootloader查询启动参数search_params

K9F1208硬件连接图

 

K9F1208 的硬件连接图

RnB: 低电平时,表明某个写入、读写或擦除操作正在进行。完成后,恢复高电平。

CLE: 命令锁存;

ALE: 地址锁存;

NFCE: 芯片使能。

 

Samsung K9F1208U0B   NAND  Flash ,存储容量为 64MByte × 8Bit 3.3V 供电。

操作模式:先擦除,再写。擦除以块为单位,读写以页 ( 扇区 ) 为单位。

K9F1208U0B: 4096 块,   16K 512 Bytes/ 块;

                             1 块,   32 页,    512 16 Bytes/ 页。

1 个存储器器件 =528Bytes × 32 页× 4096 = 64MBytes 2048KBytes( 作为备用 )

      

       528 字节一页的写操作所需时间的典型值是 200µs ,而对 16K 字节一块的擦除操作典型值也仅需 2ms 。每一页中的数据读出速度也很快,平均每个字节只需 50ns ,已经与一般的 SRAM 相当。

           8 I/O 端口采用地址、数据和命令复用的方法。这样既可以减少引脚数,还可使接口电路简洁。

 

启动代码

i = search_params();

if(!i)

       Uart_Printf("Found boot params/n");

else if(i==-1)

  {

              Uart_Printf("Fail to found boot params!/n");

              save_params();

}

else if(i==-2)

              Uart_Printf("Fail to read EEPROM!/n");

 

 

search_params

<1>InitNandFlash 初始化 Nand   Flash

1、  InitNandCfg 初始化 Nand Flash 配置 时钟等等

2、  ReadChipId   读取 flash ID      返回 ID

(1) 使能 Flash 配置   NFChipEn     (rNFCONT &= ~(1<<1))

(2) 写命令 ID    (rNFCMD = (0x90)   命令设置寄存器

(3) 写地址 (rNFADDR = (0x00))           地址设置寄存器

(4) 等待 flash 空闲,判断状态寄存器的第 0   0 繁忙   1 空闲 , 准备好

flash 繁忙状态下是不能进行读写操作的 等待空闲状态

(5) 读取数据寄存器的值 保存 ID ID 16 位的双字节数据

id  = RdNFDat()<<8;

    id |= RdNFDat();

(6) 禁止 Flash  NFChipDs   (rNFCONT |= (1<<1))

(7) 返回 ID

3 、判读返回的 ID    注: K9S1208 ID 号为 0xEC76

if((i==0x9873)||(i==0xec75))

           NandAddr = 0;

    else if(i==0xec76)

           NandAddr = 1;

else {

           if(info)   

                  puts("Chip id error!!!/n");

           have_nandflash = 0;// 读取 ID 失败

return;

    }

have_nandflash = 1  // 读取 ID 成功

 

<2>InitNandFlash 之后 判读 have_nandflash 的值 确定 ID 是否正确读取

1 、如果 ID 读写正确    

page = NandPart[0].offset>>9; // 偏移地址除以 512 地址   第几页,每页有 512 字节

           page_cnt = NandPart[0].size>>9;  // 空间大小除以 512 ,共有几页,每页有 512 字节

 

注:

struct Partition {

                     U32 offset ;

                     U32 size;

                     char *name;

};

static struct Partition NandPart [] = {

       {0,           0x00030000, "boot"},         //192K

       {0x00030000, 0x001d0000, "kernel"}, //1856K

       {0x00200000, 0x01e00000, "rootfs"},  //30M

       {0x02000000, 0x02000000, "ext-fs1"},       //32M

       {0,                 0         , 0}

};

 

 

              while(page_cnt--) {

              ReadPage(page+page_cnt, dat);// 读一页中的数据 放在 dat 512 字节数据

              if(!strncmp(boot_params.start.flags, pBP->start.flags, 10)) // 判断 10 个字符是否相同

  {

                            ret = 0;

                            break;

                     }

 

ReadPage(U32 addr, U8 *buf) 读一页中的数据        地址,读出的数据要存放的地址

(1)    使能 Flash

(2)    写命令 WrNFCmd(0x00);

(3)    写地址 WrNFAddr(0);

(4)    addr 地址的低八位

(5)    addr 地址的高八位

(6)    如果 NandAddr=1 K9S1208  addr 地址的高十六位 32 位的地址

(7)    使能 ECC   (rNFCONT |= (1<<4))

(8)    等待空闲状态

(9)    把数据寄存器的数据放入缓冲区中,以页为单位读

for(i=0; i<512; i++)

buf[i] = RdNFDat();

/     (10) 关闭 Flash

2、  如果读取 ID 不正确

memcpy(dat, (void *)(NOR_PARAMS_OFFSET), 512); //MMU 没有设置 就用 original 地址     if(!strncmp(boot_params.start.flags, pBP->start.flags, 10)) // 拷贝启动标志位参数

                  ret = 0;

<3> 禁止 Flash     DsNandFlash();   (rNFCONT &= ~1)

<4> 如果前边都完成没有问题 ret=0; 否则 ret= -1;

// boot_params 的数据放入到 BootParams

if(!ret) {

              ParamItem *pPIS = &pBP->start, *pPID = &boot_params.start;

              for(; pPID<=&boot_params.user_params; pPIS++, pPID++)// 一个个比较个数

// 判读 flags 个数是否相同 若相同,返回 0 小于返回负数,否则返回正数

                    if(!strncmp(pPID->flags, pPIS->flags, sizeof(pPID->flags)))

                            pPID->val = pPIS->val;// 把数据给了 pPID->val

 

// pPIS->flags 中的数据 , 启动参数,复制到 boot_params.string

               strncpy(boot_params.string, pPIS->flags, boot_params.user_params.val+1);

// boot_params.user_params.val 定义为 {"userpara", sizeof(DEFAULT_USER_PARAMS)}, 若个数不对,清除刚才复制的数据 user 值赋 0

               if(boot_params.user_params.val!=strlen(pPID->flags))

{

                    memset(boot_params.string, 0, sizeof(boot_params.string));

                    boot_params.user_params.val = 0;

           }

    }

else

{

           //printf("Fail to find boot params! Use Default parameters./n");

           //don't printf anything before serial initialized!

    }

 

 

注:

typedef struct {

    char flags[12];

    unsigned int val;

} ParamItem ;

 

    typedef struct {

    ParamItem start;

    ParamItem cpu_clk;

    ParamItem boot_delay;

    ParamItem serial_sel;

    ParamItem serial_baud;

    ParamItem machine;

    ParamItem run_addr;

    ParamItem root_sel;

    ParamItem tty_sel;

    ParamItem initrd_addr;

    ParamItem initrd_len;

    ParamItem mem_cfg;

    ParamItem devfs_sel;

    ParamItem osstor;

    ParamItem user_params;

    char string[128];

} BootParams

 

// 小于等于 512 个字节 , 最多保存 24 ITEM 128 字节用户定义的字符串

BootParams boot_params = {

    {"bootpara", 1},     //0=boot without parameters,1=boot with parameters

    {"cpuclk",   2},    //0=200M, 1=300M, 2=400M, 3=440M

    {"rundelay", 0},     //0 seconds

    {"serial",   1},      //0=serial port 0, 1=serial port 1

    {"baudrate", 115200},// 波特率

    {"machine",  193},

    {"runAddr",  0x30400000},

    {"rootfs",   0},

    {"tty",      1},

    {"initrdA",  0},

    {"initrdL",  0},

    {"memsize",  0x04000000},

    {"devfs",    1},

    {"ostore",   0},    //0=nand, 1=nor

    {"userpara", sizeof(DEFAULT_USER_PARAMS)},

    DEFAULT_USER_PARAMS

};

 

 

///

作者:宇帆 cfanlwn

时间:2010-01-19  15:34:21


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值