cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H5 external loader

AMend.7
Associate III

Hi,

 I need the project used to generate the external loader: MX25LM51245G_STM32H573I-DK.stldr. My custom board uses a STM32H563VIT6 and the same octo-spi flash from Macronix used in the STM32H573I-DK board. But with different gpios connections. So this project would be of great help to develop the external flash loader for my board.

 

Ari

55 REPLIES 55
Berto
Associate III

Hi all,

Thank you so much, very helpful!

@Tesla DeLorean  i'm using the following pins:

  • OCTOSPI1_IO3 --> PF6
  • OCTOSPI1_IO2 --> PF7
  • OCTOSPI1_IO0 --> PF8
  • OCTOSPI1_IO1 --> PF9
  • OCTOSPI1_CLK --> PF10
  • OCTOSPI1_NCS --> PE11

@ABasi.2Can you share also your configuration for the CSP_QSPI_EnableMemoryMappedMode and CSP_QSPI_WriteMemory fuctions?

Thanks again.

Hi Berto

yes no problem, keep in mind my memory is a MX25L512

uint8_t CSP_QSPI_EnableMemoryMappedMode(void)
{
  XSPI_RegularCmdTypeDef sCommand;
  XSPI_MemoryMappedTypeDef sMemMappedCfg;
 

  // Enable Memory-Mapped mode--------------------------------------------------
  sCommand.OperationType = HAL_XSPI_OPTYPE_COMMON_CFG;
  sCommand.IOSelect = HAL_XSPI_SELECT_IO_3_0;
  sCommand.Instruction = QUAD_OUT_FAST_READ_CMD;
  sCommand.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE;
  sCommand.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS;
  sCommand.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE;
  sCommand.Address = 0;
  sCommand.AddressMode = HAL_XSPI_ADDRESS_1_LINE;
  sCommand.AddressWidth = HAL_XSPI_ADDRESS_24_BITS;
  sCommand.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_DISABLE;
  sCommand.AlternateBytes = 0;
  sCommand.AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE;
  sCommand.AlternateBytesWidth = HAL_XSPI_ALT_BYTES_8_BITS;
  sCommand.AlternateBytesDTRMode = HAL_XSPI_ALT_BYTES_DTR_DISABLE;
  sCommand.DataMode = HAL_XSPI_DATA_4_LINES;
  sCommand.DataLength = 0;
  sCommand.DataDTRMode = HAL_XSPI_DATA_DTR_DISABLE;
  sCommand.DummyCycles = DUMMY_CLOCK_CYCLES_READ_QUAD;
  sCommand.DQSMode = HAL_XSPI_DQS_DISABLE;
  sCommand.SIOOMode = HAL_XSPI_SIOO_INST_EVERY_CMD;

  sMemMappedCfg.TimeOutActivation = HAL_XSPI_TIMEOUT_COUNTER_DISABLE;

  if(HAL_XSPI_Command(&hospi1, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE)!= HAL_OK)
  {
    return HAL_ERROR;
  }

  if (HAL_XSPI_MemoryMapped(&hospi1,&sMemMappedCfg) != HAL_OK)
  {
    return HAL_ERROR;
  }

  return HAL_OK;
}

 

uint8_t CSP_QSPI_WriteMemory(uint8_t* buffer, uint32_t address,uint32_t buffer_size)
{
  XSPI_RegularCmdTypeDef sCommand;
  uint32_t end_addr, current_size, current_addr;

  
  // Calculation of the size between the write address and the end of the page
  current_addr = 0;

  while(current_addr <= address)
  {
    current_addr += MEMORY_PAGE_SIZE;
  }
  current_size = current_addr - address;

  // Check if the size of the data is less than the remaining place in the page
  if(current_size > buffer_size)
  {
    current_size = buffer_size;
  }

  // Initialize the adress variables
  current_addr = address;
  end_addr = address + buffer_size;

  sCommand.OperationType = HAL_XSPI_OPTYPE_COMMON_CFG;
  sCommand.IOSelect = HAL_XSPI_SELECT_IO_3_0;
  sCommand.Instruction = QUAD_IN_FAST_PROG_CMD;
  sCommand.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE;
  sCommand.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS;
  sCommand.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE;
  sCommand.AddressMode = HAL_XSPI_ADDRESS_4_LINES;
  sCommand.AddressWidth = HAL_XSPI_ADDRESS_24_BITS;
  sCommand.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_DISABLE;
  sCommand.AlternateBytes = 0;
  sCommand.AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE;
  sCommand.AlternateBytesWidth = HAL_XSPI_ALT_BYTES_8_BITS;
  sCommand.AlternateBytesDTRMode = HAL_XSPI_ALT_BYTES_DTR_DISABLE;
  sCommand.DataMode = HAL_XSPI_DATA_4_LINES;
  sCommand.DataDTRMode = HAL_XSPI_DATA_DTR_DISABLE;
  sCommand.DummyCycles = 0;
  sCommand.DQSMode = HAL_XSPI_DQS_DISABLE;
  sCommand.SIOOMode = HAL_XSPI_SIOO_INST_EVERY_CMD;

  // Perform the write page by page
  do
  {
    sCommand.Address = current_addr;
    sCommand.DataLength = current_size;

    if(current_size == 0)
    {
	  return HAL_OK;
    }

    // Enable write operations
    if(QSPI_WriteEnable() != HAL_OK)
    {
      return HAL_ERROR;
    }

    // Configure the command
    if(HAL_XSPI_Command(&hospi1, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE)!= HAL_OK)
    {
      return HAL_ERROR;
    }

    // Transmission of the data
    if(HAL_XSPI_Transmit(&hospi1, buffer,HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
    {
      return HAL_ERROR;
    }

    // Configure automatic polling mode to wait for end of program
    if(QSPI_AutoPollingMemReady(HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
    {
      return HAL_ERROR;
    }

    // Update the address and size variables for next page programming
    current_addr += current_size;
    buffer += current_size;
    current_size = ((current_addr + MEMORY_PAGE_SIZE) > end_addr) ?	(end_addr - current_addr) : MEMORY_PAGE_SIZE;

  }while(current_addr <= end_addr);

  return HAL_OK;
}

 

hello Berto

just to give you my setup:

i'm using the following pin with a STM32H563ZIT (on a NUCLEO-H563ZI)

  • OCTOSPI1_IO3 --> PD13
  • OCTOSPI1_IO2 --> PE2
  • OCTOSPI1_IO0 --> PD11
  • OCTOSPI1_IO1 --> PD12
  • OCTOSPI1_CLK --> PB2
  • OCTOSPI1_NCS --> PG6

 

 

Berto
Associate III

Hi @ABasi.2 ,

thanks, my configuration is similar as yours, it returns an error in the last check:

for(var = 0; var < SECTORS_COUNT; var++)
{
if(memcmp(buffer_test,(uint8_t*) (0x90000000 + var * MEMORY_SECTOR_SIZE),MEMORY_SECTOR_SIZE) != HAL_OK)
{
while(1); //breakpoint - error detected - otherwise QSPI works properly
}
}

Berto_0-1737385542720.png

Seems is not writing correctly data on the address 0x90000000

Hi berto

i think there are some dummy clocks in your configuration that are wrong, another guy in this forum have an issue similar to yours and resolve managing the dummy clocks 

 

check the parameter 

sCommand.DummyCycles

 according to your memory datasheet

Hi @ABasi.2 ,

Thank you! I try to check this parameter, do i need to modify this just in the write funcion or in all commands functions?

The Memory Mapped Mode just uses the same read command template as you can check in command mode.

You should be able to read in 1-bit and 2-bit modes to confirm actual content in the memory so you can determine "written wrong" vs "reading wrong"

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Berto
Associate III

Hi,

thanks so much for your suggestions, i'm trying to set up the correct dummycycles parameter.

Just a question, which is your clock configuration to peripheral and octospi prescaler?

 

hello Berto!

here my ioc file, i'm using the nucleo-H563ZI

hope this helps

notice i have HCLK 250Mhz and the OctoSpi is feeded by the HCLK