CH582 对Flash写入数据错误
uint8_t buff[8] = {0};
uint8_t bat_history[8] = {0xF1, 0x08, 0x10, 0x00, 0x00, 0x02, 0x10, 0x48};
FLASH_ROM_WRITE(current_location_addr, (uint8_t *)bat_history, 8); // 写入到Flash
err = FLASH_ROM_VERIFY(current_location_addr, (uint8_t *)bat_history, 8); // 验证FlashROM数据块,最小块为dword
if (err)
{
    FLASH_ROM_READ(current_location_addr, buff, 8);
    PRINT_HEX("写入数据", (uint8_t *)bat_history, 8);
    PRINT_HEX("读到的数据", (uint8_t *)buff, 8);
}

上面是我的示例代码,

我写入的数据是{F1 08 10 00 00 02 10 48},通过

FLASH_ROM_VERIFY()

验证失败

然后把Flash里的数据读取出来,{51 08 10 00 00 02 10 48}

发现经常会有一个字节错误.

是什么原因造成的?Flash写入太频繁(我大概是2分钟写入一次,8/12字节)

image.png这是测试日志


你好,从贴出来的程序来看,写flash之前没有擦除,写flash之前是要先擦flash的,写之前加上擦除看看呢。


设备上电是有擦除Flash的,
我这是记录需要的历史数据,每记录一个点地址都会往后偏移相应的字节,当整一页(4096字节都写满了)才会擦除


你好,方便的话可以提供一个简单的可以复现的程序,我们这边帮你查看下。


#define?PRINT_HEX(str,?p,?len)?????????????\
????do?????????????????????????????????????\
????{??????????????????????????????????????\
????????PRINT("\r\n%s[%d]????",?str,?len);?????\
????????for?(uint16_t?i?=?0;?i?<?len;?i++)?\
????????{??????????????????????????????????\
????????????PRINT("%02X?",?*(p?+?i));??????\
????????}??????????????????????????????????\
????????PRINT("\r\n");?????????????????\
???????????????????????????????????????????\
????}?while?(0)

#define?PRINT_HEX_2(p,?len)?????????????\
????do?????????????????????????????????????\
????{??????????????????????????????????\
????????for?(uint16_t?i?=?0;?i?<?len;?i++)?\
????????{??????????????????????????????????\
????????????PRINT("0x%02X,?",?*(p?+?i));??????\
????????}??????????????????????????????????\
????????PRINT("\r\n");?????????????????\
???????????????????????????????????????????\
????}?while?(0)

uint8_t?Flash_Write(uint32_t?addr,?uint8_t?*pValue,?uint16_t?len)
{
????static?uint8_t?i?=?1;
????uint8_t?buff[24]?=?{0};
????uint8_t?err?=?0;
????tmos_memcpy(buff,?pValue,?len);
????FLASH_ROM_WRITE(addr,?buff,?len);????????//?写入到Flash
????err?=?FLASH_ROM_VERIFY(addr,?buff,?len);?//?验证FlashROM数据块,最小块为dword
????if?(err)
????{
????????PRINT("Flash?写入失败?地址[%d]***********************************%d\r\n",?addr,?i);
????????PRINT_HEX("写入数据",?buff,?len);
????????FLASH_ROM_READ(addr,?buff,?len);
????????PRINT_HEX("错误数据",?buff,?len);

????????tmos_memset(buff,?0,?len);
????????FLASH_ROM_WRITE(addr,?buff,?len);?//?需要清除这个位置的错误数据(写0)
????????i++;
????}
????else
????{
????????i?=?1;
????}
????return?err;
}

uint32_t?address?=?((4?*?1024?+?216?*?1024));
void?flash_test(void)
{
????static?uint8_t?count?=?0;
????uint8_t?buff[8]?=?{0};
????count++;
????tmos_memset(buff,?count,?8);
????PRINT_HEX("写入数据",?(uint8_t?*)buff,?8);
????for?(uint8_t?i?=?0;?i?<?5;?i++)
????{
????????if?(Flash_Write(address,?buff,?8)?==?0)
????????{
????????????address?+=?8;?//?偏移到下一个位置
????????????break;
????????}
????????else
????????{
????????????address?+=?8;?//?偏移到下一个位置
????????}
????}
}

在一个循环事件间隔5s执行一次 flash_test()

在main函数中擦除Flash

FLASH_ROM_ERASE(address,4096);//擦除


image.png


你好,从你的程序来看,如果写成功就还在对这个相同的地址写,这样是不对的,另外注意下写时传入的buff,需要4字节对齐。


#define PRINT_HEX_2(p, len)             \

    do                                     \

    {                                  \

        for (uint16_t i =0; i < len; i++) \

        {                                  \

            PRINT("0x%02X, ", *(p + i));      \

        }                                  \

        PRINT("\r\n");                 \

                                           \

    } while (0)



uint8_t Flash_Write(uint32_t addr, uint8_t *pValue, uint16_t len)

{

    static uint8_t i = 1;

    uint8_t buff[24] = {0};

    uint8_t err = 0;

    tmos_memcpy(buff, pValue, len);

    FLASH_ROM_WRITE(addr, buff, len);        // 写入到Flash

    err = FLASH_ROM_VERIFY(addr, buff, len); // 验证FlashROM数据块,最小块为dword

    if (err)

    {

        PRINT("Flash 写入失败 地址[%d]***********************************%d\r\n", addr, i);

        PRINT_HEX("写入数据", buff, len);

        FLASH_ROM_READ(addr, buff, len);

        PRINT_HEX("错误数据", buff, len);


        tmos_memset(buff, 0, len);

        FLASH_ROM_WRITE(addr, buff, len); // 需要清除这个位置的错误数据(写0)

        i++;

    }

    else

    {

        i = 1;

    }

    return err;

}


uint32_t address = ((4 * 1024 + 216 * 1024));

void flash_test(void)

{

    static uint8_t count = 0;

    uint8_t buff[8] = {0};

    count++;

    tmos_memset(buff, count, 8);

    PRINT_HEX("写入数据", (uint8_t *)buff, 8);

    for (uint8_t i = 0; i < 5; i++)

    {

        if (Flash_Write(address, buff, 8) == 0)

        {

            address += 8; // 偏移到下一个位置

            break;

        }

        else

        {

            address += 8; // 偏移到下一个位置

        }

    }

}

image.png


1.如果写成功就还在对这个相同的地址写,这样是不对的
-------这个问题已处理,写成功之后,对地址进行偏移

2.传入的buff,需要4字节对齐
-------这个需要怎么处理?如何强制buff为4字节对齐?


uint8_t buff[24] __attribute__((aligned(4))) = {0};


这样子?


可以参考下例程中的写法,__attribute__((aligned(4))) uint32_t MEM_BUF[BLE_MEMHEAP_SIZE/4];


请问按照上面的代码有复现出来我这个情况吗?

我修改了Flash_Write() 函数

addr地址上写入数据(传来的len是4的整数倍),如果不正确在相同的地址上,通过for多写几次,经过我的测试,第一次出现错误,重复写第2次就正确了

这个方法可以解决我的问题,但是总感觉治标不治本,出现这个bug的根因没有找到


uint8_t Flash_Write(uint32_t addr, uint8_t *pValue, uint16_t len)

{

    uint8_t buff[24] = {0};

    uint8_t err = 0;

    for (uint8_t i = 1; i < 5; i++)

    {

        tmos_memcpy(buff, pValue, len);

        FLASH_ROM_WRITE(addr, buff, len);        // 写入到Flash

        err = FLASH_ROM_VERIFY(addr, buff, len); // 验证FlashROM数据块,最小块为dword

        PRINT_HEX("Flash 写入数据", buff, len);

        if (err)

        {

            PRINT("Flash 写入失败 地址[%d]***********************************重复写入:%d\r\n", addr, i);

            FLASH_ROM_READ(addr, buff, len);

            PRINT_HEX("错误数据", buff, len);

        }

        else

        {

            return 0;

        }

    }

    tmos_memset(buff, 0, len);

    FLASH_ROM_WRITE(addr, buff, len); // 这个位置已经无法写入数据,置0

    return err;

}



写之前可以先读一下接下来写的区域,看看是否被擦除过,如果是被擦除过的,你应该不会写失败的。


写之前可以先读一下接下来写的区域,看看是否被擦除过,如果是被擦除过的,你应该不会写失败的。


是已经擦除过,

擦除后读取到的结果是a9 bd f9 f3 (硬件层的FF FF FF FF加密读取的结果)


只有登录才能回复,可以选择微信账号登录