Skip to main content
Visitor II
August 19, 2024
Question

STM32H735 Erase/Program from external Memory

  • August 19, 2024
  • 1 reply
  • 1189 views

Good day everyone,

I am currently implementing an update process and I am facing some issues if I want to erase the internal flash memory sector if my code is running from an external OSPI-Flash. I am getting the errors:

  • Read Protection Error
  • Read Secure Error

I have not activated any readout-protection or anything. The only option Byte I have set is the write protection for the Flash Sector 1/2 (Depends on which one got updated last) But this error I am facing is related to the sector 3-7. 

The same piece of code runs totaly fine if I am executing it from the internal flash memory, but due to memory constraints I have to use the external OSPI-Flash. 

Attached you can find the output which exposes all option byte settings and the error code I have mentioned. And here the code snipped of the flash class:

#include "Flash.hpp"

#include 

#include "Bootloader/Utilities.hpp"

namespace HAL {
namespace Implementation {
namespace LLDriver {

static void debugOutput(void) {
 FLASH_OBProgramInitTypeDef optionByteConfig;

 optionByteConfig.Banks = FLASH_BANK_1;
 HAL_FLASHEx_OBGetConfig(&optionByteConfig);
 Bootloader::Utilities::print("------------OPTION-BYTE-SETTINGS------------");
 Bootloader::Utilities::print("OptionType: 0x%X", optionByteConfig.OptionType);
 Bootloader::Utilities::print("WRPState: 0x%X", optionByteConfig.WRPState);
 Bootloader::Utilities::print("WRPSector: 0x%X", optionByteConfig.WRPSector);
 Bootloader::Utilities::print("RDPLevel: 0x%X", optionByteConfig.RDPLevel);
 Bootloader::Utilities::print("BORLevel: 0x%X", optionByteConfig.BORLevel);
 Bootloader::Utilities::print("USERType: 0x%X", optionByteConfig.USERType);
 Bootloader::Utilities::print("USERConfig: 0x%X", optionByteConfig.USERConfig);
 Bootloader::Utilities::print("Banks: 0x%X", optionByteConfig.Banks);
 Bootloader::Utilities::print("PCROPConfig: 0x%X",
 optionByteConfig.PCROPConfig);
 Bootloader::Utilities::print("PCROPStartAddr: 0x%X",
 optionByteConfig.PCROPStartAddr);
 Bootloader::Utilities::print("PCROPEndAddr: 0x%X",
 optionByteConfig.PCROPEndAddr);
 Bootloader::Utilities::print("BootConfig: 0x%X", optionByteConfig.BootConfig);
 Bootloader::Utilities::print("BootAddr0: 0x%X", optionByteConfig.BootAddr0);
 Bootloader::Utilities::print("BootAddr1: 0x%X", optionByteConfig.BootAddr1);
 Bootloader::Utilities::print("SecureAreaConfig: 0x%X",
 optionByteConfig.SecureAreaConfig);
 Bootloader::Utilities::print("SecureAreaStartAddr: 0x%X",
 optionByteConfig.SecureAreaStartAddr);
 Bootloader::Utilities::print("SecureAreaEndAddr: 0x%X",
 optionByteConfig.SecureAreaEndAddr);
 Bootloader::Utilities::print("SharedRamConfig: 0x%X",
 optionByteConfig.SharedRamConfig);
 Bootloader::Utilities::print("FreqBoostState: 0x%X",
 optionByteConfig.FreqBoostState);

 if (HAL_FLASH_GetError() != 0) {
 Bootloader::Utilities::print("------------HAL_FLASH_GetError------------");
 Bootloader::Utilities::print("Error Code: 0x%x", HAL_FLASH_GetError());
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_WRP_BANK1) {
 Bootloader::Utilities::print("Write Protection Error on Bank 1");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_PGS_BANK1) {
 Bootloader::Utilities::print("Program Sequence Error on Bank 1");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_STRB_BANK1) {
 Bootloader::Utilities::print("Strobe Error on Bank 1");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_INC_BANK1) {
 Bootloader::Utilities::print("Inconsistency Error on Bank 1");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_OPE_BANK1) {
 Bootloader::Utilities::print("Operation Error on Bank 1");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_RDP_BANK1) {
 Bootloader::Utilities::print("Read Protection Error on Bank 1");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_RDS_BANK1) {
 Bootloader::Utilities::print("Read Secured Error on Bank 1");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_SNECC_BANK1) {
 Bootloader::Utilities::print("ECC Single Correction Error on Bank 1");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_DBECC_BANK1) {
 Bootloader::Utilities::print("ECC Double Detection Error on Bank 1");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_CRCRD_BANK1) {
 Bootloader::Utilities::print("CRC Read Error on Bank 1");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_WRP_BANK2) {
 Bootloader::Utilities::print("Write Protection Error on Bank 2");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_PGS_BANK2) {
 Bootloader::Utilities::print("Program Sequence Error on Bank 2");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_STRB_BANK2) {
 Bootloader::Utilities::print("Strobe Error on Bank 2");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_INC_BANK2) {
 Bootloader::Utilities::print("Inconsistency Error on Bank 2");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_OPE_BANK2) {
 Bootloader::Utilities::print("Operation Error on Bank 2");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_RDP_BANK2) {
 Bootloader::Utilities::print("Read Protection Error on Bank 2");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_RDS_BANK2) {
 Bootloader::Utilities::print("Read Secured Error on Bank 2");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_SNECC_BANK2) {
 Bootloader::Utilities::print("SNECC Error on Bank 2");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_DBECC_BANK2) {
 Bootloader::Utilities::print("Double Detection ECC on Bank 2");
 }
 if (HAL_FLASH_GetError() & HAL_FLASH_ERROR_CRCRD_BANK2) {
 Bootloader::Utilities::print("CRC Read Error on Bank 2");
 }
 }
}

static uint32_t toSector(uint32_t address) {
 if (address == 0x8000000UL) {
 return FLASH_SECTOR_0;
 } else if (address == 0x8020000UL) {
 return FLASH_SECTOR_1;
 } else if (address == 0x8040000UL) {
 return FLASH_SECTOR_2;
 } else if (address == 0x8060000UL) {
 return FLASH_SECTOR_3;
 } else if (address == 0x8080000UL) {
 return FLASH_SECTOR_4;
 } else if (address == 0x80A0000UL) {
 return FLASH_SECTOR_5;
 } else if (address == 0x80C0000UL) {
 return FLASH_SECTOR_6;
 } else if (address == 0x80E0000UL) {
 return FLASH_SECTOR_7;
 } else {
 Bootloader::Utilities::Error_Handler(
 Bootloader::Utilities::ErrorCodes::HAL_ERROR);
 return FLASH_SECTOR_0;
 }
}

static uint8_t getByte(const std::vector &bytes, uint32_t offset,
 uint32_t _offset) {
 if ((offset + _offset) < bytes.size()) {
 return bytes.at(offset + _offset);
 }
 return 0xFF;
}
static uint64_t toFlashWord(const std::vector &bytes,
 uint32_t offset) {
 uint64_t retval;

 uint64_t byte0{getByte(bytes, offset, 0)};
 uint64_t byte1{getByte(bytes, offset, 1)};
 uint64_t byte2{getByte(bytes, offset, 2)};
 uint64_t byte3{getByte(bytes, offset, 3)};
 uint64_t byte4{getByte(bytes, offset, 4)};
 uint64_t byte5{getByte(bytes, offset, 5)};
 uint64_t byte6{getByte(bytes, offset, 6)};
 uint64_t byte7{getByte(bytes, offset, 7)};

 retval = (uint64_t)byte0 | (uint64_t)(byte1 << 8) | (uint64_t)(byte2 << 16) |
 (uint64_t)(byte3 << 24) | (uint64_t)(byte4 << 32) |
 (uint64_t)(byte5 << 40) | (uint64_t)(byte6 << 48) |
 (uint64_t)(byte7 << 56);

 return retval;
}

class FlashLock {
 public:
 /**
 * @brief Construct a new Flash object
 *
 */
 FlashLock() {
 __disable_irq();
 SCB_DisableICache();
 if (HAL_FLASH_Unlock() != HAL_OK) {
 Bootloader::Utilities::Error_Handler(
 Bootloader::Utilities::ErrorCodes::HAL_ERROR);
 }
 }
 /**
 * @brief Destroy the Flash object
 *
 */
 ~FlashLock() {
 __enable_irq();
 /*lint -e1551 C functions which do not throw any exceptions*/
 SCB_EnableICache();
 if (HAL_FLASH_Lock() != HAL_OK) {
 Bootloader::Utilities::Error_Handler(
 Bootloader::Utilities::ErrorCodes::HAL_ERROR);
 }

 /*lint +e1551*/
 }
 /**
 * @brief Delete the copy and assignment constructors
 *
 */
 FlashLock(const FlashLock &) = delete;
 /**
 * @brief Delete the copy and assignment constructors
 *
 */
 FlashLock(FlashLock &&) = delete;
 /**
 * @brief Delete the copy and assignment constructors
 *
 */
 FlashLock &operator=(const FlashLock &) = delete;
 /**
 * @brief Delete the copy and assignment constructors
 *
 */
 FlashLock &operator=(FlashLock &&) = delete;
};

void Flash::write(uint32_t address, const std::vector &data) {
 static constexpr size_t FLASH_WORD_ALIGNMENT{32};

 size_t loopCounter{data.size() / FLASH_WORD_ALIGNMENT};

 if (data.size() % FLASH_WORD_ALIGNMENT) {
 loopCounter++;
 }

 uint32_t offset{0};
 for (size_t x = 0; x < loopCounter; x++) {
 uint64_t FlashWord[4] = {0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF};
 FlashWord[0] = toFlashWord(data, offset);
 FlashWord[1] = toFlashWord(data, 8 + offset);
 FlashWord[2] = toFlashWord(data, 16 + offset);
 FlashWord[3] = toFlashWord(data, 24 + offset);
#ifdef DEBUG_OUTPUT_ENABLE
 const uint32_t *ptr = reinterpret_cast(&FlashWord[0]);
 Bootloader::Utilities::print(
 "1) 0X%08x 0X%08x 0X%08x 0X%08x 0X%08x 0X%08x 0X%08x 0X%08x ", ptr[0],
 ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]);
 ptr = reinterpret_cast(data.data() + offset);
 Bootloader::Utilities::print(
 "2) 0X%08x 0X%08x 0X%08x 0X%08x 0X%08x 0X%08x 0X%08x 0X%08x ", ptr[0],
 ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]);
#endif
 offset += FLASH_WORD_ALIGNMENT;
 FlashLock flashLock;
 if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD, address,
 ((uint32_t)FlashWord)) != HAL_OK) {
 Bootloader::Utilities::Error_Handler(
 Bootloader::Utilities::ErrorCodes::HAL_ERROR);
 }
 address = address + FLASH_WORD_ALIGNMENT;
 }
}
std::vector Flash::read(uint32_t address, uint32_t numberOfBytes) {
 std::vector retval;
 retval.reserve(numberOfBytes);

 const uint8_t *flashPointer{reinterpret_cast(address)};

 for (uint32_t x = 0; x < numberOfBytes; x++) {
 retval.push_back(*flashPointer);
 flashPointer++;
 }
 return retval;
}

void Flash::erase(uint32_t address) {
 FLASH_EraseInitTypeDef eraseInitStruct;
 uint32_t sectorError;
 eraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
 eraseInitStruct.Banks = FLASH_BANK_1;
 eraseInitStruct.Sector = toSector(address);
 eraseInitStruct.NbSectors = 1;
 eraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;

 FlashLock flashLock;
 auto status{HAL_FLASHEx_Erase(&eraseInitStruct, &sectorError)};

 if (sectorError != 0xFFFFFFFF || status != HAL_OK) {
 Bootloader::Utilities::print(
 "SEC_AREA_END 0x%X",
 (FLASH->SCAR_CUR1 & FLASH_SCAR_SEC_AREA_END) >> 16);
 Bootloader::Utilities::print(
 "SEC_AREA_START 0x%X", (FLASH->SCAR_CUR1 & FLASH_SCAR_SEC_AREA_START));
 Bootloader::Utilities::print("Status: %d", status);
 Bootloader::Utilities::print("sectorError: %d", sectorError);
 debugOutput();
 Bootloader::Utilities::Error_Handler(
 Bootloader::Utilities::ErrorCodes::HAL_ERROR);
 }
}

uint32_t Flash::getFlashSectorSize(void) const {
 static constexpr uint32_t INTERNAL_FLASH_SECTOR_SIZE{0x20000};
 return INTERNAL_FLASH_SECTOR_SIZE;
}

} // namespace LLDriver
} // namespace Implementation
} // namespace HAL

 

Any help is highly appreciated as I am running out of ideas to find the root-cause or a work-arround.

 

Kind regards

    This topic has been closed for replies.

    1 reply

    Technical Moderator
    August 21, 2024

    Hello @sschneider,

     

    Are you enabling the secure access mode? Is SECURITY bit in FLASH_OPTSR_CUR register set to1?

    KDJEM1_0-1724249271728.png

    May be RM0468 section can help you to find the issue.

    Thank you.

    Kaouthar