cancel
Showing results for 
Search instead for 
Did you mean: 

Can't write to CM4 core

Skippy
Associate II

I have an stm32h745zit6 on my own board, where I can write correctly to the CM7 section (0x0800 0000 to 0x080F FFFF range) but not to the CM4 section (0x0810 0000 to 0x081E FFFF range), I also can't do a full erase of the chip, and it will give me an "Error: Mass erase operation failed.Please verify flash protection" error.

What my suspicion is that the option bytes at some point got messed up, but when reading the option bytes from memory the values don't make a lot of sense, and there are more bytes than what in the reference manual is indicated. (I attached the option bytes as a reference.)

To my knowledge I didn't write these option bytes, and don't have another one available now to test on as well, anything that I can do? As indicated, I do have access to the CM7 core, so I could write the default values to the option bytes, but would rather confirm here before messing stuff up and would need to know how to do this correctly.

Best, Hans

5 REPLIES 5
hansd56
Senior II

Which tools do you use?

Skippy
Associate II

I used

  • Dfu File Manager to generate the DFU's
  • DfuSeDemo for programming
  • I also used STM32CubeProgrammer

reading the RDPLevel it is set to OB_RDP_LEVEL_0, reading WRPState for FLASH_BANK_2 returns OB_WRPSTATE_DISABLE

hansd56
Senior II

I don't know DFU. Have you got a debug port and a reset button on your board? If yes get System Workbench (supports dual core) and try it with a small test application first. I have got the STM32H745I-Disco board and I can program both sections and start both cores in a controlled manner.

Skippy
Associate II

I don't have the debug port on it, we did some testing with this code:

HAL_FLASH_Unlock(); //unlock flash writing
    __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS_BANK1 | FLASH_FLAG_ALL_ERRORS_BANK2);
    FLASH_EraseInitTypeDef EraseInitStruct;
    EraseInitStruct.Banks = FLASH_BANK_2;
    EraseInitStruct.Sector = FLASH_SECTOR_0;
    EraseInitStruct.TypeErase = TYPEERASE_SECTORS;
    EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
    EraseInitStruct.NbSectors = 1;
    uint32_t SectorError = 0;
    if (HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) == HAL_OK)
    {
        uint32_t saveData[8] = {0x12345678, 0x12345678,0x12345678,0x12345678,0x12345678,0x12345678,0x12345678,0x12345678};
 
        HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD,FLASH_BANK2_BASE,(uint32_t)saveData);
    }
 
    HAL_FLASH_Lock();

and this works, we can read the code fine with stm32cubeprogrammer, but writing it isn't possible. Might be a DFU protocol issue?

We are suspicious that the DFU flashers aren't selecting Bank 2 and are just using Bank 1.

Skippy
Associate II

In the \DFU_Standalone example, it actually is hardcoded to BANK_1

uint16_t Flash_If_Erase(uint32_t Add)
{
  uint32_t startsector = 0, sectorerror = 0;
 
  /* Variable contains Flash operation status */
  HAL_StatusTypeDef status;
  FLASH_EraseInitTypeDef eraseinitstruct;
 
  /* Get the number of sector */
  startsector = GetSector(Add);
  eraseinitstruct.TypeErase = FLASH_TYPEERASE_SECTORS;
  eraseinitstruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
  eraseinitstruct.Banks = FLASH_BANK_1;
  eraseinitstruct.Sector = startsector;
  eraseinitstruct.NbSectors = 1;
 
  status = HAL_FLASHEx_Erase(&eraseinitstruct, &sectorerror);
 
  if (status != HAL_OK)
  {
    return 1;
  }
  return 0;
}

if this is actually used in the bootloader, it will never work. GetSector uses it correctly.

the code should be something like

uint16_t Flash_If_Erase(uint32_t Add)
{
  uint32_t startsector = 0, sectorerror = 0;
 
  /* Variable contains Flash operation status */
  HAL_StatusTypeDef status;
  FLASH_EraseInitTypeDef eraseinitstruct;
 
  /* Get the number of sector */
  startsector = GetSector(Add);
  eraseinitstruct.TypeErase = FLASH_TYPEERASE_SECTORS;
  eraseinitstruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
  eraseinitstruct.Banks = ((Add >= 0x08000000) && (Add < 0x08100000)) ? FLASH_BANK_1 : FLASH_BANK_2;
  eraseinitstruct.Sector = startsector;
  eraseinitstruct.NbSectors = 1;
 
  status = HAL_FLASHEx_Erase(&eraseinitstruct, &sectorerror);
 
  if (status != HAL_OK)
  {
    return 1;
  }
  return 0;
}