912 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			912 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
 | 
						||
/*
 | 
						||
 | 
						||
  C语言库函数实现
 | 
						||
 | 
						||
*/
 | 
						||
 | 
						||
 | 
						||
#include "stdio.h"
 | 
						||
#include "ff.h"
 | 
						||
#include "errno.h"
 | 
						||
#include "stdlib.h"
 | 
						||
#include "string.h"
 | 
						||
#include "libc.h"
 | 
						||
#include "flash_manager.h"
 | 
						||
#include "bsp_init.h"
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
// 常规文件
 | 
						||
#define FILE_TYPE_FILE        0
 | 
						||
// 设备文件
 | 
						||
#define FILE_TYPE_DEVICE      1
 | 
						||
// 内存文件
 | 
						||
#define FILE_TYPE_MEM         2
 | 
						||
 | 
						||
// 定义内存文件大小
 | 
						||
#define MEM_FILE_SIZE         (100*1024)
 | 
						||
 | 
						||
 | 
						||
 | 
						||
// 定义flash中的文件
 | 
						||
typedef struct
 | 
						||
{
 | 
						||
	u32 addr;
 | 
						||
	u32 ptr;
 | 
						||
	u32 size;
 | 
						||
}libc_flash_file;
 | 
						||
 | 
						||
 | 
						||
// 定义常规文件
 | 
						||
typedef struct
 | 
						||
{
 | 
						||
	libc_flash_file flash;
 | 
						||
	FILINFO file_info;
 | 
						||
	FIL file;
 | 
						||
  
 | 
						||
}file_struct_private;
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
// 定义内存文件
 | 
						||
typedef struct
 | 
						||
{
 | 
						||
  uint8_t data[MEM_FILE_SIZE];
 | 
						||
  int size;
 | 
						||
  int ptr;
 | 
						||
}libc_mem_file;
 | 
						||
 | 
						||
 | 
						||
 | 
						||
// 定义文件结构体
 | 
						||
struct __FILE
 | 
						||
{
 | 
						||
  int type;
 | 
						||
  file_struct_private *ptr;
 | 
						||
  const libc_device_file *dev;
 | 
						||
  libc_mem_file *mem;
 | 
						||
};
 | 
						||
 | 
						||
// 寻找指定名称的设备
 | 
						||
extern const unsigned int Load$$libc_dev$$Base;
 | 
						||
extern const unsigned int Load$$libc_dev$$Limit;
 | 
						||
const libc_device_file *libc_find_dev(const char *name)
 | 
						||
{
 | 
						||
  libc_device_file *start=(libc_device_file *)&Load$$libc_dev$$Base;
 | 
						||
  libc_device_file *end=(libc_device_file *)&Load$$libc_dev$$Limit;
 | 
						||
  
 | 
						||
  libc_device_file *ptr=0;
 | 
						||
  for(ptr=start;ptr<end;ptr++)
 | 
						||
  {
 | 
						||
    if(strcmp(ptr->name,name)==0)
 | 
						||
      return ptr;
 | 
						||
  }
 | 
						||
  return NULL;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
// 基本输入输出流
 | 
						||
FILE __stdin={
 | 
						||
  .type=FILE_TYPE_DEVICE,
 | 
						||
  .dev=0,
 | 
						||
};
 | 
						||
FILE __stdout={
 | 
						||
  .type=FILE_TYPE_DEVICE,
 | 
						||
  .dev=0,
 | 
						||
};
 | 
						||
FILE __stderr={
 | 
						||
  .type=FILE_TYPE_DEVICE,
 | 
						||
  .dev=0,
 | 
						||
};
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
static int libc_init(void)
 | 
						||
{
 | 
						||
  freopen("usart","r+",stdin);
 | 
						||
  freopen("usart","r+",stdout);
 | 
						||
  freopen("usart","r+",stderr);
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 | 
						||
// extern_init(libc,libc_init);
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
// 删除文件,返回0成功
 | 
						||
int remove(const char * filename)
 | 
						||
{
 | 
						||
  if (f_unlink(filename)==FR_OK)
 | 
						||
    return 0;
 | 
						||
  else
 | 
						||
    return -1;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
//重命名,返回0成功
 | 
						||
int rename(const char * old_, const char * new_)
 | 
						||
{
 | 
						||
  if (f_rename (old_,new_)==FR_OK)
 | 
						||
    return 0;
 | 
						||
  else
 | 
						||
    return -1;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// 在指定流上创建临时文件
 | 
						||
static FILE *tmpfile_s(FILE * stream)
 | 
						||
{
 | 
						||
  FILE *file=stream;
 | 
						||
  if(file==NULL) file=calloc (1,sizeof (FILE));
 | 
						||
  file->type=FILE_TYPE_MEM;
 | 
						||
  
 | 
						||
  file->mem=calloc(1,sizeof(libc_mem_file));
 | 
						||
  file->mem->size=MEM_FILE_SIZE;
 | 
						||
 | 
						||
  return file;
 | 
						||
}
 | 
						||
 | 
						||
// 创建临时文件,在文件关闭时自动删除
 | 
						||
FILE *tmpfile(void)
 | 
						||
{
 | 
						||
  return tmpfile_s(NULL);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// 返回一个和现有文件名不同的字符串,这里始终返回 NULL
 | 
						||
char *tmpnam(char * s)
 | 
						||
{
 | 
						||
  return NULL;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// 关闭文件,返回0成功
 | 
						||
int fclose(FILE * stream)
 | 
						||
{
 | 
						||
  FILE * file=stream;
 | 
						||
	if (file)
 | 
						||
	{
 | 
						||
    if(file->ptr)
 | 
						||
    {
 | 
						||
      if (file->ptr->flash.size==0)
 | 
						||
        f_close(&file->ptr->file);
 | 
						||
      free(file->ptr);
 | 
						||
      file->ptr=NULL;
 | 
						||
    }
 | 
						||
    if(file->mem)
 | 
						||
    {
 | 
						||
      free(file->mem);
 | 
						||
      file->mem=NULL;
 | 
						||
    }
 | 
						||
    if(file->dev)
 | 
						||
    {
 | 
						||
      if(file->dev->close)
 | 
						||
        file->dev->close();
 | 
						||
      file->dev=NULL;
 | 
						||
    }
 | 
						||
    if((file!=stdin)&&(file!=stdout)&&(file!=stderr))
 | 
						||
    {
 | 
						||
      // 基本输入输出流使用的是静态内存
 | 
						||
      free(file);
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
      // 设置为初始流设备
 | 
						||
      // freopen("uart5","r+",file);
 | 
						||
    }
 | 
						||
    return 0;
 | 
						||
	}
 | 
						||
	return -1;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// 刷新,返回0成功
 | 
						||
int fflush(FILE * stream)
 | 
						||
{
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 | 
						||
int ferror(FILE * stream)
 | 
						||
{
 | 
						||
	return 0;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
// 由字符得到打开类型
 | 
						||
static BYTE f_get_mode(const char *mode)
 | 
						||
{
 | 
						||
  typedef struct{
 | 
						||
    const char *mode;
 | 
						||
    BYTE mb;
 | 
						||
  }m_item;
 | 
						||
  
 | 
						||
  m_item items[]={
 | 
						||
    {"r",FA_READ},//open text file for reading
 | 
						||
    {"w",FA_WRITE},//create text file for writing, or truncate to zero length
 | 
						||
    {"a",FA_OPEN_ALWAYS|FA_OPEN_APPEND|FA_WRITE},//append; open text file or create for writing at eof
 | 
						||
    {"rb",FA_READ},//open binary file for reading
 | 
						||
    {"wb",FA_WRITE},//create binary file for writing, or truncate to zero length
 | 
						||
    {"ab",FA_OPEN_ALWAYS|FA_OPEN_APPEND|FA_WRITE},//append; open binary file or create for writing at eof
 | 
						||
    {"r+",FA_READ|FA_WRITE},//open text file for update (reading and writing)
 | 
						||
    {"w+",FA_CREATE_NEW|FA_READ|FA_WRITE},//create text file for update, or truncate to zero length
 | 
						||
    {"a+",FA_OPEN_ALWAYS|FA_OPEN_APPEND|FA_READ|FA_WRITE},//append; open text file or create for update, writing at eof
 | 
						||
    {"rb+",FA_READ|FA_WRITE},//open binary file for update (reading and writing)
 | 
						||
    {"wb+",FA_CREATE_NEW|FA_READ|FA_WRITE},//create binary file for update, or truncate to zero length
 | 
						||
    {"ab+",FA_OPEN_ALWAYS|FA_OPEN_APPEND|FA_READ|FA_WRITE},//append; open binary file or create for update, writing at eof
 | 
						||
    {NULL,NULL},
 | 
						||
  };
 | 
						||
  
 | 
						||
  for(int i=0;items[i].mode;i++)
 | 
						||
  {
 | 
						||
    if(strcmp(items[i].mode,mode)==0)
 | 
						||
      return items[i].mb;
 | 
						||
  }
 | 
						||
  return FA_READ;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
// 在指定流上打开文件
 | 
						||
static FILE *fopen_s(const char * filename,const char * mode,FILE *stream)
 | 
						||
{
 | 
						||
	FILE *file=stream;
 | 
						||
  if(file==NULL)
 | 
						||
  file=calloc (1,sizeof(FILE));
 | 
						||
  file_struct_private *file_p=NULL;
 | 
						||
	u8 ret=0;
 | 
						||
  
 | 
						||
  // 首先查找同名设备
 | 
						||
  file->type=FILE_TYPE_DEVICE;
 | 
						||
  file->dev=libc_find_dev(filename);
 | 
						||
  if(file->dev!=NULL)
 | 
						||
  {
 | 
						||
    if(file->dev->open) file->dev->open();
 | 
						||
    return file;
 | 
						||
  }
 | 
						||
	
 | 
						||
  file->type=FILE_TYPE_FILE;
 | 
						||
	if (filename[0]=='0'&&filename[1]==':')
 | 
						||
	{
 | 
						||
    file_p=calloc (1,sizeof (file_struct_private));
 | 
						||
		ret=f_stat (filename,&file_p->file_info);
 | 
						||
		if (ret==FR_OK)
 | 
						||
		{
 | 
						||
			f_open(&file_p->file,filename,f_get_mode(mode));
 | 
						||
      file->ptr=file_p;
 | 
						||
		}
 | 
						||
		else
 | 
						||
		{
 | 
						||
      free(file_p);
 | 
						||
      file_p=NULL;
 | 
						||
			free(file);
 | 
						||
			file=NULL;
 | 
						||
		}
 | 
						||
	}
 | 
						||
	else
 | 
						||
	{
 | 
						||
    file_p=calloc (1,sizeof (file_struct_private));
 | 
						||
		if (file_p->flash.addr= FLASH_FindFile((char *)filename,&file_p->flash.size),file_p->flash.addr==0)
 | 
						||
		{
 | 
						||
      free(file_p);
 | 
						||
      file_p=NULL;
 | 
						||
			free(file);
 | 
						||
			file=NULL;
 | 
						||
		}
 | 
						||
    else
 | 
						||
    {
 | 
						||
      file->ptr=file_p;
 | 
						||
    }
 | 
						||
	}
 | 
						||
	return (FILE *)file;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// 打开文件
 | 
						||
FILE *fopen(const char * filename,const char * mode)
 | 
						||
{
 | 
						||
  return fopen_s(filename,mode,NULL);
 | 
						||
}
 | 
						||
 | 
						||
// 把新的文件名和流关联,输出新的流
 | 
						||
// 如果filename==NULL,则创建一个内存文件
 | 
						||
FILE *freopen(const char * filename, const char * mode, FILE * stream)
 | 
						||
{
 | 
						||
  FILE * file=stream;
 | 
						||
  if(file==NULL) return NULL;
 | 
						||
  
 | 
						||
  // 在本例中只允许修改基本输入输出流
 | 
						||
  if((file!=stdin)&&(file!=stdout)&&(file!=stderr)) return NULL;
 | 
						||
  
 | 
						||
  // 首先尝试关闭与流关联的文件
 | 
						||
  fclose(stream);
 | 
						||
  
 | 
						||
  // 把新文件关联到流
 | 
						||
  if(filename!=NULL)
 | 
						||
    return fopen_s(filename,mode,stream);
 | 
						||
  else
 | 
						||
    return tmpfile_s(stream);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// 设置缓冲区,返回0成功
 | 
						||
int setvbuf(FILE * stream, char * buf, int mode, size_t size)
 | 
						||
{
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 | 
						||
void setbuf(FILE * stream,char * buf)
 | 
						||
{
 | 
						||
  if(buf)
 | 
						||
    setvbuf(stream,buf,_IOFBF,BUFSIZ);
 | 
						||
  else
 | 
						||
    setvbuf(stream,buf,_IONBF,BUFSIZ);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
// 设备文件获取一个字符
 | 
						||
static int fgetc_dev(FILE * stream)
 | 
						||
{
 | 
						||
  int c=EOF;
 | 
						||
  const libc_device_file *dev=stream->dev;
 | 
						||
  if(dev)
 | 
						||
  {
 | 
						||
    if(dev->putc)
 | 
						||
    {
 | 
						||
      c=dev->getc();
 | 
						||
      return c;
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return c;
 | 
						||
}
 | 
						||
 | 
						||
// 内存文件获取一个字符
 | 
						||
static int fgetc_mem(FILE * stream)
 | 
						||
{
 | 
						||
  int c=EOF;
 | 
						||
  libc_mem_file *mem=stream->mem;
 | 
						||
  if(mem)
 | 
						||
  {
 | 
						||
    if(mem->ptr<mem->size)
 | 
						||
    {
 | 
						||
      c=mem->data[mem->ptr];
 | 
						||
      mem->ptr++;
 | 
						||
      return c;
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return c;
 | 
						||
}
 | 
						||
 | 
						||
// 普通文件获取一个字符
 | 
						||
static int fgetc_fil(FILE * stream)
 | 
						||
{
 | 
						||
  int c=EOF;
 | 
						||
  uint8_t d;
 | 
						||
  if(fread(&d, 1, 1, stream)==1)
 | 
						||
    c=d;
 | 
						||
  return c;
 | 
						||
}
 | 
						||
 | 
						||
static int (*const g_getc_funs[3])(FILE *)={
 | 
						||
  fgetc_fil,
 | 
						||
  fgetc_dev,
 | 
						||
  fgetc_mem,
 | 
						||
};
 | 
						||
 | 
						||
 | 
						||
// 获取文件流中的一个字符
 | 
						||
int fgetc(FILE * stream)
 | 
						||
{
 | 
						||
  int c=EOF;
 | 
						||
  if(stream)
 | 
						||
  {
 | 
						||
    c=g_getc_funs[stream->type](stream);
 | 
						||
  }
 | 
						||
  return c;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
// 设备文件写入一个字符
 | 
						||
static int fputc_dev(int c,FILE * stream)
 | 
						||
{
 | 
						||
  const libc_device_file *dev=stream->dev;
 | 
						||
  if(dev)
 | 
						||
  {
 | 
						||
    if(dev->putc)
 | 
						||
    {
 | 
						||
      dev->putc(c);
 | 
						||
      return c;
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return EOF;
 | 
						||
}
 | 
						||
 | 
						||
// 内存文件写入一个字符
 | 
						||
static int fputc_mem(int c,FILE * stream)
 | 
						||
{
 | 
						||
  libc_mem_file *mem=stream->mem;
 | 
						||
  if(mem)
 | 
						||
  {
 | 
						||
    if(mem->ptr<mem->size)
 | 
						||
    {
 | 
						||
      mem->data[mem->ptr]=c;
 | 
						||
      mem->ptr++;
 | 
						||
      return c;
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return EOF;
 | 
						||
}
 | 
						||
 | 
						||
// 普通文件写入一个字符
 | 
						||
static int fputc_fil(int c,FILE * stream)
 | 
						||
{
 | 
						||
  uint8_t d=c;
 | 
						||
  if(fwrite(&d, 1, 1, stream)==1)
 | 
						||
    return c;
 | 
						||
  else
 | 
						||
    return EOF;
 | 
						||
}
 | 
						||
 | 
						||
static int (*const g_putc_funs[3])(int,FILE *)={
 | 
						||
  fputc_fil,
 | 
						||
  fputc_dev,
 | 
						||
  fputc_mem,
 | 
						||
};
 | 
						||
 | 
						||
 | 
						||
// 写入一个字符
 | 
						||
int fputc(int c, FILE * stream)
 | 
						||
{
 | 
						||
  if(stream)
 | 
						||
  {
 | 
						||
    return g_putc_funs[stream->type](c,stream);
 | 
						||
  }
 | 
						||
  return EOF;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// 普通文件读取
 | 
						||
static size_t fread_fil(void * ptr, size_t size, size_t nmemb, FILE * stream)
 | 
						||
{
 | 
						||
  file_struct_private * file=stream->ptr;
 | 
						||
	if (file)
 | 
						||
	{
 | 
						||
		if (file->flash.size==0)
 | 
						||
		{
 | 
						||
			UINT rb=0;
 | 
						||
			f_read (&file->file,ptr,size*nmemb,&rb);
 | 
						||
			return rb/size;
 | 
						||
		}
 | 
						||
		else
 | 
						||
		{
 | 
						||
			u32 read_size=size*nmemb;
 | 
						||
			if (read_size>file->flash.size-file->flash.ptr)
 | 
						||
				read_size=file->flash.size-file->flash.ptr;
 | 
						||
			FLASH_ReadData(ptr,file->flash.ptr+file->flash.addr,size*nmemb);
 | 
						||
			file->flash.ptr+=read_size;
 | 
						||
			return read_size/size;
 | 
						||
		}
 | 
						||
	}
 | 
						||
	return 0;
 | 
						||
}
 | 
						||
 | 
						||
// 设备文件读取
 | 
						||
static size_t fread_dev(void * ptr, size_t size, size_t nmemb, FILE * stream)
 | 
						||
{
 | 
						||
  const libc_device_file *dev=stream->dev;
 | 
						||
  
 | 
						||
  if(dev)
 | 
						||
  {
 | 
						||
    // 暂时不支持设备文件读取
 | 
						||
  }
 | 
						||
  
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 | 
						||
// 内存文件读取
 | 
						||
static size_t fread_mem(void * ptr, size_t size, size_t nmemb, FILE * stream)
 | 
						||
{
 | 
						||
  libc_mem_file *mem=stream->mem;
 | 
						||
 | 
						||
  if(mem)
 | 
						||
  {
 | 
						||
    // 暂时不支持内存文件读取
 | 
						||
  }
 | 
						||
  
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
static size_t (*const g_read_funs[3])(void *,size_t,size_t,FILE *)={
 | 
						||
  fread_fil,
 | 
						||
  fread_dev,
 | 
						||
  fread_mem,
 | 
						||
};
 | 
						||
 | 
						||
// 读取文件
 | 
						||
size_t fread(void * ptr, size_t size, size_t nmemb, FILE * stream)
 | 
						||
{
 | 
						||
  if(stream)
 | 
						||
  {
 | 
						||
    return g_read_funs[stream->type](ptr,size,nmemb,stream);
 | 
						||
  }
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
// 设备文件写入
 | 
						||
static size_t fwrite_dev(const void * ptr, size_t size, size_t nmemb, FILE * stream)
 | 
						||
{
 | 
						||
  const libc_device_file *dev=stream->dev;
 | 
						||
  
 | 
						||
  if(dev)
 | 
						||
  {
 | 
						||
    if(dev->write)
 | 
						||
    {
 | 
						||
      return dev->write(ptr,size*nmemb)/size;
 | 
						||
    }
 | 
						||
  }
 | 
						||
  
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 | 
						||
// 内存文件写入
 | 
						||
static size_t fwrite_mem(const void * ptr, size_t size, size_t nmemb, FILE * stream)
 | 
						||
{
 | 
						||
  libc_mem_file *mem=stream->mem;
 | 
						||
 | 
						||
  if(mem)
 | 
						||
  {
 | 
						||
    // 暂时不支持内存文件写入
 | 
						||
  }
 | 
						||
  
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 | 
						||
// 普通文件写入
 | 
						||
static size_t fwrite_fil(const void * ptr, size_t size, size_t nmemb, FILE * stream)
 | 
						||
{
 | 
						||
  file_struct_private * file=stream->ptr;
 | 
						||
	if (file)
 | 
						||
	{
 | 
						||
		if (file->flash.size==0)
 | 
						||
		{
 | 
						||
			UINT rb=0;
 | 
						||
			f_write(&file->file,ptr,size*nmemb,&rb);
 | 
						||
			return nmemb;
 | 
						||
		}
 | 
						||
		else
 | 
						||
		{
 | 
						||
			//flash暂时不支持写入
 | 
						||
			return 0;
 | 
						||
		}
 | 
						||
	}
 | 
						||
	return 0;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
static size_t (*const g_write_funs[3])(const void *,size_t,size_t,FILE *)={
 | 
						||
  fwrite_fil,
 | 
						||
  fwrite_dev,
 | 
						||
  fwrite_mem,
 | 
						||
};
 | 
						||
 | 
						||
 | 
						||
// 写入文件
 | 
						||
size_t fwrite(const void * ptr, size_t size, size_t nmemb, FILE * stream)
 | 
						||
{
 | 
						||
  if(stream)
 | 
						||
  {
 | 
						||
    return g_write_funs[stream->type](ptr,size,nmemb,stream);
 | 
						||
  }
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// 获取文件位置,成功返回0
 | 
						||
int fgetpos(FILE * stream, fpos_t *pos)
 | 
						||
{
 | 
						||
  return 1;
 | 
						||
}
 | 
						||
 | 
						||
// 设置文件位置,成功返回0
 | 
						||
int fsetpos(FILE * stream, const fpos_t * pos)
 | 
						||
{
 | 
						||
  return 1;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
// 普通文件设置文件偏移,成功返回0
 | 
						||
static int fseek_fil(FILE * stream, long int offset, int whence)
 | 
						||
{
 | 
						||
  file_struct_private * file=stream->ptr;
 | 
						||
	if (file)
 | 
						||
	{
 | 
						||
		if (file->flash.size==0)
 | 
						||
		{
 | 
						||
			//文件开头
 | 
						||
			if (SEEK_SET==whence)
 | 
						||
			{
 | 
						||
				if (f_lseek(&file->file,offset)==FR_OK)
 | 
						||
					return 0;
 | 
						||
			}
 | 
						||
			else if (SEEK_END==whence)
 | 
						||
			{
 | 
						||
				//这时offset为负数
 | 
						||
				offset=file->file_info.fsize+offset;
 | 
						||
				if (f_lseek(&file->file,offset)==FR_OK)
 | 
						||
					return 0;
 | 
						||
			}
 | 
						||
			else if (SEEK_CUR==whence)
 | 
						||
			{
 | 
						||
				//这时offset可正可负
 | 
						||
        long int pos=f_tell(&file->file);
 | 
						||
				offset=pos+offset;
 | 
						||
				if (f_lseek(&file->file,offset)==FR_OK)
 | 
						||
					return 0;
 | 
						||
			}
 | 
						||
		}
 | 
						||
		else
 | 
						||
		{
 | 
						||
			//文件开头
 | 
						||
			if (SEEK_SET==whence)
 | 
						||
			{
 | 
						||
        if(offset>=0&&offset<=file->flash.size)
 | 
						||
        {
 | 
						||
          file->flash.ptr=offset;
 | 
						||
          return 0;
 | 
						||
        }
 | 
						||
			}
 | 
						||
			else if (SEEK_END==whence)
 | 
						||
			{
 | 
						||
        offset=file->flash.size+offset;
 | 
						||
        if(offset>=0&&offset<=file->flash.size)
 | 
						||
        {
 | 
						||
          file->flash.ptr=offset;
 | 
						||
          return 0;
 | 
						||
        }
 | 
						||
			}
 | 
						||
			else if (SEEK_CUR==whence)
 | 
						||
			{
 | 
						||
				//这时offset可正可负
 | 
						||
        long int pos=file->flash.ptr;
 | 
						||
				offset=pos+offset;
 | 
						||
        if(offset>=0&&offset<=file->flash.size)
 | 
						||
        {
 | 
						||
          file->flash.ptr=offset;
 | 
						||
          return 0;
 | 
						||
        }
 | 
						||
			}
 | 
						||
		}
 | 
						||
	}
 | 
						||
	return -1;
 | 
						||
}
 | 
						||
 | 
						||
// 设备文件设置文件偏移,成功返回0
 | 
						||
static int fseek_dev(FILE * stream, long int offset, int whence)
 | 
						||
{
 | 
						||
  const libc_device_file *dev=stream->dev;
 | 
						||
  
 | 
						||
  if(dev)
 | 
						||
  {
 | 
						||
  }
 | 
						||
  
 | 
						||
  return -1;
 | 
						||
}
 | 
						||
 | 
						||
// 内存文件设置文件偏移,成功返回0
 | 
						||
static int fseek_mem(FILE * stream, long int offset, int whence)
 | 
						||
{
 | 
						||
  libc_mem_file *mem=stream->mem;
 | 
						||
  
 | 
						||
  if(mem)
 | 
						||
  {
 | 
						||
    //文件开头
 | 
						||
    if (SEEK_SET==whence)
 | 
						||
    {
 | 
						||
      if(offset>=0&&offset<=mem->size)
 | 
						||
      {
 | 
						||
        mem->ptr=offset;
 | 
						||
        return 0;
 | 
						||
      }
 | 
						||
    }
 | 
						||
    else if (SEEK_END==whence)
 | 
						||
    {
 | 
						||
      offset=mem->size+offset;
 | 
						||
      if(offset>=0&&offset<=mem->size)
 | 
						||
      {
 | 
						||
        mem->ptr=offset;
 | 
						||
        return 0;
 | 
						||
      }
 | 
						||
    }
 | 
						||
    else if (SEEK_CUR==whence)
 | 
						||
    {
 | 
						||
      //这时offset可正可负
 | 
						||
      long int pos=mem->ptr;
 | 
						||
      offset=pos+offset;
 | 
						||
      if(offset>=0&&offset<=mem->size)
 | 
						||
      {
 | 
						||
        mem->ptr=offset;
 | 
						||
        return 0;
 | 
						||
      }
 | 
						||
    }
 | 
						||
  }
 | 
						||
  
 | 
						||
  return -1;
 | 
						||
}
 | 
						||
 | 
						||
static int (*const g_seek_funs[3])(FILE *,long int,int)={
 | 
						||
  fseek_fil,
 | 
						||
  fseek_dev,
 | 
						||
  fseek_mem,
 | 
						||
};
 | 
						||
 | 
						||
// 设置文件偏移,成功返回0
 | 
						||
int fseek(FILE * stream, long int offset, int whence)
 | 
						||
{
 | 
						||
  if(stream)
 | 
						||
  {
 | 
						||
    return g_seek_funs[stream->type](stream,offset,whence);
 | 
						||
  }
 | 
						||
  return -1;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// 返回文件指针偏移
 | 
						||
static long int ftell_fil(FILE * stream)
 | 
						||
{
 | 
						||
  file_struct_private * file=stream->ptr;
 | 
						||
	if (file)
 | 
						||
	{
 | 
						||
		if (file->flash.size==0)
 | 
						||
		{
 | 
						||
			return f_tell(&file->file);
 | 
						||
		}
 | 
						||
		else
 | 
						||
		{
 | 
						||
			return file->flash.ptr;
 | 
						||
		}
 | 
						||
	}
 | 
						||
	return -1;
 | 
						||
}
 | 
						||
 | 
						||
// 返回文件指针偏移
 | 
						||
static long int ftell_dev(FILE * stream)
 | 
						||
{
 | 
						||
  const libc_device_file *dev=stream->dev;
 | 
						||
  
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 | 
						||
// 返回文件指针偏移
 | 
						||
static long int ftell_mem(FILE * stream)
 | 
						||
{
 | 
						||
  libc_mem_file *mem=stream->mem;
 | 
						||
  if(mem)
 | 
						||
    return mem->ptr;
 | 
						||
  else
 | 
						||
    return 0;
 | 
						||
}
 | 
						||
 | 
						||
static long int (*const g_tell_funs[3])(FILE *)={
 | 
						||
  ftell_fil,
 | 
						||
  ftell_dev,
 | 
						||
  ftell_mem,
 | 
						||
};
 | 
						||
 | 
						||
 | 
						||
// 返回文件指针偏移
 | 
						||
long int ftell(FILE * stream)
 | 
						||
{
 | 
						||
  if(stream)
 | 
						||
  {
 | 
						||
    return g_tell_funs[stream->type](stream);
 | 
						||
  }
 | 
						||
  return 0;
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// 把文件指针设置为文件开头
 | 
						||
void rewind(FILE * stream)
 | 
						||
{
 | 
						||
  fseek(stream, 0L, SEEK_SET);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
// 测试文件结束,未结束返回0,已结束返回1
 | 
						||
static int feof_fil(FILE * stream)
 | 
						||
{
 | 
						||
  file_struct_private * file=stream->ptr;
 | 
						||
  if(file)
 | 
						||
  {
 | 
						||
		if (file->flash.size==0)
 | 
						||
    {
 | 
						||
      FIL *fp=&file->file;
 | 
						||
      return f_eof(fp);
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
      return (int)(file->flash.ptr==file->flash.size);
 | 
						||
    }
 | 
						||
  }
 | 
						||
  return 1;
 | 
						||
}
 | 
						||
// 测试文件结束,未结束返回0,已结束返回1
 | 
						||
static int feof_dev(FILE * stream)
 | 
						||
{
 | 
						||
  const libc_device_file *dev=stream->dev;
 | 
						||
  
 | 
						||
  if(dev)
 | 
						||
    return 0;
 | 
						||
  else
 | 
						||
    return 1;
 | 
						||
}
 | 
						||
 | 
						||
static int feof_mem(FILE * stream)
 | 
						||
{
 | 
						||
  libc_mem_file *mem=stream->mem;
 | 
						||
  
 | 
						||
  if(mem)
 | 
						||
    return (int)(mem->ptr==mem->size);
 | 
						||
  else
 | 
						||
    return 1;
 | 
						||
}
 | 
						||
 | 
						||
static int (*const g_eof_funs[3])(FILE *)={
 | 
						||
  feof_fil,
 | 
						||
  feof_dev,
 | 
						||
  feof_mem,
 | 
						||
};
 | 
						||
 | 
						||
 | 
						||
// 测试文件结束,未结束返回0,已结束返回1
 | 
						||
int feof(FILE * stream)
 | 
						||
{
 | 
						||
  if(stream)
 | 
						||
  {
 | 
						||
    return g_eof_funs[stream->type](stream);
 | 
						||
  }
 | 
						||
  return 1;
 | 
						||
}
 | 
						||
 | 
						||
// 断言,c语言标准库使用这个函数
 | 
						||
void __aeabi_assert(const char * e, const char *_file_, int _line_)
 | 
						||
{
 | 
						||
  printf("%s:%s,at %d\r\n",e,_file_,_line_);
 | 
						||
  while(1);
 | 
						||
}
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 | 
						||
 |