You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

394 lines
9.2 KiB

/******************************************************************************
版权所有 (C), 2018-2099, Radkil
******************************************************************************
文 件 名 : rd_stdio.c
版 本 号 : 初稿
作 者 : Radkil
生成日期 : 2026年3月11日星期三
最近修改 :
功能描述 : 标准IO的实现
修改历史 :
1.日 期 : 2026年3月11日星期三
作 者 : Radkil
修改内容 : 创建文件
******************************************************************************/
#include "rd_stdio.h"
#if LV_USE_FS_LITTLEFS
#include "../../lvgl/lvgl.h"
#endif
/*----------------------------------------------*
* 外部变量说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 外部函数原型说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 内部函数原型说明 *
*----------------------------------------------*/
/*----------------------------------------------*
* 全局变量 *
*----------------------------------------------*/
/*----------------------------------------------*
* 模块级变量 *
*----------------------------------------------*/
/*----------------------------------------------*
* 常量定义 *
*----------------------------------------------*/
/*----------------------------------------------*
* 宏定义 *
*----------------------------------------------*/
#ifdef USE_W25QXX
#include "../littlefs/include/lfs.h"
#include "../littlefs/include/lfs_flashbd.h"
lfs_t g_lfs;
lfs_flashbd_t g_bd;
struct lfs_flashbd_config g_bd_cfg;
struct lfs_config g_cfg;
#endif
#ifndef WIN32
WEAK void *Rd_Fopen(const char *path, const char *mode)
{
#ifdef USE_W25QXX
#if LV_USE_FS_LITTLEFS
lv_fs_mode_t lv_mode;
if (strchr(mode, 'r') != NULL) lv_mode = LV_FS_MODE_RD;
else lv_mode = LV_FS_MODE_WR;
lv_fs_file_t *file = RD_MALLOC(sizeof(lv_fs_file_t));
if (NULL == file) return NULL;
lv_fs_res_t res = lv_fs_open(file, path, lv_mode);
if (LV_FS_RES_OK == res)
{
return (void *)file;
}
else
{
printf("%s[%d]fs errno is %d\n", __FILE__, __LINE__, res);
return NULL;
}
#else
const char *p = path;
lfs_file_t *file = RD_MALLOC(sizeof(lfs_file_t));
int flags = 0;
if (strlen(path) >= 2 && path[1] == ':') p = path + 2;
/* 按 mode 首字符解析:r 只读 / w 写并截断 / a 追加;
带 '+' 则为读写。避免 "a+" 被误判为 TRUNC 清空文件 */
if (mode[0] == 'r') {
flags = LFS_O_RDONLY;
if (strchr(mode, '+')) flags = LFS_O_RDWR;
} else if (mode[0] == 'w') {
flags = LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC;
if (strchr(mode, '+')) flags = LFS_O_RDWR | LFS_O_CREAT | LFS_O_TRUNC;
} else if (mode[0] == 'a') {
flags = LFS_O_WRONLY | LFS_O_CREAT | LFS_O_APPEND;
if (strchr(mode, '+')) flags = LFS_O_RDWR | LFS_O_CREAT | LFS_O_APPEND;
} else {
flags = LFS_O_RDONLY; /* 未知 mode 默认只读 */
}
int err = lfs_file_open(&g_lfs, file, p, flags);
if(err) return NULL;
else return (void *)file;
#endif
#endif
return NULL;
}
WEAK void *Rd_Open(const char *path, int flags, mode_t mode)
{
return NULL;
}
WEAK ssize_t Rd_Mread(void *buf, size_t count, void *file)
{
#ifdef USE_W25QXX
#if LV_USE_FS_LITTLEFS
uint32_t size = 0;
lv_fs_file_t *fp = (lv_fs_file_t *)file;
lv_fs_res_t res = lv_fs_read(fp, buf, count, &size);
if (LV_FS_RES_OK == res)
{
return (ssize_t)size;
}
else
{
printf("%s[%d]fs errno is %d\n", __FILE__, __LINE__, res);
return RD_FAILURE;
}
#else
lfs_ssize_t size = 0;
lfs_file_t *fp = (lfs_file_t *)file;
size = lfs_file_read(&g_lfs, fp, buf, count);
if (size >= 0)
{
return (ssize_t)size;
}
else
{
printf("%s[%d]fs errno is %ld\n", __FILE__, __LINE__, size);
return RD_FAILURE;
}
#endif
#endif
return RD_FAILURE;
}
WEAK ssize_t Rd_Mwrite(const void *buf, size_t count, void *file)
{
#ifdef USE_W25QXX
#if LV_USE_FS_LITTLEFS
uint32_t size = 0;
lv_fs_file_t *fp = (lv_fs_file_t *)file;
lv_fs_res_t res = lv_fs_write(fp, buf, count, &size);
if (LV_FS_RES_OK == res)
{
return (ssize_t)size;
}
else
{
printf("%s[%d]fs errno is %d\n", __FILE__, __LINE__, res);
return RD_FAILURE;
}
#else
uint32_t size = 0;
lfs_file_t *fp = (lfs_file_t *)file;
size = lfs_file_write(&g_lfs, fp, buf, count);
if (size >= 0)
{
return (ssize_t)size;
}
else
{
printf("%s[%d]fs errno is %ld\n", __FILE__, __LINE__, size);
return RD_FAILURE;
}
#endif
#endif
return RD_FAILURE;
}
WEAK int Rd_Mclose(void *file)
{
#ifdef USE_W25QXX
#if LV_USE_FS_LITTLEFS
lv_fs_file_t *fp = (lv_fs_file_t *)file;
lv_fs_close(fp);
RD_FREE(file);
return 0;
#else
lfs_file_t *fp = (lfs_file_t *)file;
lfs_file_close(&g_lfs, fp);
RD_FREE(file);
return 0;
#endif
#endif
return RD_FAILURE;
}
WEAK int Rd_Mseek(void *file, long offset, int whence)
{
#ifdef USE_W25QXX
#if LV_USE_FS_LITTLEFS
lv_fs_file_t *fp = (lv_fs_file_t *)file;
lv_fs_whence_t lv_whence;
if (SEEK_END == whence) lv_whence = LV_FS_SEEK_END;
else if (SEEK_CUR == whence) lv_whence = LV_FS_SEEK_CUR;
else lv_whence = LV_FS_SEEK_SET;
lv_fs_res_t res = lv_fs_seek(fp, offset, lv_whence);
if (LV_FS_RES_OK == res)
{
return offset;
}
else
{
printf("%s[%d]fs errno is %d\n", __FILE__, __LINE__, res);
return RD_FAILURE;
}
#else
lfs_file_t *fp = (lfs_file_t *)file;
int flags;
if (SEEK_END == whence) flags = LFS_SEEK_END;
else if (SEEK_CUR == whence) flags = LFS_SEEK_CUR;
else flags = LFS_SEEK_SET;
int res = lfs_file_seek(&g_lfs, fp, offset, flags);
if (res >= 0)
{
return offset;
}
else
{
printf("%s[%d]fs errno is %d\n", __FILE__, __LINE__, res);
return RD_FAILURE;
}
#endif
#endif
return RD_FAILURE;
}
WEAK char *Rd_Mgets(char *buf, int size, void *file)
{
if (!file || !buf || size <= 0) return NULL;
int i = 0;
char c;
while (i < size - 1)
{
ssize_t n = Rd_Mread(&c, 1, file);
if (n != 0)
{
// 读到 EOF 或 错误(Rd_Mread 返回 0 表示读满请求的字节数)
if (i == 0) return NULL; // 什么都没读到
break; // 读到了部分数据,也返回
}
buf[i++] = c;
if (c == '\n') break; // 遇到换行符停止
}
buf[i] = '\0'; // 添加字符串结束符
return buf;
}
WEAK int Rd_Mputs(const char *str, void *file)
{
if (!file || !str) return RD_FAILURE;
size_t len = RD_STRLEN(str);
ssize_t written = Rd_Mwrite(str, len, file);
return (written == (ssize_t)len) ? RD_SUCCESS : RD_FAILURE;
}
WEAK long Rd_Mtell(void *file)
{
#ifdef USE_W25QXX
#if LV_USE_FS_LITTLEFS
uint32_t pos = 0;
lv_fs_file_t *fp = (lv_fs_file_t *)file;
lv_fs_res_t res = lv_fs_tell(fp, &pos);
if (LV_FS_RES_OK == res)
{
return pos;
}
else
{
printf("%s[%d]fs errno is %d\n", __FILE__, __LINE__, res);
return RD_FAILURE;
}
#else
lfs_file_t *fp = (lfs_file_t *)file;
long pos = lfs_file_tell(&g_lfs, fp);
if (pos >= 0)
{
return pos;
}
else
{
printf("%s[%d]fs errno is %ld\n", __FILE__, __LINE__, pos);
return RD_FAILURE;
}
#endif
#endif
return RD_FAILURE;
}
WEAK int Rd_fflush(void *file)
{
return RD_SUCCESS;
}
WEAK int Rd_remove(const char *filename)
{
#ifdef USE_W25QXX
const char *p = filename;
if (strlen(filename) >= 2 && filename[1] == ':') p = filename + 2;
int err = lfs_remove(&g_lfs, p);
if (err) { printf("lfs_remove(%s) failed: %d\n", p, err); return RD_FAILURE; }
return RD_SUCCESS;
#else
return RD_FAILURE;
#endif
}
WEAK int Rd_rename(const char *oldpath, const char *newpath)
{
#ifdef USE_W25QXX
const char *o = oldpath, *n = newpath;
if (strlen(oldpath) >= 2 && oldpath[1] == ':') o = oldpath + 2;
if (strlen(newpath) >= 2 && newpath[1] == ':') n = newpath + 2;
int err = lfs_rename(&g_lfs, o, n);
if (err) { printf("lfs_rename(%s,%s) failed: %d\n", o, n, err); return RD_FAILURE; }
return RD_SUCCESS;
#else
return RD_FAILURE;
#endif
}
WEAK void Rd_LittleFSInit(void)
{
#ifdef USE_W25QXX
// 1MB = 256 个扇区,从地址 1M 开始全部使用,即前边空出1M留做他用(1*1024*1024表示空出1M,12*256表示使用12M空间)
lfs_flashbd_default_config(&g_cfg, &g_bd, &g_bd_cfg, 1 * 1024 * 1024, 12 * 256, NULL, NULL, NULL);
int err = lfs_mount(&g_lfs, &g_cfg);
if (err)
{
printf("mount error format...\n");
lfs_format(&g_lfs, &g_cfg);
lfs_mount(&g_lfs, &g_cfg);
}
return;
#else
return;
#endif
}
WEAK void Rd_FatFSInit(void)
{
return;
}
WEAK int Rd_ListDir(const char *path, Rd_DirEntryCb callback, void *arg)
{
#ifdef USE_W25QXX
const char *p = path;
if (strlen(path) >= 2 && path[1] == ':') p = path + 2;
if (*p == '\0') p = "/";
lfs_dir_t dir;
int err = lfs_dir_open(&g_lfs, &dir, p);
if (err) return RD_FAILURE;
struct lfs_info info;
while (lfs_dir_read(&g_lfs, &dir, &info) > 0)
{
if (strcmp(info.name, ".") == 0 || strcmp(info.name, "..") == 0)
continue;
int is_dir = (info.type == LFS_TYPE_DIR) ? 1 : 0;
if (callback(info.name, is_dir, info.size, arg) != 0)
break;
}
lfs_dir_close(&g_lfs, &dir);
return RD_SUCCESS;
#else
(void)path;
(void)callback;
(void)arg;
return RD_FAILURE;
#endif
}
#endif