When flashing code on STM32H7, blocks of 0s appear in reserved flash memory.
- August 23, 2022
- 3 replies
- 3130 views
Hey everyone.
In my project, I want to reserve some flash sectors to write data that I don't want erased when flashing new code on my processor.
So I changed the .ld files to reserve my memory as follow :
M7 files :
STM32H755ZITX_FLASH.ld and STM32H755ZITX_RAM.ld :
/* Memories definition */
MEMORY
{
RAM_D1 (xrw) : ORIGIN = 0x24000000, LENGTH = 512K
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1408K /* added m4 memory to m7 since I don't need it on the m4 */
USER_FLASH (rx) : ORIGIN = 0x08180000, LENGTH = 512K
DTCMRAM (xrw) : ORIGIN...
...
}
/* The rest is unchanged */M4 files :
STM32H755ZITX_FLASH.ld
MEMORY
{
FLASH (rx) : ORIGIN = 0x08160000, LENGTH = 128K
RAM (xrw) : ORIGIN = 0x10000000, LENGTH = 288K
}
/* rest is unchanged */I can write to the reserved flash USER_FLASH using functions I defined without any apparent problem. Indeed, when I check my memory with a memory monitor, everything is writen correctly. Here are the functions :
#include "stm32h7xx_hal.h"
/**
* @brief Return the sector corresponding to the address
* given in argument
* @param The address you want to know the
* sector of.
*
* @retval The number corresponding to the sector, or
* -1 if an error occured
*/
int8_t GetSector(uint32_t address)
{
if ((address >= 0x08000000 && address < 0x08020000) || (address >= 0x08100000 && address < 0x08120000))
{
return FLASH_SECTOR_0;
}
if ((address >= 0x08020000 && address < 0x08040000) || (address >= 0x08120000 && address < 0x08140000))
{
return FLASH_SECTOR_1;
}
if ((address >= 0x08040000 && address < 0x08060000) || (address >= 0x08140000 && address < 0x08160000))
{
return FLASH_SECTOR_2;
}
if ((address >= 0x08060000 && address < 0x08080000) || (address >= 0x08160000 && address < 0x08180000))
{
return FLASH_SECTOR_3;
}
if ((address >= 0x08080000 && address < 0x080A0000) || (address >= 0x08180000 && address < 0x081A0000))
{
return FLASH_SECTOR_4;
}
if ((address >= 0x080A0000 && address < 0x080C0000) || (address >= 0x081A0000 && address < 0x081C0000))
{
return FLASH_SECTOR_5;
}
if ((address >= 0x080C0000 && address < 0x080E0000) || (address >= 0x081C0000 && address < 0x081E0000))
{
return FLASH_SECTOR_6;
}
if ((address >= 0x080E0000 && address < 0x08100000) || (address >= 0x081E0000 && address < 0x08200000))
{
return FLASH_SECTOR_7;
}
return -1;
}
/**
* @brief Return the bank corresponding to the address
* given in argument
* @param The address you want to know the
* bank of.
*
* @retval The number corresponding to the bank, or
* -1 if an error occured
*/
int8_t GetBank(uint32_t address)
{
if (address >= 0x08000000 && address < 0x08100000)
{
return FLASH_BANK_1;
}
if (address >= 0x08100000 && address < 0x08200000)
{
return FLASH_BANK_2;
}
return -1;
}
/**
* @brief Erase the specified FLASH memory sector
* @param Sector FLASH sector to erase
* This parameter can be a value of @ref FLASH_Sectors
* @param nbSectors the number of contiguous sector you want to erase.
* For instance, if nbSectors is 2 and StartSector is FLASH_SECTOR_3,
* sectors 3 and 4 are going to be erased.
* This parameter must be a value between 1 and (max number of sectors (8)- value of Initial sector)
* @param Banks Banks to be erased
* This parameter can be one of the following values:
* @arg FLASH_BANK_1: Bank1 to be erased
* @arg FLASH_BANK_2: Bank2 to be erased
* @arg FLASH_BANK_BOTH: Bank1 and Bank2 to be erased
*
* @retval None
*/
int32_t Flash_Erase_Sector(uint32_t StartSector, uint32_t Banks, uint32_t nbSectors)
{
if (Banks < 0 || StartSector < 0 || nbSectors < 1 || nbSectors > 8-StartSector)
{
return -1;
}
FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t SECTORError;
/* Unlock the Flash to enable the flash control register access *************/
HAL_FLASH_Unlock();
/* Erase the user Flash area*/
/* Fill EraseInit structure*/
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.Sector = StartSector;
EraseInitStruct.NbSectors = nbSectors;
EraseInitStruct.Banks = Banks;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
{
/*Error occurred while page erase.*/
return HAL_FLASH_GetError ();
}
HAL_FLASH_Lock();
return 0;
}
/**
* @brief Write (size*32) bytes of data in the flash memory
* @param StartAddress is the address where you want
* to start writing to.
* @param Data is a buffer containing the data you want
* to write in the flash memory.
* @param size the number of 32-bytes data you want to read
* @param erase set to TRUE to erase memory before writing
* set to FALSE to not erase memory.
*
* @retval Return the next available address on success, 0 if an error occured while
* retrieving the sector/bank where you wanted to write or a
* HAL_Error if an error occured while erasing or writing the flash.
*
* @note When writing to a sector, the whole sector will be erased first.
* Make sure there wasn't any important data here first.
*/
uint32_t Flash_Write_Data_32 (uint32_t StartAddress, uint32_t * Data, int32_t size, bool erase)
{
static FLASH_EraseInitTypeDef EraseInitStruct;
uint32_t SECTORError;
uint8_t nbSector = (size / 128000) + 1; // Les secteurs font 128 Kbytes
uint8_t StartSector = GetSector(StartAddress);
uint8_t bank = GetBank(StartAddress);
if (bank < 0 || StartSector < 0 || StartSector + nbSector -1 > 7)
{
return 0;
}
/* Unlock the Flash to enable the flash control register access *************/
HAL_FLASH_Unlock();
if (erase)
{
/* Erase the user Flash area*/
/* Fill EraseInit structure*/
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.Sector = StartSector;
EraseInitStruct.NbSectors = nbSector;
EraseInitStruct.Banks = bank;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
{
/*Error occurred while page erase.*/
return HAL_FLASH_GetError ();
}
}
/* Program the user Flash area word by word*/
while (size > 0)
{
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, StartAddress, Data) == HAL_OK)
{
StartAddress += 32;
Data += 8;
size -= 8;
}
else
{
/* Error occurred while writing data in Flash memory*/
return HAL_FLASH_GetError ();
}
}
/* Lock the Flash to disable the flash control register access (recommended
to protect the FLASH memory against possible unwanted operation) */
HAL_FLASH_Lock();
return StartAddress;
}
/**
* @brief Read data from the flash memory
* @param [in] StartAddress is the address where you want
* to start Reading from.
* @param [out] RxBuf is a buffer were read data will be placed.
* Make sure it can contain at least size bytes of data.
* @param [in] Size is the number of 32-bytes data to read.
*
* @retval None
*/
void Flash_Read_Data_32 (uint32_t StartAddress, uint32_t *RxBuf, uint32_t size) // Size en 32octet
{
for(int i=size; i>0 ; i--)
{
*RxBuf = *(__IO uint32_t *)StartAddress;
StartAddress += 4;
RxBuf ++;
}
}However, as soon as I flash my code, an apparently random number of 0s are written in the flash sector where I wrote during last execution. The blocks of 0s are all the same size though, and appear periodically every 0x200 bytes (at 0x08xxx000, 0x08xxx200, 0x08xxx400, 0x08xxx600, etc... - see attachments). The rest of the data I wrote are still here, and other sectors aren't affected.
Any idea what could cause this ? I tried to use watchpoint to see when this could happen, but without any success. Any help will be greatly appreciated.
I'm using STM32CubeIDE to flash my code and am using a NUCLEO-H755ZI-Q demo board to test my code.
Thank you and have a nice day !
QL
