u-boot-2010.03在tq6410上的移植详解(二)

原创文章版权所有!如需转载,请注明出处: http://hi.baidu.com/liushuiyue1/myhome谢谢合作!!!!!

六.对Nor flash的支持:

从上图的启动信息可以看到flash0kbUboot还没有添加对Nor flash的支持。我们使用的nor flash型号是EN29LV160AB,与AMD的兼容,所以添加对Nor flash的支持。

#cd include/configs///

#gedit smdk6410.h //

/*-----------------------------------------------------------------------

 * FLASH and environment organization

 */

#define CONFIG_SYS_FLASH_BASE     0x00000000//0x10000000Flash的基地址

#define CONFIG_SYS_MONITOR_BASE   0x00000000

 

#define CONFIG_SYS_MAX_FLASH_BANKS 1   /* max number of memory banks   */

//一定要定义为>0

/* AM29LV160B has 35 sectors, AM29LV800B - 19 */

#define CONFIG_SYS_MAX_FLASH_SECT 35//40硬件得来

 

#define CONFIG_AMD_LV800

//#define CONFIG_SYS_FLASH_CFI    1   /* Use CFI parameters (needed?) */

#define PHYS_FLASH_SIZE    0x200000 //2M Flash的大小

#define PHYS_FLASH_1    0x00000000

/* Use drivers/cfi_flash.c, even though the flash is not CFI-compliant   */

//CFI相关的屏蔽掉

//#define CONFIG_FLASH_CFI_DRIVER 1

//#define CONFIG_SYS_FLASH_CFI_WIDTH  FLASH_CFI_16BIT

//#define CONFIG_FLASH_CFI_LEGACY

//#define CONFIG_SYS_FLASH_LEGACY_512Kx16

 

/* timeout values are in ticks */

#define CONFIG_SYS_FLASH_ERASE_TOUT   (5 * CONFIG_SYS_HZ) /* Timeout for Flash Erase   */

#define CONFIG_SYS_FLASH_WRITE_TOUT   (5 * CONFIG_SYS_HZ) /* Timeout for Flash Write   */

#define CONFIG_ENV_ADDR     0x00000

#define CONFIG_ENV_SIZE 0x4000    /* Total Size of Environment Sector */

说明:Uboot2010.03中支持Nor flash的两种读写方式:CFIJEDEC。本文章采用JEDEC的方式。因为S3C2440S3C6410nor flash接口兼容,所以将S3C2440目录下的flash.c复制到./board/samsung/s3c6410/下,并修改Makefile文件。

#cd board/samsung/s3c6410/Makefile//

#gedit Makefile //

COBJS-y    := smdk6410.o flash.o

重新编译Uboot并下载到Nand Flash中,串口打印信息如下。说明板子已经能检测到Nor flash

七.Uboot支持yaffs2文件的读写

       由于Uboot本身支持yaffs2文件的读写直接修改./include/configs/smdk6410.h的配置文件,使得uboot支持yaffs2的读写,重新编译Uboot并下载到Nand Flash中,串口打印信息如下,uboot已经支持yaffs2烧写到nand flash(由于本人对于此uboot中指令不熟悉,所以至今还未写yaffs2文件成功,如有知道的可告知,谢谢)。

于是又重新手动yaffs2文件的烧写指令。首先修改./include/configs/smdk6410.h

#cd include/configs/smdk6410.h//

#define CONFIG_YAFFS2

于是又重新手动yaffs2文件的烧写指令。

1)       修改./include/configs/smdk6410.h

注意一定要屏蔽掉CONFIG_YAFFS2,否则yaffs文件读写有冲突。

#cd include/configs/smdk6410.h//

//#define CONFIG_YAFFS2

#define CONFIG_SYS_NAND_YAFFS_WRITE     1  /* support yaffs write    EN        */

#define CONFIG_MTD_NAND_ECC_YAFFS 1

2)修改common/cmd_nand.c

373行,红色字体为添加部分

if (!s || !strcmp(s, ".jffs2") ||

                 !strcmp(s, ".e") || !strcmp(s, ".i")) {

                    if (read)

                           ret = nand_read_skip_bad(nand, off, &size,

                                                 (u_char *)addr);

                    else

                           ret = nand_write_skip_bad(nand, off, &size,

                                                  (u_char *)addr);

             }

              #if defined(ENABLE_CMD_NAND_YAFFS)

              }else if ( s != NULL &&

                     (!strcmp(s, ".yaffs") || !strcmp(s, ".yaffs1"))){

                         if(read)  {

                              printf("nand read.yaffs[1] is not provide temporarily!");

                         } else    {

                            nand->rw_oob = 1;

#if defined(ENABLE_CMD_NAND_YAFFS_SKIPFB)

                            nand->skipfirstblk = 1;

#else

                            nand->skipfirstblk = 0;

#endif

                            ret = nand_write_skip_bad(nand,off,&size,(u_char *)addr);

#if defined(ENABLE_CMD_NAND_YAFFS_SKIPFB)

                            nand->skipfirstblk = 0;

#endif

                            nand->rw_oob = 0;

                         }

#endif

}           

             else if (!strcmp(s, ".oob")) {

                    /* out-of-band data */

                    mtd_oob_ops_t ops = {

                           .oobbuf = (u8 *)addr,

                           .ooblen = size,

                           .mode = MTD_OOB_RAW

                    };

505行添加,红色字体为添加部分

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

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

      #if defined(CONFIG_SYS_NAND_YAFFS_WRITE)

      "nand read[.yaffs[1]] is not provide temporarily/n"

      "nand write[.yaffs[1]] addr off size -write the 'size' byte yaffs image starting/n"

      "at offset 'off' from memory address 'addr' (.yaffs for 512+16 Nand)"

      #endif

      "nand bad - show bad blocks/n"

 

3drivers/mtd/nand/nand_base.c

2095行处红色字体为修改部分:

static int nand_write(struct mtd_info *mtd, loff_t to, size_t len,

                      size_t *retlen, const uint8_t *buf)

{

      struct nand_chip *chip = mtd->priv;

      int ret;

 

      #if defined(CONFIG_SYS_NAND_YAFFS_WRITE)

             int oldopsmode = 0;

             if(mtd->rw_oob==1)

             {

                    size_t oobsize =mtd->oobsize;  

                    size_t datasize = mtd->writesize;

                    int i=0;

                    uint8_t oobtemp[oobsize];

                    int datapages = 0;

                    datapages = len/(datasize);

                    for(i=0;i<(datapages);i++)

                    {

                           memcpy((void *)oobtemp,(void *)(buf+datasize*(i+1)),oobsize);

                           memmove((void *)(buf+datasize*(i+1)),(void *)(buf+datasize*(i+1)+oobsize),(datapages-(i+1))*(datasize)+(datapages-1)*oobsize);

                           memcpy((void *)(buf+(datapages)*(datasize+oobsize)-oobsize),(void *)(oobtemp),oobsize);

                    }

             }

      #endif

 

      /* Do not allow reads past end of device */

      if ((to + len) > mtd->size)

             return -EINVAL;

      if (!len)

             return 0;

      nand_get_device(chip, mtd, FL_WRITING);

      chip->ops.len = len;

      chip->ops.datbuf = (uint8_t *)buf;

      #if !defined(CONFIG_SYS_NAND_YAFFS_WRITE)

      chip->ops.oobbuf = NULL;

      #endif

      #if defined(CONFIG_SYS_NAND_YAFFS_WRITE)

             if(mtd->rw_oob!=1)

             {

                    chip->ops.oobbuf = NULL;

             }

             else

             {

                    chip->ops.oobbuf = (uint8_t*)(buf+len);

                    chip->ops.ooblen = mtd->oobsize;

                    oldopsmode = chip->ops.mode;

                    chip->ops.mode = MTD_OOB_RAW;

             }    

      #endif

      ret = nand_do_write_ops(mtd, to, &chip->ops);

 

      *retlen = chip->ops.retlen;

 

      nand_release_device(mtd);

      #if defined(CONFIG_SYS_NAND_YAFFS_WRITE)

             chip->ops.mode = oldopsmode;      

      #endif

 

      return ret;

}

4)修改drivers/mtd/nand/nand_util.c

int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,

                    u_char *buffer)

{

      int rval;

      size_t left_to_write = *length;

      size_t len_incl_bad;

      u_char *p_buffer = buffer;

     

      #if defined(CONFIG_SYS_NAND_YAFFS_WRITE)

             if(nand->rw_oob==1)

             {

             size_t oobsize=nand->oobsize;

             size_t datasize = nand->writesize;

             int datapages = 0;

 

             if(((*length)%(nand->oobsize+nand->writesize))!=0)

             {

                    printf("Attempt to write error lenght data!/n");

                    return -EINVAL;

             }

             datapages = *length/(datasize+oobsize);

             *length = datapages*datasize;

             left_to_write = *length;

             }

      #endif

      /* Reject writes, which are not page aligned */

      if ((offset & (nand->writesize - 1)) != 0 ||

          (*length & (nand->writesize - 1)) != 0) {

             printf ("Attempt to write non page aligned data/n");

             return -EINVAL;

      }

 

      len_incl_bad = get_len_incl_bad (nand, offset, *length);

 

      if ((offset + len_incl_bad) > nand->size) {

             printf ("Attempt to write outside the flash area/n");

             return -EINVAL;

      }

     

      #if !defined(CONFIG_SYS_NAND_YAFFS_WRITE)

      if (len_incl_bad == *length) {

             rval = nand_write (nand, offset, length, buffer);

             if (rval != 0)

                    printf ("NAND write to offset %llx failed %d/n",

                           offset, rval);

 

             return rval;

      }

      #endif

 

      while (left_to_write > 0) {

             size_t block_offset = offset & (nand->erasesize - 1);

             size_t write_size;

 

             WATCHDOG_RESET ();

 

             if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {

                    printf ("Skip bad block 0x%08llx/n",

                           offset & ~(nand->erasesize - 1));

                    offset += nand->erasesize - block_offset;

                    continue;

             }

             #if defined(CONFIG_SYS_NAND_YAFFS_WRITE)

             if (nand->skipfirstblk==1)

             {

                    nand->skipfirstblk = 0;

                    printf("Skip the first good block%llx/n",offset&~(nand->erasesize-1));

                    offset+=nand->erasesize-block_offset;

                    continue;

             }           

             #endif

 

             if (left_to_write < (nand->erasesize - block_offset))

                    write_size = left_to_write;

             else

                    write_size = nand->erasesize - block_offset;

                    printf("/rWriting at 0x%llx--",offset);

 

             rval = nand_write (nand, offset, &write_size, p_buffer);

             if (rval != 0) {

                    printf ("NAND write to offset %llx failed %d/n",

                           offset, rval);

                    *length -= left_to_write;

                    return rval;

             }

             left_to_write -= write_size;

             printf("%d%% is complete",100-(left_to_write/(*length/100)));

             offset        += write_size;

            

//           p_buffer      += write_size;

             #if defined(CONFIG_SYS_NAND_YAFFS_WRITE)

             if(nand->rw_oob==1)

             {

             p_buffer+=write_size+(write_size/nand->writesize*nand->oobsize);

             }           

             else

             {

             p_buffer+=write_size;

             }

             #else

             p_buffer      += write_size;

             #endif

      }

      return 0;

}

 

5)修改include/linux/mtd/mtd.h

131行添加红色字体部分

#if defined(CONFIG_SYS_NAND_YAFFS_WRITE)

      u_char rw_oob;

      u_char skipfirstblk;     

      #endif

重新编译uboot并下载到Nand Flash中,使用nand指令烧写yaffs2文件到nand中如下图所示,至此uboot已支持yaffs的烧写。

对于ubootyaffs2文件的烧写一定要是2048+64个字节的整数倍,否则烧写将出错,说明页面烧写不成功。

八.支持串口xmodem协议

U-Boot默认支持的loadb命令需要配合Linux下的kermit工具来使用,loady命令通过串口ymodem协议来传输文件。Windows下的超级终端虽然支持ymodem,但是它的使用界面实在不友好。而SecureCRT只支持xmodemzmodem。而上位机和开发板之间的文件传输又实在是一件非常重要的事,所以现在修改代码以增加对xmodem的支持,即增加一个命令loadx

1)依照loady的实现来编写代码,首先使用U_BOOT_CMD宏来增加loadx命令(在文件common/cmd_load.c文件中):

U_BOOT_CMD(

      loadx, 3, 0,    do_load_serial_bin,

      "load binary file over serial line (xmodem mode)",

      "[ off ] [ baud ]/n"

      "    - load binary file over serial line"

      " with offset 'off' and baudrate 'baud'"

);

2)依照loadydo_load_serial_bin函数中增加对loadx命令的处理分支。

else if(strcmp(argv[0],"loadx")==0) {

             printf ("## Ready for binary (xmodem) download "

                    "to 0x%08lX at %d bps.../n",

                    offset,

                    load_baudrate);

             addr = load_serial_xmodem (offset);

      }

3)由于addr行调用了load_serial_xmodem函数,依照load_serial_ymodem实现的一个函数。首先在文件开头增加loadx_serial_xmodem函数的声明,然后复制load_serial_ymodem函数为load_serial_xmodem,稍作修改:1)、将局部数组ymodemBuf改名为xmodemBuf,并在后面使用到的地方统一修改,这只是为了与函数名称一致,可改可不改。(2)、info.mode的值从xyzModem_ymodem改为xyzModem_xmodem

#if defined(CONFIG_CMD_LOADB)

static ulong load_serial_ymodem (ulong offset);

static ulong load_serial_xmodem (ulong offset);

#endif

重新编译,执行loadx,然后在secureCRTTransfer菜单下点Send Xmodemxxx已经放在了Upload目录里),完成对串口xmodem协议的支持。

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值