/* 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;ptrname,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->ptrsize) { 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->ptrsize) { 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); }