uboot在s3c2440上的移植(5)

发布时间:2024-07-22  

一、移植环境

主  机:VMWare--Fedora 9

开发板:Mini2440--64MB Nand,Kernel:2.6.30.4

编译器:arm-linux-gcc-4.3.2.tgz

u-boot:u-boot-2009.08.tar.bz2


二、移植步骤

9)实现u-boot对yaffs/yaffs2文件系统下载的支持。

 注意:此篇对Nand的操作是基于MTD架构方式,在“u-boot-2009.08在2440上的移植详解(三)”中讲到过。


通常一个Nnad Flash存储设备由若干块组成,1个块由若干页组成。一般128MB以下容量的Nand Flash芯片,一页大小为528B,被依次分为2个256B的主数据区和16B的额外空间;128MB以上容量的Nand Flash芯片,一页大小通常为2KB。由于Nand Flash出现位反转的概率较大,一般在读写时需要使用ECC进行错误检验和恢复。

Yaffs/yaffs2文件系统的设计充分考虑到Nand Flash以页为存取单位等的特点,将文件组织成固定大小的段(Chunk)。以528B的页为例,Yaffs/yaffs2文件系统使用前512B存储数据和16B的额外空间存放数据的ECC和文件系统的组织信息等(称为OOB数据)。通过OOB数据,不但能实现错误检测和坏块处理,同时还可以避免加载时对整个存储介质的扫描,加快了文件系统的加载速度。以下是Yaffs/yaffs2文件系统页的结构说明:


Yaffs页结构说明

==============================================

   字节                   用途

==============================================

 0 - 511                存储数据(分为两个半部)

512 - 515               系统信息

   516                  数据状态字

   517                  块状态字

518 - 519               系统信息

520 - 522               后半部256字节的ECC

523 - 524               系统信息

525 - 527               前半部256字节的ECC

==============================================

好了,在了解Nand Flash组成和Yaffs/yaffs2文件系统结构后,我们再回到u-boot中。目前,在u-boot中已经有对Cramfs、Jffs2等文件系统的读写支持,但与带有数据校验等功能的OOB区的Yaffs/Yaffs2文件系统相比,他们是将所有文件数据简单的以线性表形式组织的。所以,我们只要在此基础上通过修改u-boot的Nand Flash读写命令,增加处理00B区域数据的功能,即可以实现对Yaffs/Yaffs2文件系统的读写支持。

 

实现对Yaffs或者Yaffs2文件系统的读写支持步骤如下:

①、在include/configs/my2440.h头文件中定义一个管理对Yaffs2支持的宏和开启u-boot中对Nand Flash默认分区的宏,如下:

#gedit include/configs/my2440.h  //添加到文件末尾即可


#define CONFIG_MTD_NAND_YAFFS2   1 //定义一个管理对Yaffs2支持的宏


//开启Nand Flash默认分区,注意此处的分区要和你的内核中的分区保持一致

#define MTDIDS_DEFAULT "nand0=nandflash0"

#define MTDPARTS_DEFAULT "mtdparts=nandflash0:192k(bootloader),"

                     "64k(params),"

                     "2m(kernel),"

                     "-(root)"


②、在原来对Nand操作的命令集列表中添加Yaffs2对Nand的写命令,如下:


接着,在该文件中对nand操作的do_nand函数中添加yaffs2对nand的操作,如下:


    if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) 

    {

        int read;


        if (argc < 4)

            goto usage;


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


        read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */

        printf("nNAND %s: ", read ? "read" : "write");

        if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)

            return 1;


        s = strchr(cmd, '.');

        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);

        }


//添加yaffs2相关操作,注意该处又关联到nand_write_skip_bad函数


#if defined(CONFIG_MTD_NAND_YAFFS2)

        else if (s != NULL && (!strcmp(s, ".yaffs2")))

        {

            nand->rw_oob = 1;

            nand->skipfirstblk = 1;

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

            nand->skipfirstblk = 0;

            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

            };


            if (read)

                ret = nand->read_oob(nand, off, &ops);

            else

                ret = nand->write_oob(nand, off, &ops);

        } 

        else 

        {

            printf("Unknown nand command suffix '%s'.n", s);

            return 1;

        }


        printf(" %zu bytes %s: %sn", size, read ? "read" : "written", ret ? "ERROR" : "OK");


        return ret == 0 ? 0 : 1;

    }



③、在include/linux/mtd/mtd.h头文件的mtd_info结构体中添加上面用到rw_oob和skipfirstblk数据成员,如下:


#gedit include/linux/mtd/mtd.h   //在mtd_info结构体中添加


#if defined(CONFIG_MTD_NAND_YAFFS2)

    u_char rw_oob;

    u_char skipfirstblk;

#endif



④、在第二步关联的nand_write_skip_bad函数中添加对Nand OOB的相关操作,如下:


#gedit drivers/mtd/nand/nand_util.c  //在nand_write_skip_bad函数中添加


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_MTD_NAND_YAFFS2) //add yaffs2 file system support

    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 length 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 datan");

        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 arean");

        return -EINVAL;

    }


#if !defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support

    if (len_incl_bad == *length) {

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

        if (rval != 0)

            printf ("NAND write to offset %llx failed %dn",

                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%08llxn",

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

            offset += nand->erasesize - block_offset;

            continue;

        }


#if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support

        if(nand->skipfirstblk==1)    

        {

            nand->skipfirstblk=0;

            printf ("Skip the first good block %llxn", 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); //add yaffs2 file system support



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

        if (rval != 0) {

            printf ("NAND write to offset %llx failed %dn",

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>