欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【项目笔记_rp552d】Partition write error! Flash device(onchip_flash) write error!

程序员文章站 2024-02-23 20:35:58
...

问题描述

在使用 easy_falsh 的是时候出现问题,这个问题是发现在 触发 gc 的时候突然断电就出现了错误,一旦出现这个问题无论怎样都无法恢复,除非重新擦除数据区
【项目笔记_rp552d】Partition write error! Flash device(onchip_flash) write error!
需要擦除才能恢复,这个问题是不可接受的


问题分析

估计是触发在STM32上面触发GC机制的问题在备份在转移数据的时候突然断电会导致状态异常,这个异常的状态是写入在FLASH中的,导致即使上电数据也不能恢复,于是查找数据出错的地方:

int stm32_flash_write(rt_uint32_t addr, const rt_uint8_t *buf, size_t size)
{
    rt_err_t result        = RT_EOK;
    rt_uint32_t end_addr   = addr + size;

    if (addr % 4 != 0)
    {
        LOG_E("write addr must be 4-byte alignment");
        return -RT_EINVAL;
    }

    if ((end_addr) > STM32_FLASH_END_ADDRESS)
    {
        LOG_E("write outrange flash size! addr is (0x%p)", (void *)(addr + size));
        return -RT_EINVAL;
    }

    HAL_FLASH_Unlock();

    while (addr < end_addr)
    {
+       /* 写数据之前会进行错误检查,如果之前操作有错误积累,则之后无法操作成功,需要清除一下 */
+       __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_WRPERR | FLASH_FLAG_PGERR |
+               FLASH_FLAG_BSY | FLASH_FLAG_EOP);
        if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr, *((rt_uint32_t *)buf)) == HAL_OK)
        {
            if (*(rt_uint32_t *)addr != *(rt_uint32_t *)buf)
            {
                result = -RT_ERROR;
                break;
            }
            addr += 4;
            buf  += 4;
        }
        else
        {
            result = -RT_ERROR;
+           LOG_E(" HAL_FLASH_Program 写数据错误");
            break;
        }
    }

    HAL_FLASH_Lock();

    if (result != RT_EOK)
    {
        return result;
    }

    return size;
}

添加错误数据之后发现数据还是无法写入成功,那个此处怀疑需要格式化扇区才能恢复逻辑,于是查找代码,在写数据失败的地方增加恢复 默认状态

// ef_fal_port.c
EfErrCode ef_port_write(uint32_t addr, const uint32_t *buf, size_t size) {
    EfErrCode result = EF_NO_ERR;

    if (fal_partition_write(part, addr, (uint8_t *)buf, size) < 0)
    {
        result = EF_WRITE_ERR;
+       ef_port_env_unlock();
+       ef_env_set_default();
+       rt_thread_mdelay(50);
+       rt_hw_cpu_reset();
    }

    return result;
}

再次上电测试发现

 \ | /
- RT -     Thread Operating System
 / | \     4.0.2 build Nov 11 2020
 2006 - 2019 Copyright by rt-thread team
[1] I/NO_TAG: hw_ver:0, name:si522 find spi bus ok
[154] I/NO_TAG: hw_ver:0, name: si522 init ok
[155] D/main: d_LCD:thread:thd_beep init OK

[D/FAL] (fal_flash_init:63) Flash device |             onchip_flash | addr: 0x08000000 | len: 0x00040000 | blk_size: 0x00000800 |initialized finish.
[I/FAL] ==================== FAL partition table ====================
[I/FAL] | name | flash_dev    |   offset   |    length  |
[I/FAL] -------------------------------------------------------------
[I/FAL] | app  | onchip_flash | 0x00000000 | 0x00032000 |
[I/FAL] | dat  | onchip_flash | 0x00032000 | 0x0000e000 |
[I/FAL] =============================================================
[I/FAL] RT-Thread Flash Abstraction Layer (V0.5.0) initialize success.
[Flash] (../packages/EasyFlash-v4.1.0/src/ef_env.c:1818) ENV start address is 0x00000000, size is 32768 bytes.
[Flash] EasyFlash V4.1.0 is initialize success.
[Flash] You can get the latest version on https://github.com/armink/EasyFlash .
easyflash_init ret:0
===============================================
The system now boot 353 times
boot_delay: 120
uID_id: 3065517179
HEX_id: b6b8147b
===============================================
[222] D/fee: sys_tcb_val.tx_power: 5
[223] D/fee: sys_tcb_val.rf_ch: 96
[224] D/fee: sys_tcb_val.port_max: 120
[227] D/fee: next_pos: 30
D/HEX use_tab: 0000-000F: FF FF FF 7F 00 00 00 00  00 00 00 00 00 00 00 00    ................
[287] D/fee: end check upos:120
[288] I/NO_TAG: hw_ver:0, name: si522 card_pcd_init ok
[289] I/NO_TAG: m_CARD: thread:thd_card init OK
[289] I/esb: hw_ver:0, esb_rx_hw_sem init ret:0
[290] I/esb: hw_ver:0, esb_rx find spi bus ok
[291] D/esb: s_PORT: thread:thd_esb_rx init OK
msh >[304] D/dtq: r_PORT0: v1.x SET_CONFIG ErrCode:0 !
[310] D/dtq: r_PORT0: v1.x SET_CONFIG ErrCode:0 !

此时发现这个问题已经修复,且发现实际上环境变量的数据并未全部丢失(可能某次转移的数据丢失,但是有已经能保证设备正常使用了)


实测数据确实会丢失:(原本数据有120个uID)

msh >wl
uID_000: 1000000000 uID_001: 1000000001 uID_002: 1000000002 
uID_003: 1000000003 uID_004: 1000000004 uID_005: 1000000005 
uID_006: 1000000006 uID_007: 1000000007 uID_008: 1000000008 
uID_009: 1000000009 uID_010: 1000000010 uID_011: 1000000011 
uID_012: 1000000012 uID_013: 1000000013 uID_014: 1000000014 
uID_015: 1000000015 uID_016: 1000000016 uID_017: 1000000017 
uID_018: 1000000018 uID_019: 1000000019 uID_020: 1000000020 
uID_021: 1000000021 uID_022: 1000000022 msh >