STM32H735 Erase/Program from external Memory
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, §orError)};
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
