CH582 對(duì)Flash寫入數(shù)據(jù)錯(cuò)誤
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);?//?驗(yàn)證FlashROM數(shù)據(jù)塊,最小塊為dword
if?(err)
{
????FLASH_ROM_READ(current_location_addr,?buff,?8);
????PRINT_HEX("寫入數(shù)據(jù)",?(uint8_t?*)bat_history,?8);
????PRINT_HEX("讀到的數(shù)據(jù)",?(uint8_t?*)buff,?8);
}

上面是我的示例代碼,

我寫入的數(shù)據(jù)是{F1 08 10 00 00 02 10 48},通過

FLASH_ROM_VERIFY()

驗(yàn)證失敗

然后把Flash里的數(shù)據(jù)讀取出來,{51 08 10 00 00 02 10 48}

發(fā)現(xiàn)經(jīng)常會(huì)有一個(gè)字節(jié)錯(cuò)誤.

是什么原因造成的?Flash寫入太頻繁(我大概是2分鐘寫入一次,8/12字節(jié))

image.png這是測試日志


你好,從貼出來的程序來看,寫flash之前沒有擦除,寫flash之前是要先擦flash的,寫之前加上擦除看看呢。


設(shè)備上電是有擦除Flash的,
我這是記錄需要的歷史數(shù)據(jù),每記錄一個(gè)點(diǎn)地址都會(huì)往后偏移相應(yīng)的字節(jié),當(dāng)整一頁(4096字節(jié)都寫滿了)才會(huì)擦除


你好,方便的話可以提供一個(gè)簡單的可以復(fù)現(xiàn)的程序,我們這邊幫你查看下。


#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);?//?驗(yàn)證FlashROM數(shù)據(jù)塊,最小塊為dword
????if?(err)
????{
????????PRINT("Flash?寫入失敗?地址[%d]***********************************%d\r\n",?addr,?i);
????????PRINT_HEX("寫入數(shù)據(jù)",?buff,?len);
????????FLASH_ROM_READ(addr,?buff,?len);
????????PRINT_HEX("錯(cuò)誤數(shù)據(jù)",?buff,?len);

????????tmos_memset(buff,?0,?len);
????????FLASH_ROM_WRITE(addr,?buff,?len);?//?需要清除這個(gè)位置的錯(cuò)誤數(shù)據(jù)(寫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("寫入數(shù)據(jù)",?(uint8_t?*)buff,?8);
????for?(uint8_t?i?=?0;?i?<?5;?i++)
????{
????????if?(Flash_Write(address,?buff,?8)?==?0)
????????{
????????????address?+=?8;?//?偏移到下一個(gè)位置
????????????break;
????????}
????????else
????????{
????????????address?+=?8;?//?偏移到下一個(gè)位置
????????}
????}
}

在一個(gè)循環(huán)事件間隔5s執(zhí)行一次 flash_test()

在main函數(shù)中擦除Flash

FLASH_ROM_ERASE(address,4096);//擦除


image.png


你好,從你的程序來看,如果寫成功就還在對(duì)這個(gè)相同的地址寫,這樣是不對(duì)的,另外注意下寫時(shí)傳入的buff,需要4字節(jié)對(duì)齊。


#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); // 驗(yàn)證FlashROM數(shù)據(jù)塊,最小塊為dword

? ? if (err)

? ? {

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

? ? ? ? PRINT_HEX("寫入數(shù)據(jù)", buff, len);

? ? ? ? FLASH_ROM_READ(addr, buff, len);

? ? ? ? PRINT_HEX("錯(cuò)誤數(shù)據(jù)", buff, len);


? ? ? ? tmos_memset(buff, 0, len);

? ? ? ? FLASH_ROM_WRITE(addr, buff, len); // 需要清除這個(gè)位置的錯(cuò)誤數(shù)據(jù)(寫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("寫入數(shù)據(jù)", (uint8_t *)buff, 8);

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

? ? {

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

? ? ? ? {

? ? ? ? ? ? address += 8; // 偏移到下一個(gè)位置

? ? ? ? ? ? break;

? ? ? ? }

? ? ? ? else

? ? ? ? {

? ? ? ? ? ? address += 8; // 偏移到下一個(gè)位置

? ? ? ? }

? ? }

}

image.png


1.如果寫成功就還在對(duì)這個(gè)相同的地址寫,這樣是不對(duì)的
-------這個(gè)問題已處理,寫成功之后,對(duì)地址進(jìn)行偏移

2.傳入的buff,需要4字節(jié)對(duì)齊
-------這個(gè)需要怎么處理?如何強(qiáng)制buff為4字節(jié)對(duì)齊?


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


這樣子?


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


請(qǐng)問按照上面的代碼有復(fù)現(xiàn)出來我這個(gè)情況嗎?

我修改了Flash_Write() 函數(shù)

addr地址上寫入數(shù)據(jù)(傳來的len是4的整數(shù)倍),如果不正確在相同的地址上,通過for多寫幾次,經(jīng)過我的測試,第一次出現(xiàn)錯(cuò)誤,重復(fù)寫第2次就正確了

這個(gè)方法可以解決我的問題,但是總感覺治標(biāo)不治本,出現(xiàn)這個(gè)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); // 驗(yàn)證FlashROM數(shù)據(jù)塊,最小塊為dword

? ? ? ? PRINT_HEX("Flash 寫入數(shù)據(jù)", buff, len);

? ? ? ? if (err)

? ? ? ? {

? ? ? ? ? ? PRINT("Flash 寫入失敗 地址[%d]***********************************重復(fù)寫入:%d\r\n", addr, i);

? ? ? ? ? ? FLASH_ROM_READ(addr, buff, len);

? ? ? ? ? ? PRINT_HEX("錯(cuò)誤數(shù)據(jù)", buff, len);

? ? ? ? }

? ? ? ? else

? ? ? ? {

? ? ? ? ? ? return 0;

? ? ? ? }

? ? }

? ? tmos_memset(buff, 0, len);

? ? FLASH_ROM_WRITE(addr, buff, len); // 這個(gè)位置已經(jīng)無法寫入數(shù)據(jù),置0

? ? return err;

}



寫之前可以先讀一下接下來寫的區(qū)域,看看是否被擦除過,如果是被擦除過的,你應(yīng)該不會(huì)寫失敗的。


寫之前可以先讀一下接下來寫的區(qū)域,看看是否被擦除過,如果是被擦除過的,你應(yīng)該不會(huì)寫失敗的。


是已經(jīng)擦除過,

擦除后讀取到的結(jié)果是a9 bd f9 f3?(硬件層的FF FF FF FF加密讀取的結(jié)果)


只有登錄才能回復(fù),可以選擇微信賬號(hào)登錄

国产91精品新入口,国产成人综合网在线播放,九热这里只有精品,本道在线观看,美女视频a美女视频,韩国美女激情视频,日本美女pvp视频