armink / EasyFlash

Lightweight IoT device information storage solution: KV/IAP/LOG. | 轻量级物联网设备信息存储方案:参数存储、在线升级及日志存储 ,全新一代版本请移步至 https://github.com/armink/FlashDB
MIT License
2.01k stars 766 forks source link

日志存储功能最多只能存储一页大小的内容 #46

Closed Bamwell closed 5 years ago

Bamwell commented 5 years ago

经过测试,日志存储功能最多只能存储flash一页大小的内容,超过一页大小就写不进去了。 测试环境: easyflash v4.0.0 mcu stm32f107VC 256K的flash,2K/页 EF_ERASE_MIN_SIZE 2048 EF_WRITE_GRAN 32

找不着原因,烦请指教,谢谢~

armink commented 5 years ago

超过一页之后,会有什么样的提示信息呢

Bamwell commented 5 years ago

没有任何提示呢。 我把下面这个pr合并后,问题得到了解决。

修复Flash操作返回失败,及log_end_add返回块首址造成无法写log。

42 opened 23 days ago by hjgqx996

armink commented 5 years ago

只同步这个 pr 中的 ef_log.c 文件可以吗?

Bamwell commented 5 years ago

若只同步ef_log.c文件,则: 如写入50条日志,读回来可能是47条或46条或其他,不确定。

若只同步ef_port.c文件,则: 经测试log功能正常。存多少条,也读回多少条。

猜测:是不是每一页的开头被初始化写入了一些标志,ef_port_write的时候遇到这些非0xFF的标志造成无法继续写入?

armink commented 5 years ago

我大概知道问题了,主要是 STM32F1 系列已经写入过的位置,不允许再次写入数据,哪怕之前写入的是 0xFF 也不行。

你把 write_sector_status 改为下面的方式试试,port 里的代码还是还原

static EfErrCode write_sector_status(uint32_t addr, SectorStatus status) {
    uint32_t header, header_addr = 0;

    /* calculate the sector header address */
    header_addr = addr / EF_ERASE_MIN_SIZE * EF_ERASE_MIN_SIZE;

    /* calculate the sector staus magic */
    switch (status) {
    case SECTOR_STATUS_EMPUT: {
        header = LOG_SECTOR_MAGIC;
        return ef_port_write(header_addr, &header, sizeof(header));
    }
    case SECTOR_STATUS_USING: {
        header = SECTOR_STATUS_MAGIC_USING;
        return ef_port_write(header_addr + sizeof(header), &header, sizeof(header));
    }
    case SECTOR_STATUS_FULL: {
        header = SECTOR_STATUS_MAGIC_FULL;
        return ef_port_write(header_addr + sizeof(header) * 2, &header, sizeof(header));
    }
    default:
        return EF_WRITE_ERR;
    }
}
Bamwell commented 5 years ago

image image

如你所述修改,经测试,日志写不进去。

redocCheng commented 5 years ago

没有问题啊 测试平台:stm32f103vet6
FLASH大小:256KB snipaste_20190325_162152

redocCheng commented 5 years ago

4.0的ef_log.c好像没有更改,估计你测试3.0最新版本也是一样。

redocCheng commented 5 years ago

@Bamwell 老铁,把你ef_port.c、ef_cfg.h发出来看看晒!

redocCheng commented 5 years ago

我大概知道问题了,主要是 STM32F1 系列已经写入过的位置,不允许再次写入数据,哪怕之前写入的是 0xFF 也不行。

你把 write_sector_status 改为下面的方式试试,port 里的代码还是还原

static EfErrCode write_sector_status(uint32_t addr, SectorStatus status) {
    uint32_t header, header_addr = 0;

    /* calculate the sector header address */
    header_addr = addr / EF_ERASE_MIN_SIZE * EF_ERASE_MIN_SIZE;

    /* calculate the sector staus magic */
    switch (status) {
    case SECTOR_STATUS_EMPUT: {
        header = LOG_SECTOR_MAGIC;
        return ef_port_write(header_addr, &header, sizeof(header));
    }
    case SECTOR_STATUS_USING: {
        header = SECTOR_STATUS_MAGIC_USING;
        return ef_port_write(header_addr + sizeof(header), &header, sizeof(header));
    }
    case SECTOR_STATUS_FULL: {
        header = SECTOR_STATUS_MAGIC_FULL;
        return ef_port_write(header_addr + sizeof(header) * 2, &header, sizeof(header));
    }
    default:
        return EF_WRITE_ERR;
    }
}

写入过0xff是可以再次写的,设计0xFFFFFFFF、0xFEFEFEFE、0xFCFCFCFC肯定考虑过这个问题,测试也通过了。

Bamwell commented 5 years ago

ef_log.txt

.c文件不让传...

Bamwell commented 5 years ago

/*

ifndef EF_CFGH

define EF_CFGH

include

include "flash_map.h"

/ using ENV function, default is NG (Next Generation) mode start from V4.0 /

define EF_USING_ENV

define EF_ENV_AUTO_UPDATE

define EF_ENV_VER_NUM (0 + 0x30)

/ using IAP function / //#define EF_USING_IAP

/ using save log function /

define EF_USING_LOG

/ page size for stm32 flash /

if defined(STM32F10X_LD) || defined(STM32F10X_LD_VL) || defined (STM32F10X_MD) || defined (STM32F10X_MD_VL)

define PAGE_SIZE 1024

else

define PAGE_SIZE 2048

endif

/ the minimum size of flash erasure /

define EF_ERASE_MIN_SIZE PAGE_SIZE / it is one page for STM3210x /

/* the flash write granularity, unit: bit

/

/ backup area start address /

define EF_START_ADDR USER_ADDR_START //(0x08007800+0x31000)

/ ENV area size. It's at least one empty sector for GC. So it's definination must more then or equal 2 flash sector size. /

define ENV_AREA_SIZE (2*EF_ERASE_MIN_SIZE) //USER_ZONE_LEN

/ saved log area size /

define LOG_AREA_SIZE (13*EF_ERASE_MIN_SIZE)

/ print debug information of flash / //#define PRINT_DEBUG

endif / EF_CFGH /

redocCheng commented 5 years ago

@Bamwell 老铁,你的区域大小咋没有乘号,2EF_ERASE_MIN_SIZE是什么意思。

define ENV_AREA_SIZE (2EF_ERASE_MIN_SIZE) //USER_ZONE_LEN

define LOG_AREA_SIZE (13EF_ERASE_MIN_SIZE)

不应该是:

define ENV_AREA_SIZE (2*EF_ERASE_MIN_SIZE) //USER_ZONE_LEN

define LOG_AREA_SIZE (13*EF_ERASE_MIN_SIZE)

么。。。。

armink commented 5 years ago

@redocCheng 这个是 markdown 格式问题,下次贴代码可以试试 ```C 语法包裹一下

#define ENV_AREA_SIZE (2*EF_ERASE_MIN_SIZE) //USER_ZONE_LEN    
#define LOG_AREA_SIZE (13*EF_ERASE_MIN_SIZE)
armink commented 5 years ago

@Bamwell 完善了一下状态写入功能,你试下行不行哈?

ef_log 20190326.txt

Bamwell commented 5 years ago

@redocCheng 不好意思,没有注意markdown 格式。 @armink 经测试,替换ef_log 20190326.txt后,log功能已经正常。 大致是什么原因导致的,有空简单描述一下哈~

armink commented 5 years ago

感觉跟 STM32 的标准库与 HAL 有关系,才触发这个问题。你的 Flash 驱动用的是标准库还是 HAL 库。

Bamwell commented 5 years ago

用的标准库。

image image

armink commented 5 years ago

那跟库还没关系了,我这边用 HAL 测试发现写入 0xFFFF 数据后,再同样地址写入其他数据时,HAL 底层会报错。

给你发的补丁规避了这种情况,不会在相同地址写入不同数据。

Bamwell commented 5 years ago

好的。 多谢热心交流。

armink commented 5 years ago

感谢 @Bamwell @redocCheng @hjgqx996 的反馈与支持,代码已经更新完成: https://github.com/armink/EasyFlash/commit/a6edd12e067975c9cd0dfe48756a88ecd3c11966