Skip to main content
neil239955_st
Associate II
May 15, 2017
Question

STM32F407 FLASH erase fail with IWDG enabled (HAL)

  • May 15, 2017
  • 5 replies
  • 3796 views
Posted on May 15, 2017 at 12:47

Hi,

I am having a problem writing to flash with the IWDG enabled, presumably I am missing something.

I have cut my project down to a minimum that reproduces the problem.

The program initialises the HAL and system clocks and then erases a flash sector (FLASH_SECTOR_2), the compiler is told not to use sector 2 & 3 so I can store parameters in them.

This gives me a successful return value and all is well.

However if I enable IWDG (HAL_IWDG_Start()), then HAL_FLASHEx_Erase() fails with HAL_FLASH_GetError() = 6.

I've changed the watchdog to a long period to make sure its not interrupting the erase.

Have I skipped over some detail? I had assumed that the watchdog being independent all I needed to do was ensure the watch period was long enough not to interrupt the flash writing.

void MX_IWDG_Init(void)

{

  hiwdg.Instance = IWDG;

  hiwdg.Init.Prescaler = IWDG_PRESCALER_256;

  hiwdg.Init.Reload = 4095;

  HAL_IWDG_Init(&hiwdg);

}

  HAL_Init();

  SystemClock_Config();

  HAL_IWDG_Start(&hiwdg); /* Start Watchdog */

  HAL_FLASH_Unlock(); /* makes no difference */

 

  uint32_t error_sector_num = 0;

 

  FLASH_EraseInitTypeDef EraseInitStruct;

  EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;

  EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;

  EraseInitStruct.Sector = FLASH_SECTOR_2;

  EraseInitStruct.NbSectors = 1u;

 

  /* erase flash */

  if(HAL_FLASHEx_Erase(&EraseInitStruct, &error_sector_num) != HAL_OK)

  {

    /* Error while erasing sectors */

    uint32_t error_code = HAL_FLASH_GetError();

    __ASM volatile('BKPT #01');

  }

  else

  {

    __ASM volatile('BKPT #01');   

  }

Thanks in advance,

    This topic has been closed for replies.

    5 replies

    waclawek.jan
    Super User
    May 15, 2017
    Posted on May 15, 2017 at 13:20

    https://community.st.com/0D50X00009XkY4mSAF

    (with explanation in

    https://community.st.com/0D50X00009XkW4gSAF

    ) might be relevant.

    I am not going to comment on Cube.

    JW

    neil239955_st
    Associate II
    May 15, 2017
    Posted on May 15, 2017 at 15:15

    Thanks for the suggestion.

    I've read through the links you posted and they read as if the problem occurs immediately after changing the watchdog settings, my full project can run for hours of kicking the dog before attempting the flash write and failing.

    I have attempted the delays as suggested in the links anyway including kicking it every millisecond for 100mS before erasing the flash and it makes no difference.

    I've also tested that the watchdog times out at the intended time using a while() loop and that works fine too.

    I won't comment on the cube either as I'm 15k+ lines too deep already.

    (I missed off the call to MX_IWDG_Init() just after SystemClock_Config() in my previous post)

    waclawek.jan
    Super User
    May 15, 2017
    Posted on May 15, 2017 at 15:24

    Okay and what is the ratio between the dog's timeout and the FLASH erase/programming time then?

    JW

    matthewgkerr
    Associate III
    August 10, 2017
    Posted on August 10, 2017 at 09:13

    I appear to be having the same issue Neil. Did you resolve you issue?

    waclawek.jan
    Super User
    August 10, 2017
    Posted on August 10, 2017 at 11:07

    Please open a new thread (linking perhaps here for reference) with describing your own particular set of circumstances.

    JW

    matthewgkerr
    Associate III
    August 12, 2017
    Posted on August 12, 2017 at 05:42

    I was following the below example, but the erase was failing (returning 6).

    \Projects\STM32F4-Discovery\Examples\FLASH\FLASH_EraseProgram\

    Reading other posts, I noticed the following line was added after the flash was unlocked.

    /* Clear FLASH error flags */

    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR |

    FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR |

    FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR);

    This fixed my issue.

    My approach to managing the IWDG when writing to flash (in my case, doing an infield firmware upgrade) is to restart the application, NOT initialize the IWDG, update the firmware, restart, and then restart the IWDG. Hope that makes sense.

    Seng Tak Goh
    Associate III
    November 28, 2018

    Hi, I accidentally created a problem in my application with the IWDG and FLASH programming.

    In my program, the IWDG is initialised during boot up sequence in Cube's way, and the FLASH programming is initiated by user.

    It has been working fine until a recent change made the FLASH erroneously flip some bits on wrong memory locations.

    I have made sure that the addresses passed to the FLASH_Program_size are all correct, and searched to the end of the world until I found out that the root cause was actually that I have commented out the Initialization part of the IWDG peripheral, but the firmware still regularly kick the dog. The problem actually happened when it kicks while programming the FLASH.

    I could not find any note on this in the reference manual, however the IWDG block diagram kind of hinting that kicking the dog may have affected the VDD voltage bus, which is essential for the FLASH erasing and programming routine! You can see the relationship in the PWR-Power Supply overview of the MCU.

    I think this could be also the reason for Neil's problem, that when you try to Erase the FLASH shortly after starting the IWDG ( if the compiler did it that way without optimisation change), the voltage drop caused by IWDG starting raised some flags in FLASH registers.

    Just my humble opinion on this issue.

    Seng Tak

    waclawek.jan
    Super User
    November 28, 2018

    > The problem actually happened when it kicks while programming the FLASH.

    So, you are running the FLASH programming code out of RAM? And the IWDG kicking is in RAM, too? Can you please tell us more about your application?

    If you modify the code in a minimalistic way, so, that in the piece which kicks the IWDG, you replace only the write to the IWDG register by a write to a volatile variable in RAM, does the problem go away?

    Thanks,

    JW

    Seng Tak Goh
    Associate III
    November 29, 2018

    Hi Jan,

    The FLASH programming function runs in RAM while the IWDG refreshing runs is a Timer Interrupt Handler, in ROM, along some other small pieces of codes in that handler.

    Like I've said, the whole program has been running for months without any issue until I accidentally commented out the IWDG_init but the IWDG refresh is still being called regularly. I found out when I try to shorten the data being written to FLASH, the problem did not happen.

    But once I commented the IWDG_Refresh macro out in the timer handler, the original FLASH writing works without any issue.

    Finally I restore both the IWDG_Init and IWDG_Refresh, and everything works.

    Therefore I think writing to the IWDG Key register without IWDG being initiated properly could have caused some reactions in the VDD domain, where FLASH is somehow linked to.

    ST