Files
player/Project/Src/lib/libc.c
2025-07-05 19:47:28 +08:00

912 lines
15 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
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);
}