在开发一些单片机程序时,写应用的人常常会用到读写flash的接口,一些单片机调试的时候并不是很方便,而写应用的人一般不了解flash的底层驱动,这就给调试造成了困难;另外写驱动和写应用为了能同步进行,一般写驱动的人应提供给写应用的人标准的接口。
为了能使写应用的人能在集成IDE下开发代码,并且不受硬件的限制,本文写了一段以文件映射的方式来模拟flash读写的代码,当然大家也可以以读写文件的方式来模拟flash的读写操作。
以下代码仅供学习交流,代码并不太规范,不喜勿喷。
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
unsigned int EEP_BEGIN;
#define EEP_INIT_VAL 0xFF
#define EEP_PAGE_LEN 0x200
#define EEP_PAGE_COUN 128
#define EEP_LEN (EEP_PAGE_LEN*EEP_PAGE_COUN)
#define SETWORD(buffer, val) \
do \
{ \
(buffer)[0] = (unsigned char)((val) >> 8); \
(buffer)[1] = (unsigned char)(val); \
}while(0)
#define SETDWORD(buffer, val) \
do \
{ \
(buffer)[0] = (unsigned char)((val) >> 24); \
(buffer)[1] = (unsigned char)((val) >> 16); \
(buffer)[2] = (unsigned char)((val) >> 8); \
(buffer)[3] = (unsigned char)(val); \
}while(0)
unsigned int _filesize;
static void HexToStr(const unsigned char *buf,int len, char *ptr)
{
for(int i = 0; i < len; i++)
{
sprintf(ptr, "%02X",buf[i]);
ptr += 2;
}
}
static void ArrayToStr(const unsigned char *buf, int len, char *str)
{
int i;
for(i=0; i<len; i++)
{
sprintf(str, "%02X", buf[i]);
str[2] = ' ';
str += 3;
}
*(--str) = '\0';
}
static void StrToArray(char *str, unsigned char *buf, int len)
{
unsigned char tmpbuf[4];
int i;
for(i=0; i<len; i++)
{
sscanf(&str[i*3], "%x", (unsigned int*)tmpbuf);
buf[i] = tmpbuf[0];
}
}
static void AddrToStr(const unsigned int addr, char *str)
{
unsigned char tmpbuf[4];
SETDWORD(tmpbuf, addr);
HexToStr(tmpbuf, 4, str);
str[8] = ':';
str[9] = ' ';
str[10] = '\0';
}
static unsigned int getpos(unsigned int Addr)
{
char AddrStr[11];
unsigned int i = 0;
AddrToStr(Addr, AddrStr);
while(i < EEP_LEN/16-1)
{
if(memcmp(AddrStr, (char*)(EEP_BEGIN+i*59), 8)==0)
return EEP_BEGIN+i*59;
i++;
}
return 0;
}
//创建一个EEP_LEN大小的文件
static int CreatFlashFile(const char *filepath)
{
char AddrStr[10+48];
char DataStr[48];
unsigned char buf[16];
unsigned int addr;
memset(buf, EEP_INIT_VAL, sizeof(buf));
FILE *fp = fopen(filepath, "w");
if(fp == NULL)
return -1;
ArrayToStr(buf, sizeof(buf), DataStr);
for(addr = 0; addr<EEP_LEN; addr+=16)
{
AddrToStr(addr, AddrStr);
strcat(AddrStr, DataStr);
fwrite(AddrStr, sizeof(AddrStr), 1, fp);
fprintf(fp,"%s","\n");
}
fclose(fp);
printf("%s\n", "creat file success.\r\n");
return 0;
}
//映射flash文件,并且修改地址
int InitFlashFile(const char *filepath)
{
struct stat sb;
int fd;
char *addr;
fd = open(filepath, O_RDWR);
if(fd == -1)
return -1;
if(fstat(fd, &sb) == -1)
return -1;
_filesize = (unsigned int)sb.st_size;
printf("file size is %d.\n", _filesize);
addr = mmap(NULL, sb.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if(addr == MAP_FAILED)
return -1;
EEP_BEGIN = (unsigned int)addr;
close(fd);
printf("EEP_BEGIN is %x.\n", (unsigned int)addr);
unsigned int FA;
char AddrStr[10];
for(FA = EEP_BEGIN; FA<EEP_BEGIN+EEP_LEN; FA+=16,addr+=59)
{
AddrToStr(FA, AddrStr);
memcpy(addr, AddrStr, sizeof(AddrStr));
}
if(msync((char*)EEP_BEGIN, sb.st_size, MS_SYNC) < 0)
return -1;
printf("%s\n", "mmap success.");
return 0;
}
void EraseFlashPage(unsigned int Addr)
{
char AddrStr[10+48];
char DataStr[48];
unsigned int FileAddr;
unsigned char buf[16];
if(Addr%16)
return;
if((Addr+EEP_PAGE_LEN) > ((unsigned int)EEP_BEGIN+EEP_LEN)) //
return;
FileAddr = getpos(Addr);
if(FileAddr == 0)
{
printf("%s\n", "get poserr.");
return;
}
unsigned char i;
memset(buf, EEP_INIT_VAL, 16);
for(i=0;i<EEP_PAGE_LEN/16; i++)
{
AddrToStr(Addr+i*16, AddrStr);
ArrayToStr(buf, 16, DataStr);
strcat(AddrStr, DataStr);
memcpy((char*)(FileAddr+i*59), AddrStr, sizeof(AddrStr));
}
msync((char*)EEP_BEGIN, _filesize, MS_SYNC);
}
void WriteFlashPage(unsigned int Addr, const unsigned char *buf)
{
char AddrStr[10+48];
char DataStr[48];
unsigned int FileAddr;
if(Addr%16)
return;
if((Addr+EEP_PAGE_LEN) > ((unsigned int)EEP_BEGIN+EEP_LEN)) //
return;
FileAddr = getpos(Addr);
if(FileAddr == 0)
{
printf("%s\n", "get poserr.");
return;
}
unsigned char i;
for(i=0;i<EEP_PAGE_LEN/16; i++)
{
AddrToStr(Addr+i*16, AddrStr);
ArrayToStr(buf+i*16, 16, DataStr);
strcat(AddrStr, DataStr);
memcpy((char*)(FileAddr+i*59), AddrStr, sizeof(AddrStr));
}
msync((char*)EEP_BEGIN, _filesize, MS_SYNC);
}
void ReadFlashPage(unsigned int Addr, unsigned char *buf)
{
char tmpbuf[59];
if(Addr%16)
return;
if ((Addr + EEP_PAGE_LEN) > ((unsigned int)EEP_BEGIN + EEP_LEN))
return;
unsigned int FileAddr = getpos(Addr);
unsigned char i;
unsigned char Tbuf[16];
for(i=0;i<EEP_PAGE_LEN/16; i++)
{
memcpy(tmpbuf, (char*)(FileAddr+i*59), 59);
StrToArray(&tmpbuf[10], Tbuf, 16);
memcpy(buf+i*16, Tbuf, 16);
}
}
int main(int argc, char *argv[])
{
if(argc < 2)
{
printf("%s\n", "value cnt err.");
return -1;
}
if(CreatFlashFile(argv[1])<0)
{
printf("%s\n", "creat file error");
return -1;
}
if(InitFlashFile(argv[1])<0)
{
printf("%s\n", "init file error");
return -1;
}
unsigned char buf[EEP_PAGE_LEN];
unsigned char rbuf[EEP_PAGE_LEN];
unsigned int i;
for(i=0; i<EEP_PAGE_LEN; i++)
buf[i] = i;
WriteFlashPage(EEP_BEGIN+EEP_PAGE_LEN, buf);
ReadFlashPage(EEP_BEGIN+EEP_PAGE_LEN, rbuf);
if(memcmp(buf, rbuf, EEP_PAGE_LEN) != 0)
{
printf("%s\n", "WR flash error.");
return -1;
}
EraseFlashPage(EEP_BEGIN+EEP_PAGE_LEN);
ReadFlashPage(EEP_BEGIN+EEP_PAGE_LEN, rbuf);
for(i=0; i<EEP_PAGE_LEN; i++)
if(rbuf[i] != 0xff)
{
printf("%s\n", "erase flash error.");
return -1;
}
printf("%s\n", "init flash success.");
if(munmap((char*)EEP_BEGIN, _filesize) < 0)
{
printf("%s\n", "munmap err.");
return -1;
}
exit(EXIT_SUCCESS);
}