cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 with External QSPI Flash & SDRAM execution

DPila.1
Associate II

I am using STM32H7xx MCU with External QSPI Flash and SDRAM.

I want to download my code using STMCubeIDE directly to External QSPI Flash and once done I want to execute the same code from SDRAM without compromising the debugging ability using STMCubeIDE. Can someone help me with some procedure here.

1 ACCEPTED SOLUTION

Accepted Solutions
ChahinezC
Lead

Hello @DPila.1​,

For the  External QSPI Flash, I advise you to check the MOOC External QSPI loader how to.

For the SDRAM execution, the memory-mapped mode allows all AHB masters to access the Quad-SPI memory as an internal memory and to execute the code from the Quad-SPI memory. You can refer to the AN4760.

Best regards,

Chahinez.

View solution in original post

5 REPLIES 5

Generally one needs code to bring up the external interfaces, this normally comes in the form of a small loader you debug into initially, or a debug script that brings up the hardware, ie RCC, GPIO, QSPI, FMC, etc.

That way the MCU just accesses the memories in way that the debugger simply uses.

Debug scripts in Keil are a bit convoluted, given the complexity of the interfaces and bring-up expectations. I'd probably go with the loader method, or partition the code, so I could break-point in Internal FLASH at a point everything was up, and step in from there.

CMSIS typically expects SystemInit() to do ALL this prior to the C runtime initializing, and jumping to main().

CubeMX/HAL seems to be more backassward, and does this type of initialization early in main(), which is too late. Thus having a staged load, where you have a simple app in FLASH, and then transfer control to an app in QSPI, or unpacked / loaded into SDRAM.

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

Hello @DPila.1​,

For the  External QSPI Flash, I advise you to check the MOOC External QSPI loader how to.

For the SDRAM execution, the memory-mapped mode allows all AHB masters to access the Quad-SPI memory as an internal memory and to execute the code from the Quad-SPI memory. You can refer to the AN4760.

Best regards,

Chahinez.

Thank you for the response.

Yes, I just found this method online on youtube, now I am going to implement the same. Hope to get it working quickly. Thanks though.

Can you please help me why my Memory Mapped Configuration does not start Memory Mapped Mode for QSPI Flash (W25N512GV). Please see my code snippet below:

HAL_StatusTypeDef OSPI_EnableMemoryMappedMode(OSPI_HandleTypeDef *ospiHandle)
{
	OSPI_RegularCmdTypeDef sCommand;
	OSPI_MemoryMappedTypeDef sMemMappedCfg;
 
	memset(&sCommand, 0, sizeof(sCommand));
 
	/* Command Configuration -> Memory Mapped Mode - Read Set ------------------ */
	sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
	sCommand.OperationType = HAL_OSPI_OPTYPE_WRITE_CFG;
 
	// Setting Instruction Parameters
	sCommand.Instruction = FLASH_QUAD_LOAD_PROG_DATA_RANDOM;
	sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
	sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
	sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
 
	// Setting Address Parameters
	sCommand.Address = 0;
	sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
	sCommand.AddressSize = HAL_OSPI_ADDRESS_16_BITS;
	sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
 
	// Setting Alternate Byte Parameters
	sCommand.AlternateBytes = 0;
	sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
	sCommand.AlternateBytesSize = HAL_OSPI_ALTERNATE_BYTES_8_BITS;
	sCommand.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE;
 
	// Setting related to Data
	sCommand.NbData = 0;
	sCommand.DummyCycles = 0;
	sCommand.DataMode = HAL_OSPI_DATA_4_LINES;
	sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
	sCommand.DQSMode = HAL_OSPI_DQS_ENABLE;
	sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
 
	if (HAL_OSPI_Command(ospiHandle, &sCommand, OSPI_MIN_TIMEOUT) != HAL_OK)
	{
		return HAL_ERROR;
	}
 
	/* Command Configuration -> Memory Mapped Mode - Read Set ------------------ */
	sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
	sCommand.OperationType = HAL_OSPI_OPTYPE_READ_CFG;
 
	// Setting Instruction Parameters
	sCommand.Instruction = FLASH_READ_FAST_QUAD_IO;
	sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
	sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
	sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
 
	// Setting Address Parameters
	sCommand.Address = 0;
	sCommand.AddressMode = HAL_OSPI_ADDRESS_4_LINES;
	sCommand.AddressSize = HAL_OSPI_ADDRESS_16_BITS;
	sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
 
	// Setting Alternate Byte Parameters
	sCommand.AlternateBytes = 0;
	sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
	sCommand.AlternateBytesSize = HAL_OSPI_ALTERNATE_BYTES_8_BITS;
	sCommand.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE;
 
	// Setting related to Data
	sCommand.NbData = 0;
	sCommand.DummyCycles = FLASH_CONT_FAST_IO_QUAD_DUMMY_CYCLES;
	sCommand.DataMode = HAL_OSPI_DATA_4_LINES;
	sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
	sCommand.DQSMode = HAL_OSPI_DQS_ENABLE;
	sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
 
	if (HAL_OSPI_Command(ospiHandle, &sCommand, OSPI_MIN_TIMEOUT) != HAL_OK)
	{
		return HAL_ERROR;
	}
 
	memset(&sMemMappedCfg, 0, sizeof(sMemMappedCfg));
 
	sMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE;
 
	if (HAL_OSPI_MemoryMapped(ospiHandle, &sMemMappedCfg) != HAL_OK)
	{
		return HAL_ERROR;
	}
 
	return HAL_OK;
}