簡體   English   中英

stm32L476 - 擦除閃存

[英]stm32L476 - erasing flash

L4 系列使用頁(或存儲體,如果您進行完全擦除)擦除閃存。 但是在執行頁面擦除后我在寫入時遇到了一些問題,我不知道為什么。

只是為了概述目標,我存儲了從 0x08080000(第 256 頁)開始的 6 個值,然后我存儲了從 0x08080800(第 257 頁)到 0x08085800(第 267 頁)的更多值

我使用一個函數來擦除/寫入第 256 頁的值:

void write_bias_flash(int16_t biases[]) {
    uint16_t *flash_biases = (uint16_t*) (ADDR_FLASH_PAGE_256);
    static FLASH_EraseInitTypeDef EraseInitStruct;
    Address = ADDR_FLASH_PAGE_256;

    /* Fill EraseInit structure*/
    EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.Page = 0;
    EraseInitStruct.Banks = FLASH_BANK_2;
    EraseInitStruct.NbPages = 1;

    HAL_FLASH_Unlock();
    if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
        serprintf("Error erasing biases at address: 0x%x", Address);
    }
    for (int8_t bias = 0; bias < 6; bias++) {
         if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,
                Address + bias * sizeof(uint64_t), (uint64_t) biases[bias])
                != HAL_OK)
            serprintf("Error writing biases to flash.");
     }
    HAL_FLASH_Lock();
    serprintf("Biases stored in flash.");
}

這項工作很棒。 沒有問題。

我有兩個函數用於擦除/寫入從 0x08080800 開始的數據(第 257 頁):

void Erase_TM_Flash() {
    uint8_t *flash = (uint8_t*) (FLASH_USER_START_ADDR);
    uint8_t *b = (uint16_t*) (ADDR_FLASH_PAGE_256);
    static FLASH_EraseInitTypeDef EraseInitStruct;
    Address = FLASH_USER_START_ADDR;

    /* Fill EraseInit structure*/
    EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.Page = 1;
    EraseInitStruct.NbPages = 255;
    EraseInitStruct.Banks = FLASH_BANK_2;

    HAL_FLASH_Unlock();
    if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
        serprintf("Error erasing biases at address: 0x%x", Address);
    }

    HAL_FLASH_Lock();

    for (uint16_t i = 0; i< (FLASH_ROW_SIZE * sizeof(uint64_t))*255; i++)
    {
        if ((uint16_t) *(flash+i) != 255) {
            serprintf("0x%x is not erased (%i)", flash+i, (uint16_t) *(flash+i));
        }

    }

}
void Save_to_Flash(uint32_t *data) {

    uint32_t src_addr = (uint32_t) data;
    Erase_TM_Flash();
    serprintf("Saving to flash...");
    HAL_StatusTypeDef HAL_STATUS;

    HAL_FLASH_Unlock();
    Address = FLASH_USER_START_ADDR;
    while (Address < (FLASH_USER_END_ADDR - (FLASH_ROW_SIZE * sizeof(uint64_t)))) {
        HAL_STATUS = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FAST, Address, (uint64_t) src_addr);
        if (HAL_STATUS == HAL_OK) {
          Address = Addres+ (FLASH_ROW_SIZE * sizeof(uint64_t));
            src_addr = src_addr + (FLASH_ROW_SIZE * sizeof(uint64_t));
            } else {
                serprintf("Error writing flash at address 0x%x. (%i)", Address, HAL_STATUS);
                Address = Address + (FLASH_ROW_SIZE * sizeof(uint64_t));
                src_addr = src_addr + (FLASH_ROW_SIZE * sizeof(uint64_t));
            }
    }
    HAL_FLASH_Lock();
    serprintf("Done");
    }

擦除工作正常。 我驗證調試器中的值(以及檢查未擦除頁面的代碼)。 但是當保存發生時:

Error writing flash at address 0x8080800. (1)
Error writing flash at address 0x8080900. (1)
Error writing flash at address 0x8080a00. (1)
Error writing flash at address 0x8080b00. (1)

依此類推,直到所有剩余頁面。

但是,如果我擦除整個閃存:

void Erase_Flash() {
    serprintf("Erasing flash...");
    HAL_FLASH_Unlock();
    /* Clear OPTVERR bit set on virgin samples */
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);

    /* Fill EraseInit structure*/
    EraseInitStruct.TypeErase = FLASH_TYPEERASE_MASSERASE;
    EraseInitStruct.Banks = FLASH_BANK_2;

    if (HAL_FLASHEx_Erase(&EraseInitStruct, &PAGEError) != HAL_OK) {
        serprintf("Error erasing flash.");
    }
    HAL_FLASH_Lock();
    serprintf("Done.");
}

然后寫作就像一個魅力。 HAL_STATUS = 1,根據我發現的代碼是 HAL_ERROR = 0x01U,這並不完全有用。

我不確定有什么區別,但我希望另一組對我的擦除的關注可能會揭示這個問題。

謝謝!

此問題似乎與閃存快速編程有關,並非在所有 STM32 型號上都可用。

根據參考手冊 (RM0351) ,在使用快速編程之前必須批量擦除閃存。 否則會發生編程序列錯誤FLASH_SR寄存器中的PGSERR位將被設置。 請參閱快速編程/編程錯誤部分中的3.3.7 閃存主存儲器編程序列3.7.5位 7 PGSERR下的閃存狀態寄存器 (FLASH_SR)

RM0351 修訂版 9,3.3.7 閃存主存儲器編程序列,第 106 頁:

Fast programming
(...)
1. Perform a mass erase of the bank to program. If not, PGSERR is set.
2. (...)

RM0351 修訂版 9,3.3.7 閃存主存儲器編程序列,第 107 頁:

Programming errors
(...)
PGSERR: Programming Sequence Error
PGSERR is set if one of the following conditions occurs:
– (...)
– In the fast programming sequence: the Mass erase is not performed before setting 
  FSTPG bit.
– (...)

因此,觀察到的行為符合預期。 - 因此,您可以替換Erase_TM_Flash()函數並使用Erase_Flash()首先批量擦除整個閃存庫。 或者,完全避免使用閃存快速編程並使用FLASH_Program_DoubleWord()FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, ...)代替。

相關源文件: stm32l4xx_hal_flash.hstm32l4xx_hal_flash.c

相關文章: STM32——寫和讀flash

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM