Skip to main content
Visitor II
July 14, 2025
Question

STM32H563ZI + APS6404L QSPI Memory Mapped Reads Failing

  • July 14, 2025
  • 2 replies
  • 469 views

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();
	}

 

    This topic has been closed for replies.

    2 replies

    Technical Moderator
    July 15, 2025

    Hello @theAE 

    Please refer to the example XSPI_PSRAM_MemoryMapped.

    theAEAuthor
    Visitor II
    July 16, 2025

    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). 

     

    Graduate II
    July 16, 2025

    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);
    }

     

    theAEAuthor
    Visitor II
    July 16, 2025

    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 */
    
    }

     

    Graduate II
    July 16, 2025

    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