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