2025-07-14 7:52 AM
Hello,
I am using a STM32H563ZI with an external PSRAM QSPI device, the APS6404L. I am using Quad-SPI through the OCTOSPI interface and have been successfully able to get into memory mapped mode. However, every time I go to read, I read out only 0 data. Has anyone ran into this same issue? I have pasted my code for transitioning the device to memory mapped mode and a subsequent test write/read. Thanks!
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_ICACHE_Init();
MX_OCTOSPI1_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(100);
uint8_t reset_enable[1] = {0x66};
uint8_t rst[1] = {};
uint8_t buff[3];
uint8_t buffer[128], dato;
APS6404_RESET_ENABLE(&hospi1);
PSRAM_ReadID(&hospi1);
APS6404_ENTER_QUAD_MODE(&hospi1);
uint8_t myData[] = {0xD, 0xE, 0xA, 0xD};
APS6404L_QuadWrite(&hospi1, OCTOSPI1_BASE, myData, sizeof(myData));
uint8_t rxData[32];
APS6404L_QuadRead(&hospi1, OCTOSPI1_BASE, rxData, sizeof(rxData));
/* MEM MAPPED MODE */
XSPI_RegularCmdTypeDef sCommand;
XSPI_MemoryMappedTypeDef sMemMappedCfg;
sCommand.OperationType = HAL_XSPI_OPTYPE_WRITE_CFG;
sCommand.Instruction = 0x38;
sCommand.InstructionMode = HAL_XSPI_INSTRUCTION_4_LINES;
sCommand.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS;
sCommand.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE;
sCommand.Address = 0x00000000;
sCommand.AddressMode = HAL_XSPI_ADDRESS_4_LINES;
sCommand.AddressWidth = HAL_XSPI_ADDRESS_24_BITS;
sCommand.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_DISABLE;
sCommand.AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE;
sCommand.DataMode = HAL_XSPI_DATA_4_LINES;
sCommand.DataDTRMode = HAL_XSPI_DATA_DTR_DISABLE;
sCommand.DummyCycles = 0; // for reads only
sCommand.DQSMode = HAL_XSPI_DQS_ENABLE;
sCommand.SIOOMode = HAL_XSPI_SIOO_INST_EVERY_CMD;
sCommand.OperationType = HAL_XSPI_OPTYPE_WRITE_CFG;
sCommand.Instruction = 0x38;
sCommand.DummyCycles = 6;
if (HAL_XSPI_Command(&hospi1, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
sCommand.OperationType = HAL_XSPI_OPTYPE_READ_CFG;
sCommand.Instruction = 0xEB;
sCommand.DummyCycles = 0;
sCommand.DQSMode = HAL_XSPI_DQS_DISABLE;
if (HAL_XSPI_Command(&hospi1, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
/* Enable Memory Mapped Mode */
sMemMappedCfg.TimeOutActivation = HAL_XSPI_TIMEOUT_COUNTER_DISABLE;
//sMemMappedCfg.TimeoutPeriodClock = 0x34;
if (HAL_XSPI_MemoryMapped(&hospi1, &sMemMappedCfg))
{
Error_Handler();
}
/* Insert delay 100 ms */
HAL_Delay(100);
volatile __IO uint8_t *mem_addr_byte;
// Writing Sequence (8-bit, unaligned pattern)
mem_addr_byte = (uint8_t *)(OCTOSPI1_BASE);
mem_addr_byte[0] = 0xDE;
if (mem_addr_byte[0] != 0xDE)
{
Error_Handler();
}
2025-07-15 2:46 AM
Hello @theAE
Please refer to the example XSPI_PSRAM_MemoryMapped.
2025-07-16 9:17 AM
Hello,
Thank you for posting this link. I have seen this and my current code matches this implementation nearly besides of enabling DQS during reads. I still am unable to see any non zero data being read from the APS6404L still even with matching every setting from the example (for quad spi, 24 bits of address).
2025-07-16 11:01 AM
This seems strange to me:
When switching to memory maped mode You have to:
1. configure the READ function (0xEB is read, but you are using 0x38!), according to the datasheet this need 6 dummy cycles.
Then configure the WRITE function (0x38), according to the datasheet this has 0 dummy cycles.
It seems You have inverted the two commands.
Why did You enable DQS, the chip has no DQS pin.
You have not posted Your MX_OCTOSPI1_Init() function, so I can not comment on this.
This is what i'm using on a STM32U575:
int32_t APSBusSwitchMemoryMode( OSPI_HandleTypeDef *hospi )
{
OSPI_MemoryMappedTypeDef sMemMappedCfg = {0};
OSPI_RegularCmdTypeDef sCommand;
APSSetQuadMode(hospi);
/* Memory-mapped mode configuration ------------------------------- */
sCommand.OperationType = HAL_OSPI_OPTYPE_READ_CFG;
sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
sCommand.Instruction = APS_CMD_FAST_READ_QIO; ;
sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_4_LINES;
sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
sCommand.Address = 0;
sCommand.AddressMode = HAL_OSPI_ADDRESS_4_LINES;
sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
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;
sCommand.DataMode = HAL_OSPI_DATA_4_LINES;
sCommand.NbData = 1;
sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
sCommand.DummyCycles = 6;
sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;
sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
if (HAL_OSPI_Command(hospi, &sCommand, 5) != HAL_OK)
{
return(HAL_ERROR);
}
sCommand.OperationType = HAL_OSPI_OPTYPE_WRITE_CFG;
sCommand.Instruction = APS_CMD_WRITE_QIO;
sCommand.DummyCycles = 0;
sCommand.DQSMode = HAL_OSPI_DQS_ENABLE;
if (HAL_OSPI_Command(hospi, &sCommand, 5) != HAL_OK)
{
return(HAL_ERROR);
}
sMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE;
if (HAL_OSPI_MemoryMapped(hospi, &sMemMappedCfg) != HAL_OK)
{
return(HAL_ERROR);
}
return(HAL_OK);
}
2025-07-16 11:21 AM
Thank you for your input @MHoll.2
I enabled DQS for writes because I read in the errata on page 18 of the STM32H5 errata sheet: "Memory-mapped write error response when DQS output is disabled"
I revised the code to match yours but have the same result. So perhaps there is something else wrong with my config. I pasted my revised code and associated MX_OCTOSPI1_Init() function.
/* MEM MAPPED MODE */
XSPI_RegularCmdTypeDef sCommand;
XSPI_MemoryMappedTypeDef sMemMappedCfg;
sCommand.OperationType = HAL_XSPI_OPTYPE_READ_CFG;
sCommand.Instruction = 0xEB;
sCommand.InstructionMode = HAL_XSPI_INSTRUCTION_4_LINES;
sCommand.InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS;
sCommand.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE;
sCommand.Address = 0x00000000;
sCommand.AddressMode = HAL_XSPI_ADDRESS_4_LINES;
sCommand.AddressWidth = HAL_XSPI_ADDRESS_24_BITS;
sCommand.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_ENABLE; // changed
sCommand.AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE;
sCommand.AlternateBytes = 0;
sCommand.DataMode = HAL_XSPI_DATA_4_LINES;
sCommand.DataDTRMode = HAL_XSPI_DATA_DTR_ENABLE; // changed
sCommand.DummyCycles = 6; // for reads only
sCommand.DQSMode = HAL_XSPI_DQS_DISABLE;
sCommand.SIOOMode = HAL_XSPI_SIOO_INST_EVERY_CMD;
if (HAL_XSPI_Command(&hospi1, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
sCommand.OperationType = HAL_XSPI_OPTYPE_WRITE_CFG;
sCommand.Instruction = 0x38;
sCommand.DummyCycles = 0;
sCommand.DQSMode = HAL_XSPI_DQS_ENABLE;
if (HAL_XSPI_Command(&hospi1, &sCommand, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
/* Enable Memory Mapped Mode */
sMemMappedCfg.TimeOutActivation = HAL_XSPI_TIMEOUT_COUNTER_DISABLE;
sMemMappedCfg.TimeoutPeriodClock = 0x34;
if (HAL_XSPI_MemoryMapped(&hospi1, &sMemMappedCfg))
{
Error_Handler();
}
/* Insert delay 100 ms */
HAL_Delay(100);
volatile __IO uint8_t *mem_addr_byte;
// Writing Sequence (8-bit, unaligned pattern)
mem_addr_byte = (uint8_t *)(OCTOSPI1_BASE);
HAL_GPIO_WritePin(GPIOG, GPIO_PIN_12, GPIO_PIN_SET);
mem_addr_byte[0] = 0xDE;
if (mem_addr_byte[0] != 0xDE)
{
Error_Handler();
}
static void MX_OCTOSPI1_Init(void)
{
/* USER CODE BEGIN OCTOSPI1_Init 0 */
/* USER CODE END OCTOSPI1_Init 0 */
/* USER CODE BEGIN OCTOSPI1_Init 1 */
/* USER CODE END OCTOSPI1_Init 1 */
/* OCTOSPI1 parameter configuration*/
hospi1.Instance = OCTOSPI1;
hospi1.Init.FifoThresholdByte = 1;
hospi1.Init.MemoryMode = HAL_XSPI_SINGLE_MEM;
hospi1.Init.MemoryType = HAL_XSPI_MEMTYPE_APMEM;
hospi1.Init.MemorySize = HAL_XSPI_SIZE_64MB;
hospi1.Init.ChipSelectHighTimeCycle = 1;
hospi1.Init.FreeRunningClock = HAL_XSPI_FREERUNCLK_DISABLE;
hospi1.Init.ClockMode = HAL_XSPI_CLOCK_MODE_0;
hospi1.Init.WrapSize = HAL_XSPI_WRAP_32_BYTES;
hospi1.Init.ClockPrescaler = 3;
hospi1.Init.SampleShifting = HAL_XSPI_SAMPLE_SHIFT_NONE;
hospi1.Init.DelayHoldQuarterCycle = HAL_XSPI_DHQC_DISABLE;
hospi1.Init.ChipSelectBoundary = HAL_XSPI_BONDARYOF_NONE;
hospi1.Init.DelayBlockBypass = HAL_XSPI_DELAY_BLOCK_BYPASS;
hospi1.Init.Refresh = 0;
if (HAL_XSPI_Init(&hospi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN OCTOSPI1_Init 2 */
/* USER CODE END OCTOSPI1_Init 2 */
}
2025-07-16 11:43 AM
The only difference I have in the Init (on a different CORE, so this may be irelevant):
ChipSelectHighTme = 2
DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE
Refresh = 240
2025-07-16 12:21 PM
Thank you for taking a look @MHoll.2 - I appreciate it.