Files
player/Project/Src/lib/libc.c

912 lines
15 KiB
C
Raw Normal View History

2025-06-27 00:32:57 +08:00
/*
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);
}