基于smdk2410 开发板u-boot-1.2.0 nand flash读写操作及其命令的实现(续)

基于smdk2410 开发板u-boot-1.2.0 nand flash读写操作及其命令的实现

 

 4.     u-boot-1.2.0nand flash命令的支持及其实现

4.1.  u-boot支持nand flash的命令

"nand    - legacy NAND sub-system\n",

"info  - show available NAND devices\n"

"nand device [dev] - show or set current device\n"

"nand read[.jffs2[s]]  addr off size\n"

"nand write[.jffs2] addr off size - read/write `size' bytes starting at offset `off' to/from memory address `addr'\n"

"nand erase [clean] [off size] - erase `size' bytes from offset `off' (entire device if not specified)\n"

"nand bad - show bad blocks\n"

"nand read.oob addr off size - read out-of-band data\n"

"nand write.oob addr off size - read out-of-band data\n"

 

4.2.  涉及文件

include/cmd_confdefs.h

include/command.h

common/command.c

include/configs/smdk2410.h

 

4.3.  具体分析

U-Boot的每一个命令都是通过U_Boot_CMD宏定义的。这个宏在include/command.h头文件中定义,每一个命令定义一个cmd_tbl_t结构体。

 

#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \

cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}

 

这样每一个U-Boot命令有一个结构体来描述。结构体包含的成员变量:命令名称、最大参数个数、重复数、命令执行函数、用法、帮助。

从控制台输入的命令是由common/command.c中的程序解释执行的。find_cmd()负责匹配输入的命令,从列表中找出对应的命令结构体。

 

定义nand命令。在include/cmd_confdefs.h中定义了所有U-Boot命令的标志位。

 

#define CFG_CMD_NAND   0x0000800000000000ULL    /* NAND support                 */ 

如果有更多的命令,也要在这里添加定义。

实现nand命令的操作函数。下面是common/cmd_nand.c文件的部分代码。

 nt do_nand (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])

{

       int rcode = 0;

 

       switch (argc) {

       case 0:

       case 1:

              printf ("Usage:\n%s\n", cmdtp->usage);

              return 1;

       case 2:

              if (strcmp (argv[1], "info") == 0) {

                     int i;

 

                     putc ('\n');

 

                     for (i = 0; i < CFG_MAX_NAND_DEVICE; ++i) {

                            if (nand_dev_desc[i].ChipID ==

                                NAND_ChipID_UNKNOWN)

                                   continue; /* list only known devices */

                            printf ("Device %d: ", i);

                            nand_print (&nand_dev_desc[i]);

                     }

                     return 0;

 

              } else if (strcmp (argv[1], "device") == 0) {

                     if ((curr_device < 0)

                         || (curr_device >= CFG_MAX_NAND_DEVICE)) {

                            puts ("\nno devices available\n");

                            return 1;

                     }

                     printf ("\nDevice %d: ", curr_device);

                     nand_print (&nand_dev_desc[curr_device]);

                     return 0;

 

              } else if (strcmp (argv[1], "bad") == 0) {

                     if ((curr_device < 0)

                         || (curr_device >= CFG_MAX_NAND_DEVICE)) {

                            puts ("\nno devices available\n");

                            return 1;

                     }

                     printf ("\nDevice %d bad blocks:\n", curr_device);

                     nand_print_bad (&nand_dev_desc[curr_device]);

                     return 0;

 

              }

              printf ("Usage:\n%s\n", cmdtp->usage);

              return 1;

       case 3:

              if (strcmp (argv[1], "device") == 0) {

                     int dev = (int) simple_strtoul (argv[2], NULL, 10);

 

                     printf ("\nDevice %d: ", dev);

                     if (dev >= CFG_MAX_NAND_DEVICE) {

                            puts ("unknown device\n");

                            return 1;

                     }

                     nand_print (&nand_dev_desc[dev]);

                     /*nand_print (dev); */

 

                     if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) {

                            return 1;

                     }

 

                     curr_device = dev;

 

                     puts ("... is now current device\n");

 

                     return 0;

              } else if (strcmp (argv[1], "erase") == 0

                        && strcmp (argv[2], "clean") == 0) {

                     struct nand_chip *nand = &nand_dev_desc[curr_device];

                     ulong off = 0;

                     ulong size = nand->totlen;

                     int ret;

 

                     printf ("\nNAND erase: device %d offset %ld, size %ld ... ", curr_device, off, size);

 

                     ret = nand_legacy_erase (nand, off, size, 1);

 

                     printf ("%s\n", ret ? "ERROR" : "OK");

 

                     return ret;

              }

 

              printf ("Usage:\n%s\n", cmdtp->usage);

              return 1;

       default:

              /* at least 4 args */

 

              if (strncmp (argv[1], "read", 4) == 0 ||

                  strncmp (argv[1], "write", 5) == 0) {

                     ulong addr = simple_strtoul (argv[2], NULL, 16);

                     ulong off = simple_strtoul (argv[3], NULL, 16);

                     ulong size = simple_strtoul (argv[4], NULL, 16);

                     int cmd = (strncmp (argv[1], "read", 4) == 0) ?

                            NANDRW_READ : NANDRW_WRITE;

                     int ret, total;

                     char *cmdtail = strchr (argv[1], '.');

 

                     if (cmdtail && !strncmp (cmdtail, ".oob", 2)) {

                            /* read out-of-band data */

                            if (cmd & NANDRW_READ) {

                                   ret = nand_read_oob (nand_dev_desc + curr_device,

                                                      off, size, (size_t *) & total,

                                                      (u_char *) addr);

                            } else {

                                   ret = nand_write_oob (nand_dev_desc + curr_device,

                                                       off, size, (size_t *) & total,

                                                       (u_char *) addr);

                            }

                            return ret;

                     } else if (cmdtail && !strncmp (cmdtail, ".jffs2", 2))

                            cmd |= NANDRW_JFFS2;    /* skip bad blocks */

                     else if (cmdtail && !strncmp (cmdtail, ".jffs2s", 2)) {

                            cmd |= NANDRW_JFFS2;    /* skip bad blocks (on read too) */

                            if (cmd & NANDRW_READ)

                                   cmd |= NANDRW_JFFS2_SKIP;  /* skip bad blocks (on read too) */

                     }

#ifdef SXNI855T

                     /* need ".e" same as ".j" for compatibility with older units */

                     else if (cmdtail && !strcmp (cmdtail, ".e"))

                            cmd |= NANDRW_JFFS2;    /* skip bad blocks */

#endif

#ifdef CFG_NAND_SKIP_BAD_DOT_I

                     /* need ".i" same as ".jffs2s" for compatibility with older units (esd) */

                     /* ".i" for image -> read skips bad block (no 0xff) */

                     else if (cmdtail && !strcmp (cmdtail, ".i")) {

                            cmd |= NANDRW_JFFS2;    /* skip bad blocks (on read too) */

                            if (cmd & NANDRW_READ)

                                   cmd |= NANDRW_JFFS2_SKIP;  /* skip bad blocks (on read too) */

                     }

#endif /* CFG_NAND_SKIP_BAD_DOT_I */

                     else if (cmdtail) {

                            printf ("Usage:\n%s\n", cmdtp->usage);

                            return 1;

                     }

 

                     printf ("\nNAND %s: device %d offset %ld, size %ld ...\n",

                            (cmd & NANDRW_READ) ? "read" : "write",

                            curr_device, off, size);

 

                     ret = nand_legacy_rw (nand_dev_desc + curr_device,

                                         cmd, off, size,

                                         (size_t *) & total,

                                         (u_char *) addr);

 

                     printf (" %d bytes %s: %s\n", total,

                            (cmd & NANDRW_READ) ? "read" : "written",

                            ret ? "ERROR" : "OK");

 

                     return ret;

              } else if (strcmp (argv[1], "erase") == 0 &&

                        (argc == 4 || strcmp ("clean", argv[2]) == 0)) {

                     int clean = argc == 5;

                     ulong off =

                            simple_strtoul (argv[2 + clean], NULL, 16);

                     ulong size =

                            simple_strtoul (argv[3 + clean], NULL, 16);

                     int ret;

 

                     printf ("\nNAND erase: device %d offset %ld, size %ld ...\n",

                            curr_device, off, size);

 

                     ret = nand_legacy_erase (nand_dev_desc + curr_device,

                                           off, size, clean);

 

                     printf ("%s\n", ret ? "ERROR" : "OK");

 

                     return ret;

              } else {

                     printf ("Usage:\n%s\n", cmdtp->usage);

                     rcode = 1;

              }

 

              return rcode;

       }

}

 

U_BOOT_CMD(

       nand,      5,    1,    do_nand,                     /* nand 命令和nand函数的映射 */

       "nand    - legacy NAND sub-system\n",

       "info  - show available NAND devices\n"

       "nand device [dev] - show or set current device\n"

       "nand read[.jffs2[s]]  addr off size\n"

       "nand write[.jffs2] addr off size - read/write `size' bytes starting\n"

       "    at offset `off' to/from memory address `addr'\n"

       "nand erase [clean] [off size] - erase `size' bytes from\n"

       "    offset `off' (entire device if not specified)\n"

       "nand bad - show bad blocks\n"

       "nand read.oob addr off size - read out-of-band data\n"

       "nand write.oob addr off size - read out-of-band data\n"

);

 

U-Boot的命令都是通过结构体__U_Boot_cmd_##name来描述的。根据U_Boot_CMDinclude/command.h中的两行定义可以明白。

 

#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \

cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}

 

common/Makefile中添加编译的目标文件。

 

打开CONFIG_COMMANDS选项的命令标志位。这个程序文件开头有#if语句需要预处理是否包含这个命令函数。CONFIG_COMMANDS选项在开发板的配置文件中定义。SMDK2410平台在include/configs/smdk2410.h中有如下定义。

 

/***********************************************************

 * Command definition

 ***********************************************************/

#define CONFIG_COMMANDS \

                     (CONFIG_CMD_DFL   | \

                     CFG_CMD_CACHE      | \

                     CFG_CMD_NAND       | \         /* 打开nand flash命令 */

                     /*CFG_CMD_EEPROM |*/ \

                     /*CFG_CMD_I2C  |*/ \

                     /*CFG_CMD_USB |*/ \

                     CFG_CMD_REGINFO  | \

                     CFG_CMD_DATE  | \

                     CFG_CMD_ELF)

按照上面的操作就可以实现u-bootnand flash命令的支持

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值