历史上的今天
返回首页

历史上的今天

今天是:2025年03月10日(星期一)

正在发生

2020年03月10日 | TX2440 ARM开发板Uboot移植(三、添加Nand Flash的有关操作支持)

2020-03-10 来源:eefocus

在上一节中我们说过,通常在嵌入式bootloader中,有两种方式来引导启动内核:从Nor Flash启动和从Nand Flash启动,但不管是从Nor启动或者从Nand启动,进入第二阶段以后,两者的执行流程是相同的。当u-boot的start.S运行到“_start_armboot: .word start_armboot”时,就会调用lib_arm/board.c中的start_armboot函数,至此u-boot正式进入第二阶段。此时注意:以前较早的u-boot版本进入第二阶段后,对Nand Flash的支持有新旧两套代码,新代码在drivers/nand目录下,旧代码在drivers/nand_legacy目录下,CFG_NAND_LEGACY宏决定了使用哪套代码,如果定义了该宏就使用旧代码,否则使用新代码。但是现在的u-boot版本对Nand的初始化、读写实现是基于最近的Linux内核的MTD架构,删除了以前传统的执行方法,使移植没有以前那样复杂了,实现Nand的操作和基本命令都直接在drivers/mtd/nand目录下(在doc/README.nand中讲得很清楚)。下面我们结合代码来分析一下u-boot在第二阶段的执行流程:


1.lib_arm/board.c文件中的start_armboot函数调用了drivers/mtd/nand/nand.c文件中的nand_init函数,如下:
  #if defined(CONFIG_CMD_NAND)      //可以看到CONFIG_CMD_NAND宏决定了Nand的初始化
      puts ("NAND: ");
      nand_init();
  #endif
2.nand_init调用了同文件下的nand_init_chip函数;
3.nand_init_chip函数调用cpu/arm920t/s3c24x0/nand.c文件下的board_nand_init函数,然后再调用drivers/mtd/nand/nand_base.c函数中的nand_scan函数;
4.nand_scan函数调用了同文件下的nand_scan_ident函数等。


因为2440和2410对nand控制器的操作有很大的不同,所以s3c24x0/nand.c下对nandflash操作的函数就是我们做移植需要实现的部分了,他与具体的Nand Flash硬件密切相关。

1、修改 cpuarm920ts3c24x0nand.c 文件内容为:

#include
#if defined(CONFIG_CMD_NAND) && !defined(CFG_NAND_LEGACY)
#include
#if defined(CONFIG_S3C2410)
#include
#define S3C2410_NFSTAT_READY    (1<<0)
#define S3C2410_NFCONF_nFCE     (1<<11)
/* select chip, for s3c2410 */
static void s3c2410_nand_select_chip(struct mtd_info *mtd, int chip)
{
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
    if (chip == -1) {
        s3c2410nand->NFCONF |= S3C2410_NFCONF_nFCE;
    } else {
        s3c2410nand->NFCONF &= ~S3C2410_NFCONF_nFCE;
    }
}

static void s3c2410_nand_hwcontrol(struct mtd_info *mtd, int cmd)
{
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
    struct nand_chip *chip = mtd->priv;

    switch (cmd) {
    case NAND_CTL_SETNCE:
    s3c2410nand->NFCONF &= ~S3C2410_NFCONF_nFCE;
    case NAND_CTL_CLRNCE:
    s3c2410nand->NFCONF |= S3C2410_NFCONF_nFCE;
        printf("%s: called for NCEn", __FUNCTION__);
        break;
    case NAND_CTL_SETCLE:
        chip->IO_ADDR_W = (void *)&s3c2410nand->NFCMD;
        break;
    case NAND_CTL_SETALE:
        chip->IO_ADDR_W = (void *)&s3c2410nand->NFADDR;
        break;
        /* NAND_CTL_CLRCLE: */
        /* NAND_CTL_CLRALE: */
    default:
        chip->IO_ADDR_W = (void *)&s3c2410nand->NFDATA;
        break;
    }
}

/* s3c2410_nand_devready()
 *
 * returns 0 if the nand is busy, 1 if it is ready
 */
static int s3c2410_nand_devready(struct mtd_info *mtd)
{
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
    return (s3c2410nand->NFSTAT & S3C2410_NFSTAT_READY);
}
#elif defined(CONFIG_S3C2440)
#include
#define S3C2440_NFSTAT_READY    (1<<0)
#define S3C2440_NFCONT_nFCE     (1<<1)
/* select chip, for s3c2440 */
static void s3c2440_nand_select_chip(struct mtd_info *mtd, int chip)
{
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
    if (chip == -1) {
        s3c2440nand->NFCONT |= S3C2440_NFCONT_nFCE;
    } else {
        s3c2440nand->NFCONT &= ~S3C2440_NFCONT_nFCE;
    }
}

/* command and control functions */
static void s3c2440_nand_hwcontrol(struct mtd_info *mtd, int cmd)
{
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
    struct nand_chip *chip = mtd->priv;

    switch (cmd) {
    case NAND_CTL_SETNCE:
    s3c2440nand->NFCONT &= ~S3C2440_NFCONT_nFCE;
    case NAND_CTL_CLRNCE:
    s3c2440nand->NFCONT |= S3C2440_NFCONT_nFCE;
        printf("%s: called for NCEn", __FUNCTION__);
        break;
    case NAND_CTL_SETCLE:
        chip->IO_ADDR_W = (void *)&s3c2440nand->NFCMD;
        break;
    case NAND_CTL_SETALE:
        chip->IO_ADDR_W = (void *)&s3c2440nand->NFADDR;
        break;
        /* NAND_CTL_CLRCLE: */
        /* NAND_CTL_CLRALE: */
    default:
        chip->IO_ADDR_W = (void *)&s3c2440nand->NFDATA;
        break;
    }
}

/* s3c2440_nand_devready()
 *
 * returns 0 if the nand is busy, 1 if it is ready
 */
static int s3c2440_nand_devready(struct mtd_info *mtd)
{
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
    return (s3c2440nand->NFSTAT & S3C2440_NFSTAT_READY);
}
#endif
/*
 * Called by drivers/nand/nand.c, initialize the interface of nand flash
 */
int board_nand_init(struct nand_chip *chip)
{
#define TACLS   0
#define TWRPH0  4
#define TWRPH1  2
#if defined(CONFIG_S3C2410)
    S3C2410_NAND * const s3c2410nand = S3C2410_GetBase_NAND();
  /* Enable NAND flash controller, Initialize ECC, enable chip select, Set flash memory timing */
  s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0); 
    chip->IO_ADDR_R    = (void *)&s3c2410nand->NFDATA;
    chip->IO_ADDR_W    = (void *)&s3c2410nand->NFDATA;
    chip->hwcontrol    = s3c2410_nand_hwcontrol;
    chip->dev_ready    = s3c2410_nand_devready;
    chip->select_chip  = s3c2410_nand_select_chip;
#elif defined(CONFIG_S3C2440)
    S3C2440_NAND * const s3c2440nand = S3C2440_GetBase_NAND();
    s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
    /* Initialize ECC, enable chip select, NAND flash controller enable */
    s3c2440nand->NFCONT = (1<<4)|(0<<1)|(1<<0);
    chip->IO_ADDR_R    = (void *)&s3c2440nand->NFDATA;
    chip->IO_ADDR_W    = (void *)&s3c2440nand->NFDATA;
    chip->hwcontrol    = s3c2440_nand_hwcontrol;
    chip->dev_ready    = s3c2440_nand_devready;
    chip->select_chip  = s3c2440_nand_select_chip;
#endif
    chip->options      = 0;
    chip->eccmode       = NAND_ECC_SOFT;
  return 0;
}
#endif

2、修改文件 include/s3c2440.h ,将S3C2410_GetBase_NAND修改为 S3C2440_GetBase_NAND;仿照S3C2410_GetBase_NAND函数(96行)定义2440的函数:

static inline S3C2440_NAND * const S3C2440_GetBase_NAND(void)
{
    return (S3C2440_NAND * const)S3C2440_NAND_BASE;
}

重新编译u-boot并下载到Nand Flash中,把开发板调到Nand档从Nand启动。现在u-boot已经对我们开发板上256M的Nand Flash完全支持了。Nand相关的基本命令也都可以正常使用了。


3、将环境变量存储到Nand Flash中

从上面的启动信息看,有一个警告信息“*** Warning - bad CRC or NAND, using default environment”,这是因为没有将u-boot的环境变量保存nand中的缘故。u-boot在默认的情况下把环境变量都是保存到Nor Flash中的,所以要修改代码,让他保存到Nand中。修改 include/configs/smdk2440.h 文件:

/* 配置环境变量存放设置 */
#define CFG_ENV_ADDR  (CFG_FLASH_BASE + 0x100000) /* 使用NorFlash时,环境变量存放的开始地址 */
//#define  CFG_ENV_IS_IN_FLASH 1                    /* 环境变量保存的位置在NorFlash  */
#define CFG_ENV_IS_IN_NAND 1                        /*  环境变量保存的位置在NandFlash  */
#define CFG_ENV_OFFSET 0x60000                   /* 使用NandFlash时,环境变量存放的偏移地址 */
#define CFG_ENV_SIZE  0x20000               /*Total Size of Environment Sector;一般设定为NandFlash的一个Sector的大小*/

4、最后编译u-boot,生成u-boot.bin文件。将u-boot.bin下载到开发板的Nand Flash中,再把开发板调到Nand启动档,保存环境变量后重启开发板,那条警告信息现在没有了。

推荐阅读

史海拾趣

AAEON公司的发展小趣事

AAEON公司是一家总部位于台湾的全球性电子公司,专注于提供嵌入式计算解决方案和人工智能应用平台。以下是关于该公司发展的五个相关故事:

  1. 公司成立和初期发展: AAEON公司成立于1992年,最初主要从事电脑主板的设计和生产。公司在成立初期致力于提供高质量、高性能的计算解决方案,迅速在台湾本地市场建立了良好的声誉。

  2. 技术创新和产品多样化: 随着技术的发展和市场需求的变化,AAEON开始进行技术创新,并逐步扩展产品线。公司不仅持续改进和推出新型的嵌入式计算产品,还积极涉足人工智能领域,开发智能边缘计算平台和解决方案。

  3. 国际市场拓展: 为了进一步扩大业务规模,AAEON积极拓展国际市场。公司与全球各地的合作伙伴建立了广泛的合作关系,产品销售网络覆盖了亚洲、欧洲、北美和其他地区。公司还在一些国家设立了分支机构和办事处,加强了对当地市场的开拓和服务。

  4. 合作伙伴关系和生态系统建设: AAEON与众多的合作伙伴建立了紧密的合作关系,共同推动产品的创新和市场拓展。公司与主流的芯片厂商、系统集成商、软件开发商等建立了长期稳定的合作关系,共同打造了完善的生态系统。

  5. 未来展望和发展方向: AAEON将继续致力于技术创新和产品升级,加强在嵌入式计算和人工智能领域的领先地位。公司将不断推出符合市场需求的新产品和解决方案,为客户提供更优质的服务和支持。同时,AAEON将继续加强与合作伙伴之间的合作,共同推动行业的发展和进步。

Greenray Industries Inc公司的发展小趣事

为了加速绿色技术的推广和应用,GreenTech积极寻求与全球知名企业的战略合作。例如,公司与一家国际领先的电动汽车制造商达成合作协议,共同研发用于电动汽车的高效电池管理系统。通过这一合作,GreenTech不仅提升了自身在电池技术领域的竞争力,还成功将绿色技术应用于实际产品中,推动了电动汽车行业的绿色发展。

AIRPAX公司的发展小趣事

AIRPAX的故事始于一个对电气保护和传感器技术充满热情的团队。在20世纪初,电气技术的快速发展为各种行业带来了巨大的变革。看到这一机遇,AIRPAX的创始人在美国马萨诸塞州的阿特波罗创立了这家公司,专注于传感器、电气保护器和控制器的设计与制造。最初,AIRPAX的产品主要服务于本地的小规模工业应用,但凭借其卓越的性能和可靠性,很快赢得了市场的认可。

Amecon Magnetics公司的发展小趣事

随着电子行业的快速发展,对高性能磁性材料的需求日益增长。Amecon Magnetics公司敏锐地捕捉到这一市场机遇,加大了在技术研发上的投入。通过不断的技术创新,公司成功开发出一系列具有高性能、高稳定性的磁性材料产品,满足了市场对于高质量磁性材料的需求,从而赢得了客户的信任和市场的认可。

常忆科技(CHINGIS)公司的发展小趣事

常忆科技股份有限公司,始创于1995年,总部位于台湾。在电子行业的发展历程中,常忆科技以其专注于IC设备制造领域的执着和创新能力,逐渐崭露头角。公司成立之初,便致力于开发P型晶体管非挥发性内存,由pFlash和pFusion两个事业单位组成,分别负责不同方面的工作。pFlash专注于开发和生产标准型NOR内存,而pFusion则负责向晶圆代工厂及IC设计公司提供嵌入式非挥发内存的生产技术及知识产权,并提供定制化设计及技术咨询服务。

随着消费电子产品、电脑及周边设备、无线通讯和网络装置等领域的快速发展,常忆科技的产品得到了广泛应用。公司凭借其卓越的技术和产品质量,逐渐在市场上占据了一席之地,为后续的蓬勃发展奠定了坚实基础。

芯力微(CHI Power)公司的发展小趣事

随着公司业务的不断拓展,芯力微逐渐将目光投向国际市场。公司积极参与国际交流与合作,与国际知名企业建立了良好的合作关系。通过引进国际先进技术和管理经验,芯力微不断提升自身的核心竞争力。同时,公司还积极参加国际展会和论坛等活动,展示自身实力和产品优势,为国际化战略的实施奠定了坚实的基础。

问答坊 | AI 解惑

dac0832与lm324输出问题?帮忙看一下!!

本帖最后由 dontium 于 2015-1-23 11:32 编辑 电路如图!!我用的单电源供电,lm324没用的管脚是悬空的!不知道有没影响。问题是输出最大只有1.6V,而我的程序结果应该是0到5v 就算不能满量程也该在5V附近吧!!大侠们 帮忙看下吧!!谢了!!dac0 ...…

查看全部问答>

zigbee中语音的问题

最近小弟正在做一个利用zigbee协议的无线语音通信的东东,碰到了一些问题,例如在zigbee协议的home_automation_profile已经有了关于light、Closures等的ID,那关于voice的是不是自己定义一个值就行了?    麻烦这一领域里的师兄师姐帮助 ...…

查看全部问答>

关于vxwoks中zbuf的问题

前几天,在跑程序的时候遇到一个zbuf的异常,vxworks打印的调用链如下: data storage Exception current instruction address: 0x0050cb60 Machine Status Register: 0x00029230 Data Exception Address Register: 0x0069bf38 Condition Regi ...…

查看全部问答>

ARM7/9的flash然后实现加密?

据我所知,flash里面的程序可以通过编程器将其读出,这样不是很容易被别人盗取吗? 现在是否有什么好办法呢?…

查看全部问答>

啟動代碼的問題

LM每種型號芯片的啟動代碼一樣嗎?? 如果不同,編寫驅動代碼應該參照什麽? 各種啟動代碼裡面的地址如何確定???????? 各位大俠說說看…

查看全部问答>

Linux的开发软件SldView 谁有啊,能否给我发一下,不胜感激

想做Linux开发,在网上找了下 发现开发包都不是很好找 望大虾有的话能够发一下 先行谢过 qq:175232683…

查看全部问答>

【TI文献】智能能源规范 (Smart Energy Profile) 解决方案

智能能源规范 (Smart Energy Profile) 解决方案,欢迎大家下载!…

查看全部问答>

电源类的题目准备哪些元器件

本帖最后由 paulhyde 于 2014-9-15 03:38 编辑 各位大神,能分享一下你们的经验吗,你觉得今年的带赛题,电源类的应该准备那些元器件,最要有具体的型号,谢谢分享    …

查看全部问答>