上面的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 > )
  {
... ...
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()初始失败,然后打印一串错误代码后,等待复位.

由于2440在nand启动时,会自动装载nand的前4k内容,所以不支持norflash,因为nor的前4k内容被nand占用.

所以修改上面代码,避免nand启动一直卡住,将:

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

改为:

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

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

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

#define DEBUG     //调试模式

然后使用nor启动新的uboot,打印出调试信息:

打印出norflash的厂家ID=0xC2,设备ID=0x2249,显然uboot匹配读出的ID没有成功.

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

如上图所示,该函数会进入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)

代码如下:

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

重新烧写看打印信息,出现这么一段ERROR:

ERROR:too many flash sectors

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

显然是CONFIG_SYS_MAX_FLASH_SECT宏小于我们flash的扇区,所以打印ERROR。

所以修改CONFIG_SYS_MAX_FLASH_SECT宏定义(位于include/configs/smdk2440.h),并去掉之前定义的DEBUG调试宏(位于include/common.h)

1.3然后重新烧写

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

然后通过uboot命令,检测nor的读写是否正确:

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

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

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

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

改Makefile,如下图所示:

 

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

如上图所示,其中CONFIG_CMD_NAND宏:表示uboot是否支持nand,在上章里,我们把它屏蔽了,接下来便取消屏蔽CONFIG_CMD_NAND宏。

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

#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来动态定义宏

2.4 然后来看看nand的流程(和linux的nand驱动有很多相似的地方):

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
... ...
}

2)进入nand_init():

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

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 < )
maxchips = ; 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一摸一样,流程也非常相似.

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

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

1)首先将所有带2410字的变量都替换为

2)修改board_nand_init()

参考以前写的nand驱动,将

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

改为:

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

2)添加nand_chip结构体成员

nand->select_chip=s3c2440_select_chip;             //设置CE  

然后并写一个s3c2440_select_chip()函数

/*nand flash  :CE */

static void s3c2440_select_chip(struct mtd_info *mtd, int chipnr)
{
if(chipnr==-) //CE Disable
{
my_regs->nfcont|=(0x01<<); //bit1置1
}
else //CE Enable
{
my_regs->nfcont&=~(0x01<<); //bit1置0
} }

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

改为:

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

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寄存器地址 if (ctrl & NAND_CLE) // 传输的是命令
nand->nfcmd=cmd;
else // 传输的是地址
nand->nfaddr=cmd;
}

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

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

(PS:具体可以参考内核的nand_command_lp()函数,它会调用这个cmd_crtl函数来实现功能 )

2.7编译烧写

如下图所示,可以看到已支持Nand Flash:

试验nand是否能读写:

nand erase                        //擦除
mw.b 0x55
nand write //将0x55写入nand
nand dump //打印

如下图所示, 可以看到读写nand都没问题

下章便来学习:让uboot支持DM9000网卡,便可以通过网络来传输文件

3.移植uboot-使板卡支持nor、nand的更多相关文章

  1. tiny210(s5pv210)移植u-boot(基于 2014.4 版本号)——NAND 启动

    我们知道 s5pv210启动方式有非常多种,sd卡和nand flash 启动就是当中的两种,前面我们实现的都是基于sd卡启动,这节我们開始实现从nand flash 启动: 从 NAND 启动 u- ...

  2. tiny210(s5pv210)移植u-boot(基于 2014.4 版本号)——NAND 8位硬件ECC

    这节我们实现nand的ecc,保存环境变量到nand flash 中.然后把我们之前的led灯烧写到nand flash 中.开机启动.在 tiny210.h 中定义宏 CONFIG_S5PV210_ ...

  3. 2.移植3.4内核-使内核支持烧写yaffs2

    在上章-制作文件系统,并使内核成功启动jffs2文件系统了 本章便开始使内核支持烧写yaffs2文件系统 1.首先获取yaffs2源码(参考git命令使用详解) cd /work/nfs_root g ...

  4. 移植U-Boot时遇到的问题

    1. 在lowlevel_init过程中,本来想实现一个串口直接打印字符串的过程,编译的时候出现了问题,说是发现代码执行段没有对齐:“unaligned opcodes detected in exe ...

  5. mini2440移植uboot 2014.04(一)

    最新版的uboot添加了很多新功能,我决定在最新版代码基础上重新移植一遍加深理解. 我修改的代码已经上传到github上,地址:https://github.com/qiaoyuguo/u-boot- ...

  6. Linux主机上使用交叉编译移植u-boot到树莓派

    0环境 Linux主机OS:Ubuntu14.04 64位,运行在wmware workstation 10虚拟机 树莓派版本:raspberry pi 2 B型. 树莓派OS: Debian Jes ...

  7. 1.ok6410移植bootloader,移植u-boot,学习u-boot命令

    ok6410移植u-boot 既然是移植u-boot当然首先需要u-boot源码,这里的u-boot代码是由国嵌提供的. 一.配置编译u-boot A. 解压 u-boot 压缩文件 B. 进入解压生 ...

  8. S5PV210之Sate210-F DIY硬件,移植uboot,kernel,android 活动现在已经进入实施阶段吗,欢迎广大网友参与 !

    大家一起来diy 超低价四核的exynos4412或者Cortex A8S5pv210开源开发板 商业版Sate210已经完成了好久了.Sate4412 也已经出来.但是这两个接口非常全,主要是针对企 ...

  9. 关于Yaffs2在u-boot中的支持

    开发板是一块2G的MLC的NandFlash,页大小8k+512,为其移植u-boot到yaffs2这了.以前在Mini2440上移植过2k+64的slc的NandFlash的Yaffs2支持,当然也 ...

随机推荐

  1. java8版本base64加密解密

    首先,先是加密,这里我使用了base64类 try { String asB64 = Base64.getEncoder().encodeToString("http://www.baidu ...

  2. Selenium中如何使用xpath更快定位

    在学习Selenium路上,踩了也不少坑,这是我最近才发现的一个新写法,好吧,"才发现"又说明我做其他事了.对的,我现在还在加班! 开车~~~ 例子:知乎网 标签:Python3. ...

  3. 小随笔:利用Shader实现模型爆炸和沙粒化的效果

    0x00 前言 上一篇小随笔<小随笔:利用Shader给斯坦福兔子长毛和实现雪地效果>中,我和大家聊了聊著名的斯坦福兔子和利用geometry shader实现的一些效果.这篇文章继续沿用 ...

  4. Git 二分调试法,火速定位疑难Bug!

    你一定遇到过,一个很久没修改过的功能,莫名其妙的出现了问题?肉眼查代码.屡逻辑完全找不到问题点?前两天还好好的功能,怎么这个今天就不行了?这两天改动了这么多代码,到底是那一次改动引发的 Bug? 这样 ...

  5. 机房收费系统——转换list泛型时,字段名称不正确应出现故障

    因为之前对泛型研究了一番,所以就開始尝试着在机房收费系统重构中增加了泛型的使用. 可是到了做学生查看剩余金额这个功能的时候,还是依照之前的方法做的,可是在载入数据的时候班级这个框就没有显示出来--然后 ...

  6. KNN K~近邻算法笔记

    K~近邻算法是最简单的机器学习算法.工作原理就是:将新数据的每一个特征与样本集中数据相应的特征进行比較.然后算法提取样本集中特征最相似的数据的分类标签.一般来说.仅仅提取样本数据集中前K个最相似的数据 ...

  7. SSM学习(二)mybatis和spring的集成

    上一篇文章大概搭建了一下ssm的框架,其实还是不完整,我们往项目中添加了spring和mybatis的配置文件,还差一个spring mvc的配置文件,在resource中在新建一个Applicati ...

  8. Linux服务器配置(一)

    Linux服务器配置(一) jdk,tomcat,nginx记录 最近公司买了三台服务器System x3650 M5用来跑公司的项目.现,记录一下真机部署与后期维护历程~ 因为系统是服务器买来就装好 ...

  9. SSH简单项目

    这是我学习SSH整合时的一个测试项目,代码比较简单 整个项目实现从数据库中取数据,在页面上显示.项目的结构如下: (1)数据库设计 数据库使用的是student数据库中的一个数据库表grade,表的内 ...

  10. 【python】函数filter、map