加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

u-boot2010.06的移植(5)——支持nandflash、分区及环境参数的设

发布时间:2020-12-15 07:20:10 所属栏目:百科 来源:网络整理
导读:nandflash应该算是研究了很长时间了,但是还是有的地方没搞懂,有知道的大侠还望不吝键盘。 我用的是K9F2G08U0A,貌似第三节已经介绍过了。在此不费口舌。直接切入重点难点。 在此移植过程中,犯了一个低级的错误,导致我花了半年的时间捣鼓nand(有点夸张哈
nandflash应该算是研究了很长时间了,但是还是有的地方没搞懂,有知道的大侠还望不吝键盘。
我用的是K9F2G08U0A,貌似第三节已经介绍过了。在此不费口舌。直接切入重点难点。
在此移植过程中,犯了一个低级的错误,导致我花了半年的时间捣鼓nand(有点夸张哈 ),马虎害死人啊。
s3c 2440和s3c2410的nand寄存器不一样,需要拿两者的芯片对照修改。寄存器不一样导致了底层寄存器操作不一样。需要修改其底层函数。主要修改的初始化函数和读写 控制?函数。
初始化函数:对于下面的代码,需要注意的是局部变量cfg的初始化,因为cfg要被写入NFCONF寄存器中,若不初始化,根据c语言知识,他会是一个不确定的数,写入寄存器的话会干扰寄存器其他位。

点击(此处)折叠或打开

  1. int board_nand_init(struct nand_chip *nand)
  2. {
  3. ????u_int32_t cfg = 0;
  4. ????u_int8_t tacls, twrph0, twrph1;
  5. ????struct s3c24x0_clock_power *clk_power = s3c24x0_get_base_clock_power();
  6. ????struct s3c2440_nand *nand_reg = s3c2440_get_base_nand();

  7. ????debugX(1, "board_nand_init()n");

  8. ????writel(readl(&clk_power->CLKCON) | (1 << 4), &clk_power->CLKCON);

  9. ????/* initialize hardware */
  10. ????twrph0 = 4;
  11. ????twrph1 = 2;
  12. ????tacls = 2;

  13. ? ? writel((1<<4)|(0<<1)|(1<<0), &nand_reg->NFCONT);
  14. ????
  15. ????cfg |= S3C2440_NFCONF_TACLS(tacls - 1);
  16. ????cfg |= S3C2440_NFCONF_TWRPH0(twrph0 - 1);
  17. ????cfg |= S3C2440_NFCONF_TWRPH1(twrph1 - 1);
  18. ????writel(cfg, &nand_reg->NFCONF);

  19. ????/* initialize nand_chip data structure */
  20. ????nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)&nand_reg->NFDATA;

  21. ????nand->select_chip = nand_select;
  22. ? ? ... ...
  23. }

读写控制函数:其核心代码如下(修改后):

点击(此处)折叠或打开

  1. static void s3c2440_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
  2. {
  3. ????//struct nand_chip *chip = mtd->priv;
  4. ????struct s3c2440_nand *nand = s3c2440_get_base_nand();

  5. ????debugX(1, "hwcontrol(): 0x%02x 0x%02xn", cmd, ctrl);
  6. ????
  7. ????//IO_ADDR_W = (ulong)nand;
  8. ????if (ctrl & NAND_CTRL_CHANGE) {
  9. ????????//ulong IO_ADDR_W = (ulong)nand;
  10. ????????IO_ADDR_W = (ulong)nand;
  11. ????????if (ctrl & NAND_CLE)
  12. ????????????IO_ADDR_W |= S3C2440_ADDR_NCLE;
  13. ????????if (ctrl & NAND_ALE)
  14. ????????????IO_ADDR_W |= S3C2440_ADDR_NALE;

  15. ????????//chip->IO_ADDR_W = (void *)IO_ADDR_W;

  16. ????????if (ctrl & NAND_NCE)
  17. ????????????writel(readl(&nand->NFCONT) & ~S3C2440_NFCONT_nFCE,
  18. ???????????? &nand->NFCONT);
  19. ????????else
  20. ????????????writel(readl(&nand->NFCONT) | S3C2440_NFCONT_nFCE,
  21. ???????????? &nand->NFCONT);
  22. ????}

  23. ????if (cmd != NAND_CMD_NONE)
  24. ????????writeb(cmd, (void *)IO_ADDR_W);
  25. }
稍加分析,非常简单,但越是觉得简单就越想不到会在这里出错。代码写的少,导致的后果就是运用其规则的不熟练。
2410的原始代码是这样的:

点击(此处)折叠或打开

  1. static void s3c2410_hwcontrol(struct mtd_info *mtd, unsigned int ctrl)
  2. {
  3. ????struct nand_chip *chip = mtd->priv;
  4. ????struct s3c2410_nand *nand = s3c2410_get_base_nand();

  5. ????debugX(1, ctrl);

  6. ????if (ctrl & NAND_CTRL_CHANGE) {
  7. ????????ulong IO_ADDR_W = (ulong)nand;

  8. ????????if (!(ctrl & NAND_CLE))
  9. ????????????IO_ADDR_W |= S3C2410_ADDR_NCLE;
  10. ????????if (!(ctrl & NAND_ALE))
  11. ????????????IO_ADDR_W |= S3C2410_ADDR_NALE;

  12. ????????chip->IO_ADDR_W = (void *)IO_ADDR_W;/* BUG!因为涉及到后续的芯片的读写数据,而此处nand的写地址指向的是命令寄存器
  13. ????????????????????????????????????????? ? ?*或地址寄存器,而写数据要写到数据缓冲区中,之后写数据可能会写错寄存器*/?
  14. ????????if (ctrl & NAND_NCE)
  15. ????????????writel(readl(&nand->NFCONF) & ~S3C2410_NFCONF_nFCE,
  16. ???????????? &nand->NFCONF);
  17. ????????else
  18. ????????????writel(readl(&nand->NFCONF) | S3C2410_NFCONF_nFCE,
  19. ???????????? &nand->NFCONF);
  20. ????}

  21. ????if (cmd != NAND_CMD_NONE)
  22. ????????writeb(cmd, chip->IO_ADDR_W);
  23. }
需要注意的是临时变量IO_ADDR_W?=?(ulong)nand 的位置。我刚开始就是写到我注释的地方导致的错误。导致的错误可能是全部都是坏块:
Skipping bad block at ?0x00000000 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
Skipping bad block at ?0x00020000 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
Skipping bad block at ?0x00040000 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
Skipping bad block at ?0x00060000 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
Skipping bad block at ?0x00080000 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
Skipping bad block at ?0x000a0000 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
Skipping bad block at ?0x000c0000 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
Skipping bad block at ?0x000e0000 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
Skipping bad block at ?0x00100000 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
Skipping bad block at ?0x00120000
... ...

出现此现象的原因还不是很清楚,没有查到什么样的具体操作会导致这个。只能先暂时总结下出现此现象的解决办法了:
1、网上说的,nand scrub。
2、刚才我说的,底层函数不对。
3、环境参数不对。在配置文件smdk2440.h中,有几个关于环境参数的宏,定义了环境参数的保存地址,用于执行saveenv时保存在flash的一块区域中。通过查找 do_saveenv()函数,可知道,如果要环境参数保存在nor中,要定义
#define CONFIG_ENV_IS_IN_FLASH 1 以及相关的宏,如果环境参数要保存在nand中,就定义#define CONFIG_ENV_IS_IN_NAND 1 以及相关函数。
暂时修改为下:

#define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + 0x070000) /* addr of environment */
#define CONFIG_ENV_IS_IN_FLASH 1
#define CONFIG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */
将上述宏改为
#define CONFIG_ENV_IS_IN_NAND 1 #define CONFIG_CMD_SAVEENV #define CONFIG_ENV_OFFSET 0X40000 #define CONFIG_ENV_RANGE CONFIG_ENV_OFFSET #define CONFIG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */ 之所以说“暂时”是因为还没有给nand分区,所以还不能执行saveenv命令,因为执行saveenv可能会破坏代码的结构。shell中查看分析信息用mtdparts,u-boot还没此命令,需要在源码里添加,具体的添加过程比较简单,略了。分区信息如下: 256k(u-boot),128k(params),4m(kernel),-(rootfs) 仅供参考。 分区完后再裁剪(这个u-boot已经很小了,也就没裁剪),才能设置环境参数的这几个宏。可以计算得到,存放参数的这块区域起始地址以及大小。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读