在uclinux中读写flash分区

在uclinux中读写flash分区

早年写的笔记,压箱底了,翻出来晒晒


目          录

在uclinux中读写flash分区...1

实验环境...1

配置编译内核...1

Flash分区操作函数...3

1. 载入待烧录文件...3

2. 打开分区...4

3. 写入分区...5

附源代码和makefile.6

fwUpgrade.c文件内容...6

Makefile内容...10

 

实验环境

u  IXDP425 266Mhz 64Mram 16M flash

u  FC4: kernel 2.6.11-1.1369_FC4smp(FC6 也行),安装在虚拟机上

u  arm-linux-tools-20051123.tar.gz: gcc 3.4.4编译器

u  snapgear-3.5.0.tar.gz:  snapgear发布的uClinux包

 

配置编译内核

在Device Drivers-->Memory Technology Devices(MTD)àMapping drivers for chip access

选中supportnon-linear mapping of flash chips,就会出现IXP4XX的选项,选中之后就会在/proc/mtd里面就可以看到分区信息。

       编译完成之后下载到板子上,板子启动后进入linux系统,执行# cat /proc/mtd会打印如下信息:

#cat /proc/mtd

dev:    size  erasesize  name

mtd0: 0004000000020000 "RedBoot"

mtd1: 0010000000020000 "zImage"

mtd2: 0068000000020000 "ramdisk"

mtd3: 0006000000020000 "unallocated space"

mtd4: 0004000000020000 "G8000cfg"

mtd5: 0076000000020000 "unallocated space"

mtd6: 0000100000020000 "RedBoot config"

mtd7: 0002000000020000 "FIS directory"

 

另外一种查看mtd分区的方法是在redboot启动的时候,输入fis list可以找到信息。

RedBoot> fislist

Name              FLASH addr  Mem addr   Length      Entry point

RedBoot           0x50000000  0x50000000 0x00040000  0x00000000

RedBootconfig    0x50FC0000  0x50FC0000 0x00001000  0x00000000

FISdirectory     0x50FE0000  0x50FE0000 0x00020000  0x00000000

ramdisk           0x50140000  0x00800000 0x00680000  0x00800000

zImage            0x50040000  0x01600000 0x00100000  0x01600000

G8000cfg          0x50820000  0x01A00000  0x00040000 0x00800000

       根据分区起始地址的大小可以看出ramdisk分区是第三个,而mtd从0开始编号,那么ramdisk分区就是mtd2。

 

Flash分区操作函数

因为zimage,ramdisk,redboot的烧录都是二进制的,所以使用open,write,read函数比较合适。下面以写入redboot分区为例讲解。

1. 载入待烧录文件

使用mmap来载入烧录文件。mmap函数的定义如下:

MMAP(2)                    Linux Programmer’sManual                   MMAP(2)

 

NAME

       mmap,munmap - map or unmap files or devices into memory

 

SYNOPSIS

       #include<sys/mman.h>

 

       void*mmap(void *start, size_t length, int prot, int flags,

                 int fd, off_t offset);

 

       intmunmap(void *start, size_t length);

 

DESCRIPTION

       The  mmap() function  asks to map length bytesstarting at offset offset from the file (or other object)

      specified by the file descriptor fd into memory, preferably at addressstart.  This latter address  is  a

      hint  only,  and is  usually specified as 0.  The actual place where the object is mappedis returned by

       mmap().

 

PROT_READ Pages may be read.

MAP_PRIVATE

                 Create a private copy-on-write mapping. Stores to the region do not affect the original file.

                 It is unspecified whether changes made to the file after the mmap() callare  visible  in  the

                 mapped region.

 

具体的程序如下:

    /* map file */

char *str_image=redboot.bin

    if ((fd=open(str_image,O_RDONLY))<0)

    return rc;

   

    file_len=lseek(fd,0,SEEK_END); /* get filesize */

       

    if ((file_addr=(char *)mmap(0, file_len,PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)

    {

    printf("mmaperror \n");

    close(fd);

    return rc;

    }

 

其中str_image是文件名,lseek的目的是为了得到文件的大小。mmap(0,file_len, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)的含义就是从文件头开始,在内存里映射redboot.bin文件。

 

2. 打开分区

Open的函数说明如下:

 

OPEN(2)                          System calls                          OPEN(2)

                                                                                                                            

NAME

       open,creat - open and possibly create a file or device

                                                                                                                             

SYNOPSIS

       #include<sys/types.h>

       #include<sys/stat.h>

       #include<fcntl.h>

                                                                                                                             

       intopen(const char *pathname, int flags);

       intopen(const char *pathname, int flags, mode_t mode);

       intcreat(const char *pathname, mode_t mode);

 

 

具体的程序如下:

char *mtd = "/dev/mtdblock0";

fmtd=open(mtd,O_WRONLY| O_SYNC)

 

这样分区就打开了,O_WRONLY是只写模式,O_SYNC表示实时写入。

 

3. 写入分区

写入函数write的说明如下:

WRITE (2)                   Linux Programmer’sManual                  WRITE(2)

 

NAME

       write -write to a file descriptor

 

SYNOPSIS

       #include<unistd.h>

 

       ssize_twrite(int fd, const void *buf, size_t count);

 

DESCRIPTION

      write  writes  up to  count  bytes to the file referenced by the file

      descriptor fd from the buffer starting at buf.  POSIX requires  that  a

      read()  which  can be  proved  to occur  after a write() hasreturned

       returnsthe new data.  Note that not all filesystems  are  POSIX con-

       forming.

 

具体的程序如下:

fflush(stdout);

flock(fmtd,LOCK_EX);

if (write(fmtd,0,file_len) < file_attr[0].length)

{

printf("upgrade failed!\n");

}

    flock(fmtd, LOCK_UN);

    close(fmtd);

      

       上面的程序的含义就是从头将文件全部写入了。

 

附源代码和makefile

fwUpgrade.c文件内容

fwUpgrade.c中有一些内容是读取debug用的,会有一些冗余的代码。编译完成之后,输入fwUpgradefilename.bin命令,就会将filename.bin烧录到mtd0,也就是redboot分区。

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

#include<stdio.h>

#include<errno.h>

#include<stdlib.h>

#include<string.h>

#include<ctype.h>

#include<unistd.h>

#include<fcntl.h>

#include<sys/file.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<sys/sendfile.h>

#include<sys/mman.h>

 

 

structFileAttr1{

    int start_address;

    int length;

};

 

typedefstruct FileAttr1 FileAttr;

//0update

//1sign

//2zImage (start_address += update.start_address)

//3ramdisk

FileAttrfile_attr[4];

char*mtd_file[3]={"/dev/mtdblock0","/dev/mtdblock1","/dev/mtdblock2"};

char* file_addr;  // mmap address

 

intUpgradeImage(char filename[],int fileindex, int mode)

{

     char*mtd;

    int fmtd=-1;

    int rc=-1;

    int total=0, step=0, i=0;

    char redboot_print[200];

    int j = 0;

    int pi = 0;

    //this is specially for redboot

    mtd=mtd_file[0];

   

    if((fmtd=open(mtd, O_RDONLY| O_SYNC))<0)

    {

        printf( "Error to open the mtd%s:%s!\n", mtd, strerror(errno));

        return rc;

    }

 

    printf("UpgradeImage ln 10: fmtd%d\n", fmtd);

       

    memset(redboot_print, 0, 200);

    j = read(fmtd, redboot_print, 200);

 

    printf("UpgradeImage ln 30redboot_print : %s, j = %d\n", redboot_print, j);

 

    for(pi = 0; pi < 200; pi++)

    {

        printf("%x,",redboot_print[pi]);

   

    }

       

    close(fmtd);

 

    fmtd=open(mtd, O_WRONLY| O_SYNC);

   

    if(fmtd < 0)

    {

        printf( "Error to open the mtd%s:%s!\n", mtd, strerror(errno));

        return rc;

    }

 

    printf("\nln 35 show redboot_printagain\n");

 

    memset(redboot_print, 0, 200);

    j = read(fmtd, redboot_print, 200);

 

    for(pi = 0; pi < 200; pi++)

    {

        printf("%x,",redboot_print[pi]); 

    }

 

    printf("\nUpgrade %s\n",mtd);

    printf("[Start");

    fflush(stdout);

   

    flock(fmtd, LOCK_EX); 

   

#if1

        if(write(fmtd,file_addr+file_attr[0].start_address, file_attr[0].length) <file_attr[0].length)

        {

            printf("upgradefailed!\n");

        }

        else

            rc =0;

#endif/* NEVER */

   

    flock(fmtd, LOCK_UN);

   

    printf("End]\n");

    close(fmtd);

   

    fflush(stdout);

   

    flock(fmtd, LOCK_EX);

    if((fmtd=open(mtd, O_RDONLY| O_SYNC))<0)

    //if((fmtd=open(mtd, O_RDWR| O_SYNC))<0)

    {

        printf( "Error to open the mtd%s:%s!\n", mtd, strerror(errno));

        return rc;

    }

   

    memset(redboot_print, 0, 200);

    j = read(fmtd, redboot_print, 200);

 

    for(pi = 0; pi < 200; pi++)

    {

        printf("%x,",redboot_print[pi]);

   

    }

    flock(fmtd, LOCK_UN);

    fflush(stdout);

    close(fmtd);

 

    printf("End]\n");

    return rc;

}

intupgrade(char* str_image, int mode)

{

    int rc = -1;

    int fd;

    int file_len;

       

//mmap

        /*map file */

    if ((fd=open(str_image,O_RDONLY))<0)

    return rc;

   

    file_len=lseek(fd,0,SEEK_END); /* get filesize */

       

    if ((file_addr=(char *)mmap(0, file_len,PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)

    {

    printf("mmaperror \n");

    close(fd);

    return rc;

    }       

       

//upgrade

 

    file_attr[0].length = file_len;

    file_attr[0].start_address = 0;

    rc = UpgradeImage(str_image,2, 1);

   

    munmap(file_addr, file_len);

    close(fd);     

 

    return rc;

}

 

 

intmain(int argc , char **argv)

{

    int rc;

       

    //argv[1] is the file name here

    printf("file = %s, mode =%d",argv[1], (*argv[2] - 48));

    rc = upgrade(argv[1], argv[2]);

    exit(rc);

}

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

 

Makefile内容

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

KERNEL_UC_VERSION = linux-2.6.x

C_FLAGS = -mbig-endian-I/home/linuxuser/snapgear/$(KERNEL_UC_VERSION)/include  -Wall -Wstrict-prototypes -O-fno-strict-aliasing -fno-common -Uarm -fno-common -pipe -mapcs-32 -D__LINUX_ARM_ARCH__=5-mcpu=xscale -mtune=xscale -malignment-traps

 

CC=/home/linuxuser/snapgear/tools/ucfront-gccarm-linux-gcc

 

arm:

       $(CC)$(C_FLAGS) -o fwUpgrade fwUpgrade.c

clean:

       rm-f *.o

       rmfwUpgrade

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

 

你可能感兴趣的:(在uclinux中读写flash分区)