STM32H5 external loader
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎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
- Labels:
-
STM32H5 Series
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-01-20 6:17 AM
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-01-20 6: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;
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-01-20 6:48 AM
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-01-20 7: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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-01-20 7: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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-01-20 7: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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-01-20 8:07 AM
https://github.com/cturvey/stm32extldr/blob/main/h5_mx25l25645g/README.md
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-01-20 9: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"
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎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?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2025-01-21 12:27 AM
