2023-10-23 12:13 PM - edited 2023-10-23 12:14 PM
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
2025-01-20 06:17 AM
Hi all,
Thank you so much, very helpful!
@Tesla DeLorean i'm using the following pins:
@ABasi.2Can you share also your configuration for the CSP_QSPI_EnableMemoryMappedMode and CSP_QSPI_WriteMemory fuctions?
Thanks again.
2025-01-20 06:44 AM
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;
}
2025-01-20 06:48 AM
hello Berto
just to give you my setup:
i'm using the following pin with a STM32H563ZIT (on a NUCLEO-H563ZI)
2025-01-20 07:12 AM
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
}
}
Seems is not writing correctly data on the address 0x90000000
2025-01-20 07:18 AM
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
2025-01-20 07:52 AM
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?
2025-01-20 08:07 AM
https://github.com/cturvey/stm32extldr/blob/main/h5_mx25l25645g/README.md
2025-01-20 09:15 AM
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"
2025-01-21 12:18 AM
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?
2025-01-21 12:27 AM