代码如下所示(位于arch/arm/lib/board.c),r()里的代码

       
 图片 1

       
 图片 2

上面的Flash: *** failed ***
是属于uboot第叁等级函数board_init_r()里的代码,
代码如下所示(位于arch/arm/lib/board.c):

上面的Flash: *** failed ***
是属于uboot第叁阶段函数board_init_r()里的代码,
代码如下所示(位于arch/arm/lib/board.c):

/*第二阶段*/
void board_init_r(gd_t *id, ulong dest_addr)        //gd    uboot重定位地址
{
     ... ...
  puts("Flash: ");                        //打印flash:
  flash_size = flash_init();                    //初始化nor_flash
  if (flash_size > 0)
  {
       ... ...
       print_size(flash_size, "\n");            //打印nor_flash的大小
  }
  else
  {
    puts(failed);                //打印数组failed[]="*** failed ***\n";
    hang();                        //进入while中,并打印: ### ERROR ### Please RESET the board ###     
  }
#if defined(CONFIG_CMD_NAND)
       puts("NAND:  ");                                      //打印NAND:
       nand_init();                                               //初始化nand_flah
... ...
}
/*第二阶段*/
void board_init_r(gd_t *id, ulong dest_addr)        //gd    uboot重定位地址
{
     ... ...
  puts("Flash: ");                        //打印flash:
  flash_size = flash_init();                    //初始化nor_flash
  if (flash_size > 0)
  {
       ... ...
       print_size(flash_size, "\n");            //打印nor_flash的大小
  }
  else
  {
    puts(failed);                //打印数组failed[]="*** failed ***\n";
    hang();                        //进入while中,并打印: ### ERROR ### Please RESET the board ###     
  }
#if defined(CONFIG_CMD_NAND)
       puts("NAND:  ");                                      //打印NAND:
       nand_init();                                               //初始化nand_flah
... ...
}

从上边代码看出, board_init_r()会来伊始化nor,由于新的uboot不支持nor,所以flash_init()初阶退步,然后打印一串错误代码后,等待复位.

从地点代码看出, board_init_r()会来起首化nor,由于新的uboot不支持nor,所以flash_init()开端失利,然后打字与印刷一串错误代码后,等待复位.

鉴于2440在nand运行时,会自动装载nand的前4k内容,所以不扶助norflash,因为nor的前4k内容被nand占用.

出于2440在nand运营时,会自动装载nand的前4k内容,所以不帮助norflash,因为nor的前4k内容被nand占用.

所以修改上边代码,制止nand运维平昔不通,将:

故而修改下面代码,幸免nand运转一贯不通,将:

else
{
  puts(failed);                //打印数组failed[]="*** failed ***\n";
  hang();                        //进入while中,并打印: ### ERROR ### Please RESET the board ###     
}
else
{
  puts(failed);                //打印数组failed[]="*** failed ***\n";
  hang();                        //进入while中,并打印: ### ERROR ### Please RESET the board ###     
}

改为:

改为:

else
{
  puts("0  KB\r\n");                //打印0 KB
}
else
{
  puts("0  KB\r\n");                //打印0 KB
}

 

 



1.接下来,下章便来修改代码,使uboot支持读写norflash

1.接下来,下章便来修改代码,使uboot支持读写norflash

1.1首先在include/common.h中添加:

1.1首先在include/common.h中添加:

#define DEBUG     //调试模式
#define DEBUG     //调试模式

下一场使用nor运维新的uboot,打字与印刷出调试消息:

下一场使用nor运营新的uboot,打字与印刷出调节和测试消息:

 图片 3

 图片 4

打印出norflash的厂家ID=0xC2,设备ID=0x2249,明显uboot匹配读出的ID未遂.

打印出norflash的厂家ID=0xC2,设备ID=0x2249,显著uboot匹配读出的ID未遂.

搜索JEDEC
PROBE字段,找到位于board_init_r()->flash_init()->flash_detect_legacy():

搜索JEDEC
PROBE字段,找到位于board_init_r()->flash_init()->flash_detect_legacy():

 图片 5

 图片 6

 

 

如上海教室所示,该函数会进入board_init_r()->flash_init()->flash_detect_legacy()->jedec_flash_match(),里面会通过三个ID来合营jedec_table[].

如上图所示,该函数会进去board_init_r()->flash_init()->flash_detect_legacy()->jedec_flash_match(),里面会透过八个ID来合作jedec_table[].

 

 

1.2接下去向jedec_table[]里添加norflash:MT29LV160DB(位于drivers/mtd/jedec_flash.c)

1.2接下去向jedec_table[]里添加norflash:MT29LV160DB(位于drivers/mtd/jedec_flash.c)

代码如下:

代码如下:

     /*MX29LV160DB*/
       {
       .mfr_id         = (u16)MX_MANUFACT,        //厂家ID0x00C200C2 (读nor,便是0xc2)
       .dev_id         = 0x2249,                          //设备ID
       .name           = "MXIC MX29LV160DB",
       .uaddr          = {
           [1] = MTD_UADDR_0x0555_0x02AA /* 数组[1]表示是16位nor,解锁地址为:0x555,0x2AA */
        },
       .DevSize        = SIZE_2MiB,
       .CmdSet         = P_ID_AMD_STD,
       .NumEraseRegions= 4,                      //4种不同的扇区规格
       .regions        = {
       ERASEINFO(16*1024, 1),
       ERASEINFO(8*1024, 2),
       ERASEINFO(32*1024, 1),
       ERASEINFO(64*1024, 31),
                          }
           },
     /*MX29LV160DB*/
       {
       .mfr_id         = (u16)MX_MANUFACT,        //厂家ID0x00C200C2 (读nor,便是0xc2)
       .dev_id         = 0x2249,                          //设备ID
       .name           = "MXIC MX29LV160DB",
       .uaddr          = {
           [1] = MTD_UADDR_0x0555_0x02AA /* 数组[1]表示是16位nor,解锁地址为:0x555,0x2AA */
        },
       .DevSize        = SIZE_2MiB,
       .CmdSet         = P_ID_AMD_STD,
       .NumEraseRegions= 4,                      //4种不同的扇区规格
       .regions        = {
       ERASEINFO(16*1024, 1),
       ERASEINFO(8*1024, 2),
       ERASEINFO(32*1024, 1),
       ERASEINFO(64*1024, 31),
                          }
           },

 

 

重新烧写看打字与印刷新闻,出现那样一段ELacrosseROHighlander:

再度烧写看打印新闻,出现如此一段E福特ExplorerROSportage:

ERROR:too many flash sectors
ERROR:too many flash sectors

说flash的扇区太多了,搜索找到位于drivers/mtd/jedec_flash.c中:

说flash的扇区太多了,搜索找到位于drivers/mtd/jedec_flash.c中:

 图片 7

 图片 8

显然是CONFIG_SYS_MAX_FLASH_SECT宏小于咱们flash的扇区,所以打字与印刷EQX56RO昂Cora。

显然是CONFIG_SYS_MAX_FLASH_SECT宏小于大家flash的扇区,所以打字与印刷E奇骏RO昂科雷。

故此修改CONFIG_SYS_MAX_FLASH_SECT宏定义(位于include/configs/smdk2440.h),并去掉在此以前定义的DEBUG调节和测试宏(位于include/common.h)

由此修改CONFIG_SYS_MAX_FLASH_SECT宏定义(位于include/configs/smdk2440.h),并去掉此前定义的DEBUG调节和测试宏(位于include/common.h)

1.3然后再也烧写

1.3然后再次烧写

输入flinfo命令(flash
info),就能查看flash的音讯了:

输入flinfo命令(flash
info),就能查看flash的消息了:

 图片 9

 图片 10

接下来经过uboot命令,检查和测试nor的读写是不是正确:

接下来通过uboot命令,检测nor的读写是或不是科学:

protect off all 
erase 80000 +7ffff              
cp.b 30000000 80000 1000             //烧写在另一个位置
cmp.b 30000000 80000 1000              //比较,是否读写正确
protect off all 
erase 80000 +7ffff              
cp.b 30000000 80000 1000             //烧写在另一个位置
cmp.b 30000000 80000 1000              //比较,是否读写正确

2.接下来继续修改代码,使uboot支持NandFlash

2.接下来继续修改代码,使uboot辅助NandFlash

2410的NandFlash位于drivers/mtd/nand/s3c2410_nand.c

2410的NandFlash位于drivers/mtd/nand/s3c2410_nand.c

2.1 首先复制s3c2410_nand.c,改为s3c2440_nand.c

2.1 首先复制s3c2410_nand.c,改为s3c2440_nand.c

改Makefile,如下图所示:

改Makefile,如下图所示:

 图片 11

 图片 12

 

 

2.2
在上一章分析过CONFIG_NAND_S3C2410宏,位于include/configs/smdk2440.h:

2.2
在上一章分析过CONFIG_NAND_S3C2410宏,位于include/configs/smdk2440.h:

 图片 13

 图片 14

如上海体育场所所示,此中CONFIG_CMD_NAND宏:表示uboot是或不是帮助nand,在上章里,大家把它屏蔽了,接下去便注销屏蔽CONFIG_CMD_NAND宏。

如上海体育场地所示,个中CONFIG_CMD_NAND宏:表示uboot是或不是协助nand,在上章里,大家把它屏蔽了,接下去便注销屏蔽CONFIG_CMD_NAND宏。

 

 

2.3卫冕增进对CONFIG_NAND_S3C2440宏的帮衬,将:

2.3继续丰裕对CONFIG_NAND_S3C2440宏的支持,将:

#ifdef CONFIG_CMD_NAND
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#define CONFIG_SYS_MAX_NAND_DEVICE  1
#define CONFIG_SYS_NAND_BASE              0x4E000000
#endif
#ifdef CONFIG_CMD_NAND
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#define CONFIG_SYS_MAX_NAND_DEVICE  1
#define CONFIG_SYS_NAND_BASE              0x4E000000
#endif

改为:

改为:

#ifdef CONFIG_CMD_NAND


#ifdef CONFIG_S3C2410          
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#else                                                                   // CONFIG_S3C2440      
#define CONFIG_NAND_S3C2440    
#define CONFIG_SYS_S3C2440_NAND_HWECC
#endif

#define CONFIG_SYS_MAX_NAND_DEVICE      1
#define CONFIG_SYS_NAND_BASE            0x4E000000
#endif
#ifdef CONFIG_CMD_NAND


#ifdef CONFIG_S3C2410          
#define CONFIG_NAND_S3C2410
#define CONFIG_SYS_S3C2410_NAND_HWECC
#else                                                                   // CONFIG_S3C2440      
#define CONFIG_NAND_S3C2440    
#define CONFIG_SYS_S3C2440_NAND_HWECC
#endif

#define CONFIG_SYS_MAX_NAND_DEVICE      1
#define CONFIG_SYS_NAND_BASE            0x4E000000
#endif

由于smdk2410.h中定义的是CONFIG_S3C2410,而smdk2440.h中定义的是CONFIG_S3C2440,所以便会依据地点的#ifdef来动态定义宏

由于smdk2410.h中定义的是CONFIG_S3C2410,而smdk2440.h中定义的是CONFIG_S3C2440,所以便会依据地点的#ifdef来动态定义宏

 

 

2.4
然后来探视nand的流程(和linux的nand驱动有成千成万貌似的地点):

2.4
然后来探视nand的流程(和linux的nand驱动有不少貌似的地点):

1)uboot重一直后跻身第③阶段board_init_r():

1)uboot重一向后进入第壹阶段board_init_r():

void board_init_r(gd_t *id, ulong dest_addr)        //gd    uboot重定位地址
{
  ... ...
#if defined(CONFIG_CMD_NAND)                      //需要定义CONFIG_CMD_NAND宏
       puts("NAND:  ");
       nand_init();            /* go init the NAND */
#endif
 ... ...
}
void board_init_r(gd_t *id, ulong dest_addr)        //gd    uboot重定位地址
{
  ... ...
#if defined(CONFIG_CMD_NAND)                      //需要定义CONFIG_CMD_NAND宏
       puts("NAND:  ");
       nand_init();            /* go init the NAND */
#endif
 ... ...
}

 

 

2)进入nand_init():

2)进入nand_init():

void nand_init(void)
{
... ...
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)      //在2.3小节里,该宏为1
nand_init_chip(i);                     
printf("%lu MiB\n", total_nand_size / 1024);
... ...
}
void nand_init(void)
{
... ...
for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)      //在2.3小节里,该宏为1
nand_init_chip(i);                     
printf("%lu MiB\n", total_nand_size / 1024);
... ...
}

 

 

3)进入nand_init()->nand_init_chip(0):

3)进入nand_init()->nand_init_chip(0):

static void nand_init_chip(int i)
{
    struct mtd_info *mtd = &nand_info[i];      //mtd_info属于软件的一部分,实现用户层读写等操作
    struct nand_chip *nand = &nand_chip[i];     //属于底层,保存对nand的硬件相关操作,它是mtd_info结构体的priv私有成员
    ulong base_addr = base_address[i];           //获取nand寄存器基地址,等于0x4E000000
    int maxchips = CONFIG_SYS_NAND_MAX_CHIPS;

    if (maxchips < 1)
           maxchips = 1;

    mtd->priv = nand;     //设置私有成员nand_chip
    ... ...
    if (board_nand_init(nand))                   //位于s3c2440_nand.c,该函数会设置nand_chip结构体的成员
           return;

    if (nand_scan(mtd, maxchips)) //通过mtd->priv来开启nand片选,来获取nand的型号,类型等.并填充mtd结构体下其它的成员.
           return;

    nand_register(i);     //注册nand,使uboot支持对nand的读写操作
}
static void nand_init_chip(int i)
{
    struct mtd_info *mtd = &nand_info[i];      //mtd_info属于软件的一部分,实现用户层读写等操作
    struct nand_chip *nand = &nand_chip[i];     //属于底层,保存对nand的硬件相关操作,它是mtd_info结构体的priv私有成员
    ulong base_addr = base_address[i];           //获取nand寄存器基地址,等于0x4E000000
    int maxchips = CONFIG_SYS_NAND_MAX_CHIPS;

    if (maxchips < 1)
           maxchips = 1;

    mtd->priv = nand;     //设置私有成员nand_chip
    ... ...
    if (board_nand_init(nand))                   //位于s3c2440_nand.c,该函数会设置nand_chip结构体的成员
           return;

    if (nand_scan(mtd, maxchips)) //通过mtd->priv来开启nand片选,来获取nand的型号,类型等.并填充mtd结构体下其它的成员.
           return;

    nand_register(i);     //注册nand,使uboot支持对nand的读写操作
}

这个nand_chip结构体和我们事先学的linux下的nand驱动章节里的nand_chip一摸一样,流程也越发相似.

这个nand_chip结构体和大家事先学的linux下的nand驱动章节里的nand_chip一摸一样,流程也10分相似.

 由于在2.1小节里,该函数所在的文书s3c2440_nand.c是从s3c2410_nand.c复制过来的,所以接下去便修改s3c2440_nand.c
(位于drivers/mtd/nand目录下)

 由于在2.1小节里,该函数所在的文件s3c2440_nand.c是从s3c2410_nand.c复制过来的,所以接下去便修改s3c2440_nand.c
(位于drivers/mtd/nand目录下)

 

 

2.5
修改s3c2440_nand.c(参考2410数量手册和2440数目手册)

2.5
修改s3c2440_nand.c(参考2410数据手册和2440数量手册)

1)先是将有着带2410字的变量都替换为2440

1)先是将富有带2410字的变量都替换为2440

2)修改board_nand_init()

2)修改board_nand_init()

参考在此之前写的nand驱动,将

参考原先写的nand驱动,将

   tacls = 4;
    twrph0 = 8;
    twrph1 = 8;
    cfg = S3C2440_NFCONF_EN;                       //启动nand控制器
    cfg |= S3C2440_NFCONF_TACLS(tacls - 1);
    cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
    cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
    writel(cfg, &nand_reg->nfconf); 
   tacls = 4;
    twrph0 = 8;
    twrph1 = 8;
    cfg = S3C2440_NFCONF_EN;                       //启动nand控制器
    cfg |= S3C2440_NFCONF_TACLS(tacls - 1);
    cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
    cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
    writel(cfg, &nand_reg->nfconf); 

改为:

改为:

    tacls = 0;                      //10ns    
    twrph0 = 1;                  //20ns
    twrph1 = 0;                  //10ns

    nand_reg->nfconf = (tacls<<12) | (twrph0<<8) | (twrph1<<4); //设置时序
    nand_reg->nfcont=(1<<1)|(1<<0); // bit1:关闭片选(),       bit0:开启nand flash 控制器
    tacls = 0;                      //10ns    
    twrph0 = 1;                  //20ns
    twrph1 = 0;                  //10ns

    nand_reg->nfconf = (tacls<<12) | (twrph0<<8) | (twrph1<<4); //设置时序
    nand_reg->nfcont=(1<<1)|(1<<0); // bit1:关闭片选(),       bit0:开启nand flash 控制器

 

 

3)遮掩带硬件ECC的有关操作

3)遮掩带硬件ECC的相干操作

将:

将:

#ifdef CONFIG_S3C2410_NAND_HWECC
nand->ecc.hwctl = s3c2440_nand_enable_hwecc;
nand->ecc.calculate = s3c2440_nand_calculate_ecc;
nand->ecc.correct = s3c2440_nand_correct_data;
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
#else
nand->ecc.mode = NAND_ECC_SOFT;
#endif
#ifdef CONFIG_S3C2410_NAND_HWECC
nand->ecc.hwctl = s3c2440_nand_enable_hwecc;
nand->ecc.calculate = s3c2440_nand_calculate_ecc;
nand->ecc.correct = s3c2440_nand_correct_data;
nand->ecc.mode = NAND_ECC_HW;
nand->ecc.size = CONFIG_SYS_NAND_ECCSIZE;
nand->ecc.bytes = CONFIG_SYS_NAND_ECCBYTES;
#else
nand->ecc.mode = NAND_ECC_SOFT;
#endif

改为:

改为:

nand->ecc.mode = NAND_ECC_SOFT;               //使用软件ECC 
nand->ecc.mode = NAND_ECC_SOFT;               //使用软件ECC 

 

 

2.6
修改s3c2440_hwcontrol()函数

2.6
修改s3c2440_hwcontrol()函数

改为:

改为:

static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
  struct nand_chip *chip = mtd->priv;       
  struct s3c2440_nand *nand = s3c2440_get_base_nand();   //获取nand寄存器地址

  debug("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);

  if (ctrl & NAND_CTRL_CHANGE) 
   {
     if (ctrl & NAND_CLE)                 // 传输的是命令
        chip->IO_ADDR_W = 0x4E000008;    
        else if (ctrl & NAND_ALE)         // 传输的是地址
        chip->IO_ADDR_W =  0x4E00000C;

     if (ctrl & NAND_NCE)       //启动nCE片选  
             nand->nfcont &= ~(1<<1);
       else                       //否则关闭nCE片选
             nand->nfcont |= (1<<1);
  }
  if (cmd != NAND_CMD_NONE)
   writeb(cmd, chip->IO_ADDR_W);       //发送命令/地址
}
static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
{
  struct nand_chip *chip = mtd->priv;       
  struct s3c2440_nand *nand = s3c2440_get_base_nand();   //获取nand寄存器地址

  debug("hwcontrol(): 0x%02x 0x%02x\n", cmd, ctrl);

  if (ctrl & NAND_CTRL_CHANGE) 
   {
     if (ctrl & NAND_CLE)                 // 传输的是命令
        chip->IO_ADDR_W = 0x4E000008;    
        else if (ctrl & NAND_ALE)         // 传输的是地址
        chip->IO_ADDR_W =  0x4E00000C;

     if (ctrl & NAND_NCE)       //启动nCE片选  
             nand->nfcont &= ~(1<<1);
       else                       //否则关闭nCE片选
             nand->nfcont |= (1<<1);
  }
  if (cmd != NAND_CMD_NONE)
   writeb(cmd, chip->IO_ADDR_W);       //发送命令/地址
}

s3c2440_hwcontrol()函数的ctrl是个标志位:

s3c2440_hwcontrol()函数的ctrl是个标志位:

  • bit[1]==1:
    表示要发送的dat是命令
  • bit[2]==1:
    表示要发送的dat是地方
  • bit[0]==1:表示使能nand ,
    ==0:表示禁止nand
  • bit[1]==1:
    表示要发送的dat是命令
  • bit[2]==1:
    表示要发送的dat是地方
  • bit[0]==1:表示使能nand ,
    ==0:表示禁止nand

(PS:具体可以参见内核的nand_command_lp()函数,它会调用那个cmd_crtl函数来落到实处际效果益
)

(PS:具体能够参照内核的nand_command_lp()函数,它会调用这一个cmd_crtl函数来促作用益
)

 

 

2.7编写翻译烧写

2.7编写翻译烧写

一般来说图所示,能够看看已援助Nand
Flash:

一般来说图所示,能够观察已协助Nand
Flash:

 图片 15

 图片 16

 

 

未完待续,下章便来读书,让uboot协助DM柒仟网卡,便足以透过互连网来传输文件~

未完待续,下章便来读书,让uboot补助DM7000网卡,便能够透过网络来传输文件~

相关文章