cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H735 Erase/Program from external Memory

sschneider
Associate

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

1 REPLY 1
KDJEM.1
ST Employee

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

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.