diff --git a/bspMCU/include/w25qxx.h b/bspMCU/include/w25qxx.h index f8bb134..c7e3d95 100644 --- a/bspMCU/include/w25qxx.h +++ b/bspMCU/include/w25qxx.h @@ -79,12 +79,12 @@ void W25QXX_4ByteAddr_Enable(void); void W25QXX_Write_SR(uint8_t regno, uint8_t sr); void W25QXX_Write_Enable(void); void W25QXX_Write_Disable(void); -void W25QXX_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite); -void W25QXX_Write_NoCheck(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite); -void W25QXX_Read(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead); +int W25QXX_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite); +int W25QXX_Write_NoCheck(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite); +int W25QXX_Read(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead); void W25QXX_Write(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite); void W25QXX_Erase_Chip(void); -void W25QXX_Erase_Sector(uint32_t Dst_Addr); +int W25QXX_Erase_Sector(uint32_t Dst_Addr); void W25QXX_Wait_Busy(void); void W25QXX_PowerDown(void); void W25QXX_WAKEUP(void); diff --git a/bspMCU/w25qxx.c b/bspMCU/w25qxx.c index ad94fe9..85b7f42 100644 --- a/bspMCU/w25qxx.c +++ b/bspMCU/w25qxx.c @@ -221,14 +221,14 @@ void W25QXX_Write_Disable(void) W25QXX_CommandOnly(W25X_WriteDisable); } -/** 读取指定地址、指定长度的数据(1-Line 标准读 0x03) */ -void W25QXX_Read(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead) +/** 读取指定地址、指定长度的数据(1-Line 标准读 0x03),返回 0 成功 / -1 失败 */ +int W25QXX_Read(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead) { QSPI_CommandTypeDef cmd = {0}; if (NumByteToRead == 0) { - return; + return 0; } W25QXX_Command_Base(&cmd); @@ -241,19 +241,23 @@ void W25QXX_Read(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead) if (HAL_QSPI_Command(&hqspi, &cmd, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { - return; + return -1; + } + if (HAL_QSPI_Receive(&hqspi, pBuffer, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return -1; } - HAL_QSPI_Receive(&hqspi, pBuffer, HAL_QSPI_TIMEOUT_DEFAULT_VALUE); + return 0; } -/** 页编程(≤256 字节,不跨页) */ -void W25QXX_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) +/** 页编程(≤256 字节,不跨页),返回 0 成功 / -1 失败 */ +int W25QXX_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) { QSPI_CommandTypeDef cmd = {0}; if (NumByteToWrite == 0) { - return; + return 0; } W25QXX_Write_Enable(); @@ -268,14 +272,18 @@ void W25QXX_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToW if (HAL_QSPI_Command(&hqspi, &cmd, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { - return; + return -1; + } + if (HAL_QSPI_Transmit(&hqspi, pBuffer, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) + { + return -1; } - HAL_QSPI_Transmit(&hqspi, pBuffer, HAL_QSPI_TIMEOUT_DEFAULT_VALUE); W25QXX_Wait_Busy(); + return 0; } -/** 无校验写入:自动跨页,不检查/不擦除(调用方须保证目标区已擦除) */ -void W25QXX_Write_NoCheck(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) +/** 无校验写入:自动跨页,不检查/不擦除(调用方须保证目标区已擦除),返回 0 成功 / -1 失败 */ +int W25QXX_Write_NoCheck(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) { uint16_t pageremain = W25QXX_PAGE_SIZE - (WriteAddr % W25QXX_PAGE_SIZE); /* 本页剩余 */ @@ -286,7 +294,10 @@ void W25QXX_Write_NoCheck(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByte while (1) { - W25QXX_Write_Page(pBuffer, WriteAddr, pageremain); + if (W25QXX_Write_Page(pBuffer, WriteAddr, pageremain) != 0) + { + return -1; + } if (NumByteToWrite == pageremain) { @@ -308,6 +319,7 @@ void W25QXX_Write_NoCheck(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByte } } } + return 0; } /** 带擦除的写入:自动跨页跨扇区,非 0xFF 区域先擦除再写 */ @@ -387,8 +399,8 @@ void W25QXX_Erase_Chip(void) W25QXX_WaitBusy_Timeout(250000U); } -/** 扇区擦除,入参为扇区号(内部 ×4096 得到字节地址) */ -void W25QXX_Erase_Sector(uint32_t Dst_Addr) +/** 扇区擦除,入参为扇区号(内部 ×4096 得到字节地址),返回 0 成功 / -1 失败 */ +int W25QXX_Erase_Sector(uint32_t Dst_Addr) { uint32_t byte_addr = Dst_Addr * W25QXX_SECTOR_SIZE; QSPI_CommandTypeDef cmd = {0}; @@ -405,9 +417,10 @@ void W25QXX_Erase_Sector(uint32_t Dst_Addr) if (HAL_QSPI_Command(&hqspi, &cmd, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { - return; + return -1; } W25QXX_Wait_Busy(); + return 0; } /** 等待 Flash 空闲:自动轮询状态寄存器 bit0(BUSY) 直至为 0 */ @@ -541,7 +554,7 @@ uint16_t W25QXX_ReadID(void) return Temp; } -void W25QXX_Read(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead) +int W25QXX_Read(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead) { uint16_t i; W25QXX_CS(0); @@ -558,9 +571,10 @@ void W25QXX_Read(uint8_t *pBuffer, uint32_t ReadAddr, uint16_t NumByteToRead) pBuffer[i] = SPI2_ReadWriteByte(0xFF); } W25QXX_CS(1); + return 0; } -void W25QXX_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) +int W25QXX_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) { uint16_t i; W25QXX_Write_Enable(); @@ -579,9 +593,10 @@ void W25QXX_Write_Page(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToW } W25QXX_CS(1); W25QXX_Wait_Busy(); + return 0; } -void W25QXX_Write_NoCheck(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) +int W25QXX_Write_NoCheck(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) { uint16_t pageremain; pageremain = 256 - WriteAddr % 256; @@ -611,6 +626,7 @@ void W25QXX_Write_NoCheck(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByte } } } + return 0; } void W25QXX_Write(uint8_t *pBuffer, uint32_t WriteAddr, uint16_t NumByteToWrite) @@ -686,7 +702,7 @@ void W25QXX_Erase_Chip(void) W25QXX_Wait_Busy(); } -void W25QXX_Erase_Sector(uint32_t Dst_Addr) +int W25QXX_Erase_Sector(uint32_t Dst_Addr) { Dst_Addr *= 4096; W25QXX_Write_Enable(); @@ -702,6 +718,7 @@ void W25QXX_Erase_Sector(uint32_t Dst_Addr) SPI2_ReadWriteByte((uint8_t)Dst_Addr); W25QXX_CS(1); W25QXX_Wait_Busy(); + return 0; } void W25QXX_Wait_Busy(void) diff --git a/library/common/rd_stdio.c b/library/common/rd_stdio.c index 5b2fbd1..dabe014 100644 --- a/library/common/rd_stdio.c +++ b/library/common/rd_stdio.c @@ -81,10 +81,22 @@ WEAK void *Rd_Fopen(const char *path, const char *mode) #else const char *p = path; lfs_file_t *file = RD_MALLOC(sizeof(lfs_file_t)); - int flags; + int flags = 0; if (strlen(path) >= 2 && path[1] == ':') p = path + 2; - if (strchr(mode, 'r') != NULL) flags = LFS_O_RDONLY; - else flags = LFS_O_WRONLY | LFS_O_CREAT | LFS_O_TRUNC; + /* 按 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; diff --git a/library/littlefs/include/lfs.h b/library/littlefs/include/lfs.h index 8fbd5b4..6f1cf3a 100644 --- a/library/littlefs/include/lfs.h +++ b/library/littlefs/include/lfs.h @@ -32,7 +32,7 @@ extern "C" #define LFS_DISK_VERSION_MAJOR (0xffff & (LFS_DISK_VERSION >> 16)) #define LFS_DISK_VERSION_MINOR (0xffff & (LFS_DISK_VERSION >> 0)) - +#define LFS_THREADSAFE /// Definitions /// // Type definitions diff --git a/library/littlefs/lfs_flashbd.c b/library/littlefs/lfs_flashbd.c index 3846727..c781957 100644 --- a/library/littlefs/lfs_flashbd.c +++ b/library/littlefs/lfs_flashbd.c @@ -10,6 +10,9 @@ #include "lfs_flashbd.h" #include "../../bspMCU/include/w25qxx.h" #include +#include "rd_thread.h" + +static rd_mutex_t g_lfs_mutex; int lfs_flashbd_create(const struct lfs_config *cfg, const struct lfs_flashbd_config *bdcfg) { @@ -47,7 +50,10 @@ int lfs_flashbd_read(const struct lfs_config *cfg, lfs_block_t block, + (uint32_t)block * cfg->block_size + (uint32_t)off; - W25QXX_Read((uint8_t *)buffer, addr, (uint16_t)size); + if (W25QXX_Read((uint8_t *)buffer, addr, (uint16_t)size) != 0) + { + return LFS_ERR_IO; + } return LFS_ERR_OK; } @@ -68,7 +74,10 @@ int lfs_flashbd_prog(const struct lfs_config *cfg, lfs_block_t block, * 但该函数只读取 buffer 内容,不会修改,故安全地去除 const。 * littleFS 保证写入前块已擦除,因此无需带擦除的 W25QXX_Write。 */ - W25QXX_Write_NoCheck((uint8_t *)(uintptr_t)buffer, addr, (uint16_t)size); + if (W25QXX_Write_NoCheck((uint8_t *)(uintptr_t)buffer, addr, (uint16_t)size) != 0) + { + return LFS_ERR_IO; + } return LFS_ERR_OK; } @@ -85,7 +94,10 @@ int lfs_flashbd_erase(const struct lfs_config *cfg, lfs_block_t block) { * W25QXX_Erase_Sector 的参数是扇区号(内部会乘以 4096), * 所以传入字节地址除以扇区大小。 */ - W25QXX_Erase_Sector(addr / LFS_FLASHBD_SECTOR_SIZE); + if (W25QXX_Erase_Sector(addr / LFS_FLASHBD_SECTOR_SIZE) != 0) + { + return LFS_ERR_IO; + } return LFS_ERR_OK; } @@ -96,6 +108,20 @@ int lfs_flashbd_sync(const struct lfs_config *cfg) { return LFS_ERR_OK; } +int lfs_flashbd_lock(const struct lfs_config *cfg) +{ + (void)cfg; + Rd_MutexLock(&g_lfs_mutex, __func__, NULL); + return LFS_ERR_OK; +} + +int lfs_flashbd_unlock(const struct lfs_config *cfg) +{ + (void)cfg; + Rd_MutexUnlock(&g_lfs_mutex, __func__, NULL); + return LFS_ERR_OK; +} + void lfs_flashbd_default_config( struct lfs_config *cfg, lfs_flashbd_t *bd, @@ -113,12 +139,16 @@ void lfs_flashbd_default_config( bd->cfg = bdcfg; + (void)Rd_MutexInit(&g_lfs_mutex); + /* 回调函数 */ cfg->context = bd; cfg->read = lfs_flashbd_read; cfg->prog = lfs_flashbd_prog; cfg->erase = lfs_flashbd_erase; cfg->sync = lfs_flashbd_sync; + cfg->lock = lfs_flashbd_lock; + cfg->unlock = lfs_flashbd_unlock; /* 块设备参数 */ cfg->read_size = 256; /* W25QXX 页大小,读取可任意长度 */ diff --git a/library/log/elog_file.c b/library/log/elog_file.c index 076ef40..591ddf5 100644 --- a/library/log/elog_file.c +++ b/library/log/elog_file.c @@ -81,7 +81,8 @@ static bool elog_file_rotate(void) RD_MEMCPY(oldpath, local_cfg.name, base); RD_MEMCPY(newpath, local_cfg.name, base); - fclose(fp); + Rd_Mclose(fp); + fp = NULL; for (n = local_cfg.max_rotate - 1; n >= 0; --n) { RD_SNPRINTF(oldpath + base, SUFFIX_LEN, n ? ".%d" : "", n - 1);