裸机移植yaffs2文件系统

来源:互联网 发布:淘宝代销需要什么条件 编辑:程序博客网 时间:2024/05/13 00:54


裸机移植yaffs2演示

Linux系统上

[fulinux@centos6 ~]$ cd yaffs2/

[fulinux@centos6 yaffs2]$ ls

bootstrap.c  bootstrap.lds  bsp  common  makefile  start.S  yaffs2

[fulinux@centos6 yaffs2]$ make

........................

........................

........................

[fulinux@centos6 yaffs2]$ ls

bootstrap.bin  bootstrap.c  bootstrap.lds  bootstrap.map  bsp  common  makefile  start.S  yaffs2

[fulinux@centos6 yaffs2]$ 

bootstrap.bin文件拷贝到/tfpt目录下

s3c2440开发板上

[ s3c2440@guowenxue ]# set bstarp 'tftp 31000000 bootstrap.bin;go 31000000'

[ s3c2440@guowenxue ]# save

Saving Environment to NAND...

Erasing Nand...

Erasing at 0x60000 -- 100% complete.

Writing to Nand... done

[ s3c2440@guowenxue ]# run bstarp

dm9000 i/o: 0x20000300, id: 0x90000a46 

DM9000: running in 16 bit mode

MAC: 08:00:3e:26:0a:6b

could not establish link

operating at 100M full duplex mode

Using dm9000 device

TFTP from server 192.168.1.2; our IP address is 192.168.1.111

Filename 'bootstrap.bin'.

Load address: 0x31000000

Loading: T ##############

done

Bytes transferred = 193924 (2f584 hex)

## Starting application at 0x31000000 ...

Bootstrap nandflash yaffs2 test Version 0.0.1

malloc memory space: 0x30f00000~0x31000000

Malloc address: 30f00008, string: Hello World!

Configures yaffs mount /nand: start block 16, end block 96 

'/nand' mounted

Create directory [/nand/foo]

Create File [/nand/foo/f1] content: [foo/f1]

Create File [/nand/foo/f2] content: [foo/f2]

Create File [/nand/foo/f3] content: [foo/f3]

Create File [/nand/foo/f4] content: [foo/f4]

Create directory [/nand/bar]

Create File [/nand/bar/f1] content: [bar/f1]

List folder '/nand' with recursive:

drw- 1 /nand/bar 2048 bytes

-rw- 1 /nand/bar/f1 6 bytes

drw- 1 /nand/foo 2048 bytes

-rw- 1 /nand/foo/f4 6 bytes

-rw- 1 /nand/foo/f3 6 bytes

-rw- 1 /nand/foo/f2 6 bytes

-rw- 1 /nand/foo/f1 6 bytes

drw- 1 /nand/lost+found 2048 bytes

Remove /nand/foo/f4

Remove /nand/bar

List folder '/nand' with recursive:

drw- 1 /nand/foo 2048 bytes

-rw- 1 /nand/foo/f3 6 bytes

-rw- 1 /nand/foo/f2 6 bytes

-rw- 1 /nand/foo/f1 6 bytes

drw- 1 /nand/lost+found 2048 bytes

unmount and remount

List folder '/nand' with recursive:

drw- 1 /nand/lost+found 2048 bytes

代码分析

[fulinux@centos6 yaffs2]$ ls

bootstrap.bin  bootstrap.c  bootstrap.lds  bootstrap.map  bsp  common  makefile  start.S  yaffs2

[fulinux@centos6 yaffs2]$ 

先看看make后生成的bootstrap.map文件中主要的段:

Linker script and memory map startsize size

                 0x0000000000000000                 . = ALIGN (0x4)

(.stack xxxxxxxxxxxxxxxxxx          xxxx  运行时初始化这个段)

.text              0x0000000031000000     0x2c3dc

.rodata            0x000000003102c3dc      0x2c58

.data            0x000000003102f054        0x10

.bss             0x000000003102f588      0x36b4

其中代码段的第一个代码是start.S

start.S文件

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

 *        File:  start.S - Startup Code for ARM920 CPU-core

 *     Version:  1.0.0

 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>

 * Description:  When system power up, the CPU will comes here to excute the first code here.

 *   ChangeLog:  1, Release initial version on "Tue Jul 12 16:43:18 CST 2011"

 *

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

/*

 *************************************************************************

 *

 * Jump vector table as in table 3.1 in [1]

 *

 *************************************************************************

 */

.globl _start

_start: b   start_code

_TEXT_BASE:

    .word   TEXT_BASE

    

.globl _armboot_start

_armboot_start:

    .word _start

/*

 * These are defined in the board-specific linker script.

 */

.globl _bss_start

_bss_start:

    .word __bss_start

.globl _bss_end

_bss_end:

    .word _end

start_code:

    /* Set up the stack */

stack_setup:

    ldr r0, =TEXT_BASE      /* upper 128 KiB: relocated uboot   */

    sub r0, r0, #CONFIG_SYS_MALLOC_LEN  /* malloc area              */

    sub sp, r0, #12     /* leave 3 words for abort-stack    */

    bic sp, sp, #7      /* 8-byte alignment for ABI compliance */

clear_bss:

    ldr r0, _bss_start      /* find start of bss segment        */

    ldr r1, _bss_end        /* stop here                        */

    mov r2, #0x00000000     /* clear                            */

clbss_l:str r2, [r0]        /* clear loop...                    */

    add r0, r0, #4

    cmp r0, r1

    ble clbss_l

bl  bootstrap_main

堆栈段初始化

其中TEXT_BASE#CONFIG_SYS_MALLOC_LEN变量是在makefile文件中定义的,如下:

# Set the stack top base address here

TEXT_BASE=0x31000000

STACK_BASE=0x31010000

MALLOC_SIZE=0x100000

CFLAGS+=-DTEXT_BASE=$(TEXT_BASE) -DSTACK_BASE=${STACK_BASE} -DCONFIG_SYS_MALLOC_LEN=${MALLOC_SIZE}

上面的CFLAGS一行中的-D的意思类似于#define,,例如-DTEXT_BASE=$(TEXT_BASE) 等于#define TEXT_BASE 0X31000000.

BSS段初始化

Bss段初始化代码其中的_bss_start  ---> __bss_start是在makefile文件中

APP_NAME=bootstrap

LDFLAGS=-Bstatic -T$(APP_NAME).lds -Ttext $(TEXT_BASE)

参数LDFLAGS依赖于文件bootstrap.lds文件,如下

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

 *        File:  bootstrap.lds

 *     Version:  1.0.0

 *   Copyright:  2011 (c) Guo Wenxue <guowenxue@gmail.com>

 * Description:  This is the LD linker configure script for bootstrap

 *   ChangeLog:  1, Release initial version on "Tue Jul 12 16:43:18 CST 2011"

 *

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

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")

OUTPUT_ARCH(arm)

ENTRY(_start)

SECTIONS{

    . = ALIGN(4);

    .text   :

    {

      start.o   (.text)

      *(.text)

    }

    . = ALIGN(4);

    .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }

    . = ALIGN(4);

    .rodata : { *(.rodata) }

    . = ALIGN(4);

    .data : { *(.data) }

    . = ALIGN(4);

    __bss_start = .;

    .bss : { *(.bss) }

    _end = .;

}

然后是跳转到c函数中的bootstarp_main()函数中去,bootstarp_main()函数如下:

位置:yaffs2/bootstrap.c

int bootstrap_main(void)

{

    char *ptr = NULL;

    int rv = -1;

    

    console_serial_init();

    printf("\b\n");     

    printf("\bBootstrap nandflash yaffs2 test Version 0.0.1\n");

    /*  armboot_start is defined in the board-specific linker script */

    mem_malloc_init (TEXT_BASE - CONFIG_SYS_MALLOC_LEN, CONFIG_SYS_MALLOC_LEN);

    

    ptr = (char *)malloc(MALLOC_SIZE);                          

    strncpy(ptr, "Hello World!\n", MALLOC_SIZE);

    printf("Malloc address: %p, string: %s\n", ptr, ptr);       

    free(ptr);

    

    yaffs_test(YAFFSFS_MNT_POINT);

hang:

    while(1)

        ;

    return 0;

}

首先是初始化串口,console_serial_init()函数如下:

位置:yaffs2/bsp/s3c_board.h

#define CONSOLE_BAUDRATE         115200

#define CONSOLE_SERIAL           S3C2440_UART0

其中S3C2440_UART0在文件yaffs2/bsp/s3c2440.h中定义:

enum s3c2440_uarts_nr {

    S3C2440_UART0 = 0,

    S3C2440_UART1 = 1,

    S3C2440_UART2 = 2

};

#define console_serial_init()      s3c2440_serial_init(CONSOLE_BAUDRATE, CONSOLE_SERIAL)

--> console_serial_init()-->s3c2440_serial_init()如下:

int s3c2440_serial_init(unsigned int baudrate, int index)

{

    struct s3c2440_uart *uart = s3c2440_get_base_uart(index);

    /* FIFO enable, Tx/Rx FIFO clear */

    uart->UFCON = 0x07;

    uart->UMCON = 0x0;

    /* Normal,No parity,1 stop,8 bit */

    uart->ULCON = 0x3;

    /*

     * tx=level,rx=edge,disable timeout int.,enable rx error int.,

     * normal,interrupt or polling

     */

    uart->UCON = (1<<8) | (1<<2) | (1<<0);

//  uart->UMCON = 0x1; /* RTS up */

    s3c2440_set_baudrate(baudrate, index);

    return (0);

}

设置波特率函数s3c2440_set_baudrate()

void s3c2440_set_baudrate(unsigned int baudrate, int index)

{

    struct s3c2440_uart *uart = s3c2440_get_base_uart(index);

    unsigned int reg = 0;

    int i; 

    reg = s3c2440_get_pclk() / (16 * baudrate) - 1;

    uart->UBRDIV = reg;

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

返回到bootstrap_main()函数中去,看下printf()函数如何将打印信息通过串口显示出来。

#define CFG_PBSIZE                  1024 /*  Print Buffer Size */

void printf(const char *fmt, ...)

{

    va_list args;

    uint i;

    char printbuffer[CFG_PBSIZE];

    va_start(args, fmt);

    /* For this to work, printbuffer must be larger than

     * anything we ever want to print.

     */

    i = vsprintf(printbuffer, fmt, args);

    va_end(args);

    console_serial_puts(printbuffer);

}

调用函数console_serial_puts()函数,如下:

#define console_serial_puts(s)     s3c2440_serial_puts(s, CONSOLE_SERIAL)

void s3c2440_serial_puts(const char *s, int index)

{

    while (*s)

    {

        if (*s == '\n')              /*  If \n, also do \r */

            s3c2440_serial_putc('\r', index);

        s3c2440_serial_putc (*s++, index);

    }

}

调用函数s3c2440_serial_putc()函数,如下:

/*

 * Output a single byte to the serial port.

 */

void s3c2440_serial_putc (char c, int index)

{

    struct s3c2440_uart *uart = s3c2440_get_base_uart(index);

    /* wait for room in the tx FIFO */

    //while ((!(uart->UTRSTAT & 0x2)));

    while (uart->UFSTAT & (1<<14));

    uart->UTXH = c;

返回bootstrap_main()函数,调用mem_mallloc_init()函数初始化动态分配的存储区,为我们调用malloc()函数做好准备工作,如下:

void mem_malloc_init(ulong start, ulong size)

{

    mem_malloc_start = start;

    mem_malloc_end = start + size;

    mem_malloc_brk = start;

    

    memset((void *)mem_malloc_start, 0, size);

    printf("malloc memory space: 0x%lx~0x%lx\n", start, start+size);

}   

函数返回,调用函数

ptr = (char *)malloc(MALLOC_SIZE);

其中MALLOC_SIZE定义在makefile函数,MALLOC_SIZE=0x100000。我们深入到malloc函数中去,如下

声明位置:yaffs2/common/malloc.h

#define mALLOc      malloc

Void_t* mALLOc(size_t);

定义位置:yaffs2/common/dlmalloc.c

代码量很大,不拷贝了。

返回bootstrap_main()函数,调用如下函数目的是测试动态分配到存储区域是否成功:

    strncpy(ptr, "Hello World!\n", MALLOC_SIZE);

    printf("Malloc address: %p, string: %s\n", ptr, ptr);

    free(ptr);

接着就到了测试yaffs2文件系统的阶段了。

#define YAFFSFS_MNT_POINT              "/nand"

yaffs_test(YAFFSFS_MNT_POINT);

hang:

    while(1)

        ;

    return 0;

}

其中yaffs_test()函数主要是通过创建文件或目录,并删除一些文件的功能来达到测试yaffs2文件系统是否移植成功,代码如下:

位置:与bootstrap_main()函数同处于一个位置。

void yaffs_test(const char *mountpt)

{

    yaffs_start_up();

    yaffs_format(mountpt,0,0,0);

    yaffs_mount(mountpt);

    printf("'%s' mounted\n", mountpt);

    mkdir(mountpt, "foo");

    mkfile(mountpt, "foo/f1");

    mkfile(mountpt, "foo/f2");

    mkfile(mountpt, "foo/f3");

    mkfile(mountpt, "foo/f4");

    mkdir(mountpt, "bar");

    mkfile(mountpt, "bar/f1");

    ls(mountpt, NULL);

    rm(mountpt, "foo/f4");

    rm(mountpt, "bar");

    ls(mountpt, NULL);

    printf("unmount and remount\n\n");

    

    /*  Unmount/remount yaffs_trace_mask */

    yaffs_unmount(mountpt);

    yaffs_mount(mountpt);

    ls(mountpt, NULL);

}

其中yaffs_start_up()函数用来配置将要用到的设备,如下:

位置:yaffs2/yaffs2/yaffscfg2k.c

/* Configure the devices that will be used */

int yaffs_start_up(void)

{

    static int start_up_called = 0;

    if(start_up_called)

        return 0;

    start_up_called = 1;

    yaffs_devconfig(YAFFSFS_MNT_POINT, YAFFSFS_START_BLOCK, YAFFSFS_END_BLOCK);

    /* Call the OS initialisation (eg. set up lock semaphore */

    yaffsfs_OSInitialisation();

    return 0;

}

其中yaffs_devconfig(YAFFSFS_MNT_POINT, YAFFSFS_START_BLOCK, YAFFSFS_END_BLOCK),的参数是宏,如下:

#define YAFFSFS_MNT_POINT              "/nand"

#define YAFFSFS_OFFSET                 (2*SIZE_1M)  /* YAFFS2 file system start offset address */

#define YAFFSFS_SIZE                   (10*SIZE_1M) /* YAFFS2 file system size */

#define YAFFSFS_START_BLOCK            ( YAFFSFS_OFFSET/NF_BLOCK_SIZE )

#define K9F2G08_BLOCK_SIZE             0x20000      /* Nandflash block size: 128K  */

#define NF_BLOCK_SIZE                  K9F2G08_BLOCK_SIZE

#define YAFFSFS_END_BLOCK              ( YAFFSFS_START_BLOCK+(YAFFSFS_SIZE/NF_BLOCK_SIZE) )

yaffs_devconfig()函数的代码如下:

位置:yaffs2/yaffs2/yaffscfg2k.c

int yaffs_devconfig(char *_mp, int start_block, int end_block)

{

    struct yaffs_dev *dev = NULL;

    char *mp = NULL;

    dev = malloc(sizeof(*dev));

    mp = strdup(_mp);

    if (!dev || !mp)

    {

        /*  Alloc error */

        printf("Failed to allocate memory\n");

        return -1;

    }

    /*  Seems sane, so configure */

    memset(dev, 0, sizeof(*dev));

    dev->param.name = mp;

    dev->param.is_yaffs2 = 1;

    dev->param.total_bytes_per_chunk = NF_PAGE_SIZE;

    dev->param.spare_bytes_per_chunk = NF_SPARE_SIZE;

    dev->param.chunks_per_block = NF_BLOCK_SIZE / NF_PAGE_SIZE;

    dev->param.start_block = start_block;

    dev->param.end_block = end_block;

    dev->param.n_reserved_blocks = 8;

    dev->param.inband_tags = 0;

    dev->param.use_nand_ecc = 0;

    dev->param.no_tags_ecc = 0;

    dev->param.n_caches=0;

    dev->param.empty_lost_n_found = 1;

    dev->param.skip_checkpt_rd = 0;

    dev->param.skip_checkpt_wr = 0;

    dev->param.refresh_period = 1000;

    dev->param.initialise_flash_fn = ynf_init;

    dev->param.erase_fn = ynf_erase_block;

    dev->param.write_chunk_tags_fn = ynf_write_chunk_tags;

    dev->param.read_chunk_tags_fn = ynf_read_chunk_tags;

    dev->param.bad_block_fn = ynf_mark_block_bad;

    dev->param.query_block_fn = ynf_query_block;

    dev->driver_context = NULL;

    yaffs_add_device(dev);

    printf("Configures yaffs mount %s: start block %d, end block %d %s\n",

            mp, start_block, end_block, dev->param.inband_tags ? "using inband tags" : "");

    return 0;

}

其中主要是有一个重要的数据结构体struct yaffs_dev,如下

代码清单 struct yaffs_dev结构体

struct yaffs_dev {

    struct yaffs_param param;

    /* Context storage. Holds extra OS specific data for this device */

        

    void *os_context;

    void *driver_context;

    struct list_head dev_list;

    

    /* Runtime parameters. Set up by YAFFS. */

    int data_bytes_per_chunk;

    /* Non-wide tnode stuff */

    u16 chunk_grp_bits; /* Number of bits that need to be resolved if

                 * the tnodes are not wide enough.

                 */

    u16 chunk_grp_size; /* == 2^^chunk_grp_bits */

    

    /* Stuff to support wide tnodes */

    u32 tnode_width;

    u32 tnode_mask;

    u32 tnode_size;

    

    /* Stuff for figuring out file offset to chunk conversions */

    u32 chunk_shift;    /* Shift value */

    u32 chunk_div;      /* Divisor after shifting: 1 for 2^n sizes */

    u32 chunk_mask;     /* Mask to use for power-of-2 case */

    int is_mounted;

    int read_only;

    int is_checkpointed;

    /* Stuff to support block offsetting to support start block zero */

    int internal_start_block;

    int internal_end_block;

    int block_offset;

int chunk_offset;

    /* Runtime checkpointing stuff */

    int checkpt_page_seq;   /* running sequence number of checkpt pages */

    int checkpt_byte_count;

    int checkpt_byte_offs;

    u8 *checkpt_buffer;

    int checkpt_open_write;

    int blocks_in_checkpt;

    int checkpt_cur_chunk;

    int checkpt_cur_block;

    int checkpt_next_block;

    int *checkpt_block_list;

    int checkpt_max_blocks;

    u32 checkpt_sum;

    u32 checkpt_xor;

    int checkpoint_blocks_required; /* Number of blocks needed to store

                     * current checkpoint set */

    /* Block Info */

    struct yaffs_block_info *block_info;

    u8 *chunk_bits;     /* bitmap of chunks in use */

    unsigned block_info_alt:1;  /* allocated using alternative alloc */

    unsigned chunk_bits_alt:1;  /* allocated using alternative alloc */

    int chunk_bit_stride;   /* Number of bytes of chunk_bits per block.

                 * Must be consistent with chunks_per_block.

                 */

    int n_erased_blocks;

    int alloc_block;    /* Current block being allocated off */

    u32 alloc_page;

    int alloc_block_finder; /* Used to search for next allocation block */

    /* Object and Tnode memory management */

    void *allocator;

    int n_obj;

    int n_tnodes;

    int n_hardlinks;

    struct yaffs_obj_bucket obj_bucket[YAFFS_NOBJECT_BUCKETS];

    u32 bucket_finder;

    int n_free_chunks;

    /* Garbage collection control */

    u32 *gc_cleanup_list;   /* objects to delete at the end of a GC. */

    u32 n_clean_ups;

    unsigned has_pending_prioritised_gc;    /* We think this device might

                        have pending prioritised gcs */

    unsigned gc_disable;

    unsigned gc_block_finder;

    unsigned gc_dirtiest;

    unsigned gc_pages_in_use;

    unsigned gc_not_done;

    unsigned gc_block;

    unsigned gc_chunk;

    unsigned gc_skip;

    struct yaffs_summary_tags *gc_sum_tags;

    /* Special directories */

    struct yaffs_obj *root_dir;

    struct yaffs_obj *lost_n_found;

    int buffered_block; /* Which block is buffered here? */

    int doing_buffered_block_rewrite;

    struct yaffs_cache *cache;

    int cache_last_use;

    /* Stuff for background deletion and unlinked files. */

    struct yaffs_obj *unlinked_dir; /* Directory where unlinked and deleted

                     files live. */

    struct yaffs_obj *del_dir;  /* Directory where deleted objects are

                    sent to disappear. */

    struct yaffs_obj *unlinked_deletion;    /* Current file being

                            background deleted. */

    int n_deleted_files;    /* Count of files awaiting deletion; */

    int n_unlinked_files;   /* Count of unlinked files. */

    int n_bg_deletions; /* Count of background deletions. */

    /* Temporary buffer management */

    struct yaffs_buffer temp_buffer[YAFFS_N_TEMP_BUFFERS];

    int max_temp;

    int temp_in_use;

    int unmanaged_buffer_allocs;

    int unmanaged_buffer_deallocs;

    /* yaffs2 runtime stuff */

    unsigned seq_number;    /* Sequence number of currently

                    allocating block */

    unsigned oldest_dirty_seq;

    unsigned oldest_dirty_block;

    /* Block refreshing */

    int refresh_skip;   /* A skip down counter.

                 * Refresh happens when this gets to zero. */

    /* Dirty directory handling */

    struct list_head dirty_dirs;    /* List of dirty directories */

    /* Summary */

    int chunks_per_summary;

    struct yaffs_summary_tags *sum_tags;

    /* Statistics */

    u32 n_page_writes;

    u32 n_page_reads;

    u32 n_erasures;

    u32 n_erase_failures;

    u32 n_gc_copies;

    u32 all_gcs;

    u32 passive_gc_count;

    u32 oldest_dirty_gc_count;

    u32 n_gc_blocks;

    u32 bg_gcs;

    u32 n_retried_writes;

    u32 n_retired_blocks;

    u32 n_ecc_fixed;

    u32 n_ecc_unfixed;

    u32 n_tags_ecc_fixed;

    u32 n_tags_ecc_unfixed;

    u32 n_deletions;

    u32 n_unmarked_deletions;

    u32 refresh_count;

    u32 cache_hits;

    u32 tags_used;

    u32 summary_used;

};

这个结构体真是庞大啊,

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 华为mate7忘记开机密码怎么办 华为mate9开机密码忘记怎么办 华为手机系统更新失败怎么办 mate9系统升级后耗电快怎么办 华为荣耀手机耗电快怎么办 荣耀10手机拍照不清晰怎么办 荣耀6x拍照模糊怎么办 华为荣耀P9进水了怎么办 苹果5s手机信号不好怎么办 苹果5s信号不好怎么办? 苹果5s像素不好怎么办 华为mate边缘有缝怎么办 华为mate8边缘有缝怎么办 手机系统占用运行内存大怎么办 安卓手机储存空间不足怎么办 手机显示系统空间不足怎么办 联系人存储已停止运行怎么办 荣耀note8听筒声音小怎么办 红米4x内存不足怎么办 安卓电视内存小怎么办 红米手机运行内存不足怎么办 红米手机存储空间不足怎么办 华为手机储存空间不足怎么办 大麦机顶盒遥控器丢了怎么办 大麦盒子总自动加软件怎么办 小米手机玩王者荣耀卡怎么办 荣耀8青春版信号差怎么办 华为mate8电池不耐用怎么办 华为4x内存小怎么办 发现手机被用过怎么办 华为p8手机声音小怎么办 手机指纹解锁密码忘了怎么办 华为p10黑色掉漆怎么办 金立手机导航信号弱怎么办 手机导航时gps信号弱怎么办 三星手机导航gps信号弱怎么办 小米5导航信号弱怎么办 华为手机导航gps信号弱怎么办 手机屏玻璃裂了怎么办 oppo音量键坏了怎么办 魅蓝手机屏幕碎了怎么办