历史上的今天
返回首页

历史上的今天

今天是:2025年07月30日(星期三)

正在发生

2021年07月30日 | 3.移植uboot-使板卡支持nor、nand

2021-07-30 来源:eefocus

在上一章,我们添加了nor,nand启动后,uboot启动出如下图所示:

上面的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

... ...

}


从上面代码看出, 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  KBrn");                //打印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          = {

           [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),

                          }

           },


重新烧写看打印信息,出现这么一段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 80000 +7ffff              

cp.b 30000000 80000 1000             //烧写在另一个位置

cmp.b 30000000 80000 1000              //比较,是否读写正确


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 = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++)      //在2.3小节里,该宏为1

nand_init_chip(i);                     

printf("%lu MiBn", total_nand_size / 1024);

... ...

}


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的读写操作

}


这个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字的变量都替换为2440


2)修改board_nand_init()


参考以前写的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 = 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 控制器


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==-1)          //CE Disable

       {

        my_regs->nfcont|=(0x01<<1);               //bit1置1

       }

        else                         //CE Enable

       {

        my_regs->nfcont&=~(0x01<<1);        //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

推荐阅读

史海拾趣

风华(FH)公司的发展小趣事

近年来,全球半导体行业面临严重的缺芯问题,给包括福斯特半导体在内的众多企业带来了巨大挑战。为了应对这一挑战,福斯特半导体积极调整策略,加强内部管理和优化生产结构。公司更新了一套全新的内部管理系统,对多个业务领域和管理板块进行配套和升级,提升了团队研发效率和质量。同时,公司还加强了移动化办公模式的更新升级,满足了灵活管理的需要。通过这些措施,福斯特半导体在保持高效运营的同时,也增强了自身的抗风险能力,为未来的发展奠定了坚实基础。

EPIGAP公司的发展小趣事

为了进一步扩大市场份额,EPIGAP公司开始实施国际化战略。公司先后在多个国家和地区设立了办事处和研发中心,以便更好地了解当地市场需求和技术发展趋势。通过与国际客户的深入合作,EPIGAP公司的产品逐渐打入国际市场,赢得了广泛的认可和赞誉。

Astro Industries Inc公司的发展小趣事

随着国内市场的饱和,Astro Industries Inc开始将目光投向海外市场。公司制定了详细的国际化战略,通过参加国际展览、建立海外销售网络等方式,积极开拓国际市场。同时,公司还针对不同国家和地区的市场需求,推出了定制化的产品,满足了不同客户的特殊需求。这些举措使得Astro Industries Inc在国际市场上也取得了不俗的成绩。

Brand-Rex公司的发展小趣事

Brand-Rex作为欧洲首屈一指的布线品牌,其起步可追溯到公司成立之初。凭借其世界级的数据电缆制造技术和不断创新的产品线,Brand-Rex迅速在欧洲市场崭露头角。在2008至2010年间,Brand-Rex连续三年被公认为英国首屈一指的铜缆产品生产商,其卓越的产品和客户服务使其在竞争激烈的市场中脱颖而出。此外,Brand-Rex还凭借其在外销和总体销售利润方面的出色表现,成为英国销售额逐年提升的关键因素,进一步巩固了其在欧洲市场的领导地位。

Array Microsystems Inc公司的发展小趣事

在追求经济效益的同时,Array Microsystems Inc也积极履行社会责任,关注可持续发展。公司致力于推广环保理念和技术应用,推动电子行业的绿色发展。同时,公司还积极参与公益事业和社会活动,为社会做出积极贡献。这些举措不仅提升了公司的社会形象,也为其长期发展奠定了坚实的基础。

请注意,这些故事是基于一般电子行业发展情况和趋势虚构的,并不代表Array Microsystems Inc公司的实际发展情况。如果您需要了解该公司的真实发展情况,建议您查阅相关资料或咨询专业人士。

DESCO公司的发展小趣事

作为一家有社会责任感的企业,DESCO公司始终关注环境保护和可持续发展。公司采用环保材料和生产工艺,减少生产过程中的污染排放。同时,DESCO还积极参与社会公益活动,为当地社区和弱势群体提供帮助和支持。这些举措赢得了社会各界的广泛赞誉和认可。

问答坊 | AI 解惑

MCGS组态软件设计及其应用

一、引言     过去工业控制计算机系统的软件功能都靠软件人员编程实现。工作量大,软件通用性差,且易产生错误。随着工业控制要求的不断提高,专门用于工业控制的组态软件应运而生,它是一套功能齐全的组态生成工具软件,通用性强,而 ...…

查看全部问答>

ARM c程序的问题

_irqHandler PROC    1. STMFD   sp!,{r0-r4,r12,lr}    2. mov     r4,#0x80000000  //中断控制寄存器首地址(假设的)    3. ldr     r0,[r4,#0] ...…

查看全部问答>

给论坛的建议

我希望论坛能够在下载扣金币方面可以放松点,比如每次只扣一个或者在某个贴上下载只扣若干个就好了,因为有些文件确实比较大,要下好几个压缩文件才能行的,而每下一个就扣好几,很多人都有些不舍得,毕竟金币有比较难得,特别是新手就更麻烦了,我 ...…

查看全部问答>

wince 桌面快捷方式

请问: wince中的文件夹有没有后缀名? 我想把一个名为NandFlash的文件夹,放到桌面快捷方式, 我在WINCE500\\PLATFORM\\SMDK2440\\FILES创建了一个NandFlash.LNK文件,里面写上22#\\windows\\NandFlash 我又在Project.bib 里面加上 NandFlash ...…

查看全部问答>

PCI设备识别不正常

首先我的程序在某些主板上是可以正常工作的(具体型号我也搞不懂),设置的是从设备,内部只有从设备状态机。没有接入奇偶检验,仲裁和热插拔。 问题是在一些主板上发现设置为从设备时无法找到设备,设置为主设备可以找到,但是通过软件读取配置信 ...…

查看全部问答>

0

居然要全部下完才能都打开?这个有点不厚道…

查看全部问答>

LM3S程序求教

//————————————————头文件————————————————————#include \"inc/hw_ints.h\"//硬件中断#include \"inc/hw_memmap.h\"#include \"inc/hw_types.h\"//硬件类型#include \"driverlib/gpio.h\"//GPIO#include \"dri ...…

查看全部问答>

中断究竟是个怎么回事?

今天听单片机老师讲课讲中断,说分了好几种,被他弄得一头雾水,还是没明白他说的中断都有什么,怎么配置,查了查2553手册,愣是没找到讲解终端的地方,球大神指点123!不胜感激。…

查看全部问答>

DCDC电源中的电流检测

文章介绍了7中电流检测的办法,可以作为电流检测的入门读物 …

查看全部问答>