早年写的笔记,压箱底了,翻出来晒晒
目 录
在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。
因为zimage,ramdisk,redboot的烧录都是二进制的,所以使用open,write,read函数比较合适。下面以写入redboot分区为例讲解。
使用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文件。
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表示实时写入。
写入函数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);
上面的程序的含义就是从头将文件全部写入了。
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);
}
/***************************************************************/
/***************************************************************/
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
/***************************************************************/