cancel
Showing results for 
Search instead for 
Did you mean: 

New STM32_ExtMem_Manager driver for STM32H7S7 won't erase/write sectors

nico23
Senior III

I'm using an STM32H7S78-DK board and I have a part of the firmware that, from the boot, updates the FLASH from a .bin inside an SD card

The code is pretty simple as I loop the FLASH comparing every sector with the one in the SD card and, if different I erase the internal flash sector and write the new one.

Everything was working correctly until a update the code via CubeMX

The read seems to still working

if (EXTMEM_Read(0, fw_offset, flash_buf, br) != 0)

but as soon as I do the

if (EXTMEM_EraseSector(0, fw_offset, FLASH_SECTOR_SIZE) != 0)

I got an error

The crash happens in

          if (EXTMEM_DRIVER_NOR_SFDP_OK != EXTMEM_DRIVER_NOR_SFDP_SectorErase(&extmem_list_config[MemId].NorSfdpObject,
                                                                              local_address, sector_type))
          {
            retr = EXTMEM_ERROR_DRIVER;
          }

I've rolled back just the driver in the STM32_ExtMem_Manager, and everything started working again

I've noticed that quite a few files have been changed, including the addition of #define EXTMEM_DRIVER_CUSTOM     0

In the conf_template, it could be helpful to understand what's changed. Everything else has stayed the same. Where should I look?

 
Another thing that has changed, if it is useful to understand the changes, is that in stm32_sfdp_driver.c the 
#define ERASE_COMMAND 0x60 has been deleted
 
What could be the issue?
 
I've just found out that I've updated from SLA0044 Rev5/February 2018 to SLA0044 Rev6/October 2025
4 REPLIES 4
Guenael Cadier
ST Employee

Hi @nico23 
I guess you are now using ExtMemManager v1.5.0 right ?
And that you were previously using v1.3.0 ?

The 1.5.0 version contains addition of a new driver inside EMM, called CUSTOM. It is fully separated from the NOR_SFDP driver, so should have no impact on the use of NOR_SFDP driver, as in your configuration.

ERASE_COMMAND define was removed in v1.4.0 and has been replaced by SFDP_DRIVER_ERASE_CHIP_COMMAND which is now located in stm32_sfdp_driver_type.h (same value).
(this define corresponds to the full chip erase instraction, so should not be used when performing EXTMEM_DRIVER_NOR_SFDP_SectorErase().)

If you debug inside EXTMEM_DRIVER_NOR_SFDP_SectorErase() what is the command and type of erase operation that will be executed ?
What is the error code returned by EXTMEM_DRIVER_NOR_SFDP_SectorErase() ?

Regards

Hi @Guenael Cadier ,

I can confirm

#define EXTMEM_VERSION 0x00010500 /* Version v1.5.0 */

I've done various test and at some point I'm seeing driver_check_FlagBUSY function return error EXTMEM_DRIVER_NOR_SFDP_ERROR_BUSY

This is the command I'm launching

EXTMEM_EraseSector(0, fw_offset, FLASH_SECTOR_SIZE); with fw_offset=0 e #define FLASH_SECTOR_SIZE               0x2000UL  /* 8 KB */

                EXTMEM_DRIVER_NOR_SFDP_SectorErase(&extmem_list_config[MemId].NorSfdpObject,
                                                   local_address, sector_type))

local_address=0x24004557
sector_type=EXTMEM_DRIVER_NOR_SFDP_SECTOR_TYPE1

Inside EXTMEM_DRIVER_NOR_SFDP_SectorErase it's executing

    case EXTMEM_DRIVER_NOR_SFDP_SECTOR_TYPE1:
      command = SFDPObject->sfdp_private.DriverInfo.EraseType1Command;
      size = SFDPObject->sfdp_private.DriverInfo.EraseType1Size;
      timeout = SFDPObject->sfdp_private.DriverInfo.EraseType1Timing;
      break;

Command and size value are correct (command is 0x21).

I can't understand why  local_address doesn't have an address of my external memory, even if I pass 

EXTMEM_EraseSector(0, fw_offset

with fw_offset=0 (in fact, it fails at the very first iteration).

The memory chip on board is mx66uw1g45g.

My current init is

/**
  * Init External memory manager
  * @retval None
  */
void MX_EXTMEM_MANAGER_Init(void)
{

  /* USER CODE BEGIN MX_EXTMEM_Init_PreTreatment */

  /* USER CODE END MX_EXTMEM_Init_PreTreatment */
  HAL_RCCEx_EnableClockProtection(RCC_CLOCKPROTECT_XSPI);

  /* Initialization of the memory parameters */
  memset(extmem_list_config, 0x0, sizeof(extmem_list_config));

  /* EXTMEMORY_1 */
  extmem_list_config[0].MemType = EXTMEM_NOR_SFDP;
  extmem_list_config[0].Handle = (void*)&hxspi2;
  extmem_list_config[0].ConfigType = EXTMEM_LINK_CONFIG_8LINES;

  /* EXTMEMORY_2 */
  extmem_list_config[1].MemType = EXTMEM_PSRAM;
  extmem_list_config[1].Handle = (void*)&hxspi1;
  extmem_list_config[1].ConfigType = EXTMEM_LINK_CONFIG_16LINES;

  extmem_list_config[1].PsramObject.psram_public.MemorySize = HAL_XSPI_SIZE_256MB;
  extmem_list_config[1].PsramObject.psram_public.FreqMax = 200 * 1000000u;
  extmem_list_config[1].PsramObject.psram_public.NumberOfConfig = 1u;

  /* Config */
  extmem_list_config[1].PsramObject.psram_public.config[0].WriteMask = 0x40u;
  extmem_list_config[1].PsramObject.psram_public.config[0].WriteValue = 0x40u;
  extmem_list_config[1].PsramObject.psram_public.config[0].REGAddress = 0x08u;

  /* Memory command configuration */
  extmem_list_config[1].PsramObject.psram_public.ReadREG           = 0x40u;
  extmem_list_config[1].PsramObject.psram_public.WriteREG          = 0xC0u;
  extmem_list_config[1].PsramObject.psram_public.ReadREGSize       = 2u;
  extmem_list_config[1].PsramObject.psram_public.REG_DummyCycle    = 4u;
  extmem_list_config[1].PsramObject.psram_public.Write_command     = 0xA0u;
  extmem_list_config[1].PsramObject.psram_public.Write_DummyCycle  = 4u;
  extmem_list_config[1].PsramObject.psram_public.Read_command      = 0x20u;
  extmem_list_config[1].PsramObject.psram_public.WrapRead_command  = 0x00u;
  extmem_list_config[1].PsramObject.psram_public.Read_DummyCycle   = 4u;

  EXTMEM_Init(EXTMEMORY_1, HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_XSPI2));
  EXTMEM_Init(EXTMEMORY_2, HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_XSPI1));

  /* USER CODE BEGIN MX_EXTMEM_Init_PostTreatment */

  /* USER CODE END MX_EXTMEM_Init_PostTreatment */
}

I don't know if it is useful, but in the Boot code, I have just the external PSRAM memory area (used for the framebuffer) in the MPU settings.

static void MPU_Config(void)
{
  MPU_Region_InitTypeDef MPU_InitStruct = {0};

  /* Disables the MPU */
  HAL_MPU_Disable();

  /* Disables all MPU regions */
  for(uint8_t i=0; i<__MPU_REGIONCOUNT; i++)
  {
    HAL_MPU_DisableRegion(i);
  }

  /** Initializes and configures the Region and the memory to be protected
  */
  MPU_InitStruct.Enable = MPU_REGION_ENABLE;
  MPU_InitStruct.Number = MPU_REGION_NUMBER3;
  MPU_InitStruct.BaseAddress = 0x90000000;
  MPU_InitStruct.Size = MPU_REGION_SIZE_32B;
  MPU_InitStruct.SubRegionDisable = 0x0;
  MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
  MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
  MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
  MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
  MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
  MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;

  HAL_MPU_ConfigRegion(&MPU_InitStruct);
  /* Enables the MPU */
  HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

}

Why is that?

nico23
Senior III

Hi @Guenael Cadier 

any news on this?

Guenael Cadier
ST Employee

Hi @nico23 
From calling EXTMEM_EraseSector(), with fw_offset = 0, I can't figure how you could get local_address=0x24004557 when calling sub function EXTMEM_DRIVER_NOR_SFDP_SectorErase().
This is abnormal in my opinion.

Could your stack be damaged or too short ?

Regards