cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 Flash Erase Fails: HAL_FLASHEx_Erase() Doesn't Reset Bytes to 0xFF

AChap.1
Associate III

Hello ST Community,

I'm currently facing a challenging issue with my STM32L476RET6 where I'm unable to erase a specific page in the flash memory. Despite the HAL_FLASHEx_Erase() function returning HAL_OK, indicating the erase operation was supposedly successful, the bytes at the specified memory location are not set to 0xFF as expected. I've confirmed this by checking the memory location with STM32CubeProgrammer.

Environment:

MCU: STM32L476RET6

IDE: STM32CubeIDE

OS: Windows 10

 

Here's the function where I'm encountering the issue:

 

HAL_StatusTypeDef set_update_flag(void) {
    // Unlock the Flash to enable the flash control register access
    HAL_StatusTypeDef status = HAL_FLASH_Unlock();
    if (status != HAL_OK) {
        // Unlock failed, handle accordingly
        return status;
    }

    // Define the page and bank for the erase operation
    FLASH_EraseInitTypeDef EraseInitStruct;
    uint32_t PageError = 0;
    EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.Banks = FLASH_BANK_1;
    EraseInitStruct.Page = 255;  // Targeting the last page for the erase operation
    EraseInitStruct.NbPages = 1;

    // Erase the page
    status = HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
    if (status != HAL_OK) {
        // Erase failed, handle accordingly
        HAL_FLASH_Lock();  // Make sure to lock the flash again before returning
        return status;
    }

    // Set the update flag to 1
    status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, UPDATE_FLAG_ADDRESS, 0x0000000100000001);
    if (status != HAL_OK) {
        // Program failed, handle accordingly
        HAL_FLASH_Lock();  // Make sure to lock the flash again before returning
        return status;
    }

    HAL_FLASH_Lock();  // Lock the Flash to disable the flash control register access
    return HAL_OK;
}

 

Interestingly, there's no HAL_ERROR after calling HAL_FLASHEx_Erase(), but PageError returns 0xFFFFFFFF. This leads to a HAL_ERROR when attempting to write to the memory location afterwards with HAL_FLASH_Program().

 

I've previously had this functionality working, but it's currently not behaving as expected, and I'm at a bit of a loss. I've checked and re-checked the page number and confirmed that the flash is being unlocked successfully. The same goes for the flash lock at the end of the operation.

 

Has anyone encountered a similar issue or have insights into what might be going wrong? Any suggestions or advice would be greatly appreciated.

 

Thank you in advance for your help!

 

Adrian.

 

1 ACCEPTED SOLUTION

Accepted Solutions
AChap.1
Associate III

Hi @TDK ,

Thank you so much for your advice regarding the dual-bank configuration and the suggestion to inspect the option bytes using STM32CubeProgrammer. I took your recommendations on board and delved into CubeProgrammer to get a better understanding of my STM32L476's configuration. Here's what I discovered and how it led me to a solution:

  1. Dual-Bank Configuration: As you mentioned, the L476 can indeed operate in both single and dual-bank modes. Upon inspection, I confirmed that the DualBank option was indeed checked, validating that my device was set up for dual-bank operation, with each bank presumably starting its page numbering from 0.

  2. BFB2 Setting: I also noted that the BFB2 option was unchecked, which aligns with the dual-bank boot being disabled, and the microcontroller is set to boot from the main flash memory as per the standard booting procedure.

  3. Write Protection: I checked the write protection settings (WRP1A_END and WRP1B_END), and both were set to 0x0, indicating that write protection wasn't the cause of my issue, as no pages were write-protected.

Given these insights, particularly the confirmation of dual-bank operation with independent page numbering, I revisited my flash erase code. Initially, I had been trying to erase page 255 (EraseInitStruct.Page = 255;), working under the assumption that the pages were numbered sequentially across the two banks. However, understanding that each bank starts its page numbering from 0, I realized that page 255 would be outside the range of the first bank's pages.

I adjusted the page number to 127 (EraseInitStruct.Page = 127;), aiming to target the last page of the first bank, considering the dual-bank setup. This adjustment proved to be the solution, and the erase operation was successful, allowing me to proceed with setting the update flag as intended.

Please see my amended code:

 

HAL_StatusTypeDef set_update_flag(void) {
    // Unlock the Flash to enable the flash control register access
    HAL_StatusTypeDef status = HAL_FLASH_Unlock();
    if (status != HAL_OK) {
        // Unlock failed, handle accordingly
        return status;
    }

    // Define the page and bank for the erase operation
    FLASH_EraseInitTypeDef EraseInitStruct;
    uint32_t PageError = 0x0;
    EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.Banks = FLASH_BANK_2;
    EraseInitStruct.Page = 127;
    EraseInitStruct.NbPages = 1;

    // Erase the page
    status = HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
    if (status != HAL_OK) {
        // Erase failed, handle accordingly
        HAL_FLASH_Lock();  // Make sure to lock the flash again before returning
        // Use PageError to determine the page that caused the error if needed
        return status;
    }

    // Set the update flag to 1
    status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, UPDATE_FLAG_ADDRESS, 0x0000000100000001);
    if (status != HAL_OK) {
        // Program failed, handle accordingly
        HAL_FLASH_Lock();  // Make sure to lock the flash again before returning
        return status;
    }

    // Lock the Flash to disable the flash control register access
    HAL_FLASH_Lock();

    return HAL_OK;  // Return HAL_OK if the entire operation was successful
}

 

 

Your guidance was instrumental in helping me navigate this issue, and greatly appreciate.

Many thanks,

Adrian.

View solution in original post

4 REPLIES 4
TDK
Guru

Let's get a bit more specific.

> at the specified memory location are not set to 0xFF as expected. I've confirmed this by checking the memory location with STM32CubeProgrammer.

What memory location are you looking at? What values are you seeing?

Are you in dual bank mode?

Are the banks write protected by option bytes?

If you feel a post has answered your question, please click "Accept as Solution".
AChap.1
Associate III

Hi @TDK 

Hi,

Thank you for reaching out and helping me troubleshoot this issue.

  1. Memory Location and Values:

    • I am targeting a double word at the memory address 0x0807FFF0 for the update flag. This address is defined in my code as follows:

 

#define UPDATE_FLAG_ADDRESS 0x0807FFF0

 

  • The expected value after erasing should be 0xFFFFFFFFFFFFFFFF (indicating the double word is erased), but it remains at 0x0000000000000000, which was the value from a previous write operation.
  1. Cube Version and Regression Testing:

    • Initially, this functionality worked with STM32Cube FW_L4 V1.17.2. When I encountered the issue, I was using STM32Cube FW_L4 V1.18.0. To isolate the problem, I reverted to V1.17.2, but the issue persists, suggesting it may not be related to the Cube version.
  2. Single Bank vs. Dual Bank:

    • Given the STM32L476RET6's 512KB memory size, I assumed it operates in single bank mode. I did experiment with setting FLASH_BANK_2 in the EraseInitStruct.Banks field as a troubleshooting step, but as expected, it didn't resolve the issue.
  3. Write Protection:

    • I haven't explicitly set any write protections via option bytes. However, following your suggestion, I will double-check to ensure no write protections are inadvertently enabled that might be preventing the erase operation.

I appreciate your insights and am looking forward to any further advice you might have.

Adrian.

Single Bank vs. Dual Bank:

The L476 can operate in both modes. Look at the DUALBANK option bit to find out which one it's in. You can do this within STM32CubeProgrammer on the OB tab on the left. By default, the chip operates in dual bank mode.

You can also view the write protect option bytes from there as well.

Also you should probably ensure BFB2=0.

If you feel a post has answered your question, please click "Accept as Solution".
AChap.1
Associate III

Hi @TDK ,

Thank you so much for your advice regarding the dual-bank configuration and the suggestion to inspect the option bytes using STM32CubeProgrammer. I took your recommendations on board and delved into CubeProgrammer to get a better understanding of my STM32L476's configuration. Here's what I discovered and how it led me to a solution:

  1. Dual-Bank Configuration: As you mentioned, the L476 can indeed operate in both single and dual-bank modes. Upon inspection, I confirmed that the DualBank option was indeed checked, validating that my device was set up for dual-bank operation, with each bank presumably starting its page numbering from 0.

  2. BFB2 Setting: I also noted that the BFB2 option was unchecked, which aligns with the dual-bank boot being disabled, and the microcontroller is set to boot from the main flash memory as per the standard booting procedure.

  3. Write Protection: I checked the write protection settings (WRP1A_END and WRP1B_END), and both were set to 0x0, indicating that write protection wasn't the cause of my issue, as no pages were write-protected.

Given these insights, particularly the confirmation of dual-bank operation with independent page numbering, I revisited my flash erase code. Initially, I had been trying to erase page 255 (EraseInitStruct.Page = 255;), working under the assumption that the pages were numbered sequentially across the two banks. However, understanding that each bank starts its page numbering from 0, I realized that page 255 would be outside the range of the first bank's pages.

I adjusted the page number to 127 (EraseInitStruct.Page = 127;), aiming to target the last page of the first bank, considering the dual-bank setup. This adjustment proved to be the solution, and the erase operation was successful, allowing me to proceed with setting the update flag as intended.

Please see my amended code:

 

HAL_StatusTypeDef set_update_flag(void) {
    // Unlock the Flash to enable the flash control register access
    HAL_StatusTypeDef status = HAL_FLASH_Unlock();
    if (status != HAL_OK) {
        // Unlock failed, handle accordingly
        return status;
    }

    // Define the page and bank for the erase operation
    FLASH_EraseInitTypeDef EraseInitStruct;
    uint32_t PageError = 0x0;
    EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
    EraseInitStruct.Banks = FLASH_BANK_2;
    EraseInitStruct.Page = 127;
    EraseInitStruct.NbPages = 1;

    // Erase the page
    status = HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
    if (status != HAL_OK) {
        // Erase failed, handle accordingly
        HAL_FLASH_Lock();  // Make sure to lock the flash again before returning
        // Use PageError to determine the page that caused the error if needed
        return status;
    }

    // Set the update flag to 1
    status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, UPDATE_FLAG_ADDRESS, 0x0000000100000001);
    if (status != HAL_OK) {
        // Program failed, handle accordingly
        HAL_FLASH_Lock();  // Make sure to lock the flash again before returning
        return status;
    }

    // Lock the Flash to disable the flash control register access
    HAL_FLASH_Lock();

    return HAL_OK;  // Return HAL_OK if the entire operation was successful
}

 

 

Your guidance was instrumental in helping me navigate this issue, and greatly appreciate.

Many thanks,

Adrian.