Electrical – STM32F1 Flash erase not erasing

cflashhal-librarystm32f10x

Hello everyone,

I am trying to write in the FLASH of my STM32F1, but for some reason it is not working … Whenever I am programming something, it wil return an error : HAL_FLASH_ERROR_PROG which is a programming error. When I look at it in the flash status register, it means : Set by hardware when an address to be programmed contains a value different from '0xFFFF' before programming.

When I then parse into the FLASH memory of my STM32F1, I see that memory rangin from : 0x801EC00 to 0x801F17F is filled with 0x0000. Hence the Programming error.

What I don't understand is why this part of the memory hasn't been erased. Here is my code :

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 20K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 128K - 5K
Erases (RW)          : ORIGIN = 0x801EC00, LENGTH = 4
Frames (RW)          : ORIGIN = 0x801EC04, LENGTH = 4
FRAMESTx (RW)     : ORIGIN = 0x801EC08, LENGTH = 1400
FRAMESRx (RW)     : ORIGIN = 0x801F180, LENGTH = 1800
FRAMESADC(RW)     : ORIGIN = 0x801F888, LENGTH = 800
FRAMESOP (RW)     : ORIGIN = 0x801FBA8, LENGTH = 800
}


/* Define output sections */
SECTIONS
{
  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH

 .nb_Erases : 
 {
    . = ALIGN(4);

      *(.nb_Erases)

    . = ALIGN(4);
    } > Erases

 .nb_Frames : 
 {
    . = ALIGN(4);

      *(.nb_Frames)

    . = ALIGN(4);
    } > Frames

 .user_TramesTx : 
 {
    . = ALIGN(4);

      *(.user_FramesTx)

    . = ALIGN(4);
    } > FRAMESTx

 .user_TramesRx : 
 {
    . = ALIGN(4);

      *(.user_FramesRx)

    . = ALIGN(4);
    } > FRAMESRx

 .user_TramesADC : 
 {
    . = ALIGN(4);

      *(.user_FramesADC)

    . = ALIGN(4);
    } > FRAMESADC

 .user_TramesOp : 
 {
    . = ALIGN(4);

      *(.user_FramesOp)

    . = ALIGN(4);
    } > FRAMESOP

for the linker script

#include "includes.h"

__attribute__((__section__(".nb_Erases"))) const uint32_t Flash_nb_Erases;
__attribute__((__section__(".nb_Frames"))) const uint32_t Flash_nb_Frames;
__attribute__((__section__(".user_TramesTx"))) const CanTxMsgTypeDef CAN_Tab_TxMessages_Flash[50];
__attribute__((__section__(".user_TramesRx"))) const CanRxMsgTypeDef CAN_Tab_RxMessages_Flash[50];
__attribute__((__section__(".user_TramesADC"))) const ADC_TxTypeDef CAN_ADC_Tab_TxMessages_Flash[50];
__attribute__((__section__(".user_TramesOp"))) const CAN_operation Operation_Flash[50];



int Flash_writepreparation(void)
/* Resumé : Function preparing for Flash writing. Unlock flash, clear flags and erase flash.
 *
 * Arguments : none
 *
 * Return : -1 if everything is ok, else : faulty page number
 *
 */
{
     FLASH_EraseInitTypeDef *Erase_Page = NULL;
     uint32_t *Erasing_Error = NULL;


     if (HAL_FLASH_Unlock() != HAL_OK)                                                                                     // We unlock the FLASH to write in it
     {
          return(0);
     }
     __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPERR | FLASH_FLAG_BSY | FLASH_FLAG_OPTVERR );     // Clear of every FLASH flag
     Erase_Page = malloc(sizeof(Erase_Page));                                                                           // Configuration of the Erase_Page structure
     Erasing_Error = malloc(sizeof(Erasing_Error));
     if(Erase_Page == NULL || Erasing_Error == NULL)
     {
          Error_Handler();
     }
     Erase_Page ->TypeErase = FLASH_TYPEERASE_PAGES;
     Erase_Page ->PageAddress =0x801EC00; //ADDRESSE DU DEBUT DE DATA SAUVEGARDE
     Erase_Page ->NbPages = 5;
     HAL_FLASHEx_Erase(Erase_Page , Erasing_Error);                                                                 // We need to erase FLASH to be able to write on it
     if(*Erasing_Error!= 0xFFFFFFFF)
     {
          return(*Erasing_Error);                                                                                          // If there is an error during the erase, Erasing_Error takes the faulty page value
     }
     else
     {
          return(-1);                                                                                                              // -1 = everything is ok
     }

}




int Flash_CANTx_write(CanTxMsgTypeDef *CAN_Tab_TxMessages)
/* Résumé : Function writing CANTx frames in FLASH memory
 *
 * Arguments : CAN_Tab_TxMessages
 *
 * Retourne : 1 if everything is ok, 0 otherwise
 *
 */
{
     uint32_t nb_Erases = 0;
     uint32_t nb_frames_Tx = 0;


     int count_Frames;

     nb_Erases = Flash_nb_Erases + 1;
     nb_frames_Tx = CAN_nb_frames_Tx_cc; //CAN_nb_frames_Tx_cc defined in includes.h

     for (count_Frames= 0 ; count_Frames< nb_frames_Tx ; count_Frames++)
     {
          if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (intptr_t)&CAN_Tab_TxMessages_Flash[count_Frames].DLC, CAN_Tab_TxMessages[count_Frames].DLC) != HAL_OK)     
          {                                                       
               return 0;
          }
          if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (intptr_t)&CAN_Tab_TxMessages_Flash[count_Frames].ExtId, CAN_Tab_TxMessages[count_Frames].ExtId) != HAL_OK)
          {
               return 0;
          }
          if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (intptr_t)&CAN_Tab_TxMessages_Flash[count_Frames].IDE, CAN_Tab_TxMessages[count_Frames].IDE) != HAL_OK)
          {
               return 0;
          }
          if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (intptr_t)&CAN_Tab_TxMessages_Flash[count_Frames].RTR, CAN_Tab_TxMessages[count_Frames].RTR) != HAL_OK)
          {
               return 0;
          }
          if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (intptr_t)&CAN_Tab_TxMessages_Flash[count_Frames].StdId, CAN_Tab_TxMessages[count_Frames].StdId) != HAL_OK)
          {
               return 0;
          }
          if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (intptr_t)&CAN_Tab_TxMessages_Flash[count_Frames].Data[0], CAN_Tab_TxMessages[count_Frames].Data[0]) != HAL_OK)
          {
               return 0;
          }
          if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (intptr_t)&CAN_Tab_TxMessages_Flash[count_Frames].Data[4], CAN_Tab_TxMessages[count_Frames].Data[4]) != HAL_OK)
          {
               return 0;
          }
     }

     if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, (intptr_t)&Flash_nb_Erases , nb_Erases ) != HAL_OK)                                                       
     {
          return 0;
     }

     return 1;





}



int Saving_Flash(CanTxMsgTypeDef *CAN_Tab_TxMessages)
/* Résumé : Function saving in FLASH
 *
 * Arguments : CAN_Tab_TxMessages
 *
 * Retourne : 1 if everything is ok, 0 otherwise
 *
 */
{
     int test = 0;

     test = Flash_writepreparation();                                                  

     if (test != -1)
     {
          Error_Handler();
     }

     if(Flash_CANTx_write(CAN_Tab_TxMessages) != 1)                         
     {
          Error_Handler();
     }

     if(HAL_FLASH_Lock() != HAL_OK)                                                       //We need to lock the FLASH at the end
     {
          Error_Handler();
     }

     return 1;



}

The function "Saving_Flash" is the one I call in main.c to save the CAN_Tab_TxMessages in the FLASH. Flash_writepreparation() is supposed to prepare the Flash for being written (unlock, erase the 5 pages, clear the flags). Finally, Flash_CANTx_write writes every frame of the array in the FLASH.

If you have any idea on why HAL_FLASHEx_Erase() is not working …

Just to add : there is no special warning or error when I build my code.

Thank you in advance !

I've tried to change the address of HAL_FLASH_Program in FLASH_CANTx_Write, to put &CAN_Tab_RxMessages_Flash, now, starting from 0x801F180 to 0x801F888 in the memory buffer is equal to 00000000. So it appears that depending on where I want to write, the address won't erase properly … But I don't know how to deal with it ..

EDIT : IT IS WORKING ! more or less …
The writing is now functionning but the reading not completely …

To retrieve the data I wrote in the Flash I am doing this :

__attribute__((__section__(".nb_Frames"))) extern const uint32_t number_Frames_Flash;
__attribute__((__section__(".user_FramesTx"))) extern const CanTxMsgTypeDef CAN_Tab_TxMessages_Flash[50];

[...]

CAN_nb_frames_Tx = (number_Frames_Flash & 0x000000FF);


for(cpt_for = 0 ; cpt_for < CAN_nb_frames_Tx ; cpt_for ++)
{
      CAN_Tab_TxMessages[cpt_for] = CAN_Tab_TxMessages_Flash[cpt_for];
}

Since the number of Tx Frames is stored in the right byte of number_Frames_Flash, I just look at the right byte.
But the issue is that CAN_nb_frames_Tx stays = 0 ; whereas if I look at the value of "(number_Frames_Flash & 0x000000FF)" in the debugger, it is equal to the value I expect (i.e the number of Tx Frames).
I don't know where it's coming from …

I am almost done !

Best Answer

You should not use malloc on an embedded system (unless you wrote a custom malloc?). Looks like you're erasing a different region of memory than you intended.

An example of a similar problem from someone using malloc on an STM32F1:

https://stackoverflow.com/questions/22422733/malloc-behaviour-on-an-embedded-system