Skip to main content
Visitor II
May 20, 2024
Question

OSPI in QSPI mode, issue with sending address

  • May 20, 2024
  • 3 replies
  • 3124 views

I'm importing some QSPI code we've been using a few years from an SMT32F7xx project to a new project using an STM32L4xx. Both projects use the same target device. I'm having an issue where the majority of messages don't seem to be sent. After debugging with a logic analyzer the behavior I'm seeing is that if I send a message where 

 

	sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE;

then it sends correctly. For any other value of AddressMode, none of the signals change at all when the command is executed. 

For example the following message sends correctly:

 sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
 	sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
	sCommand.DummyCycles = DUMMY_CLOCK_CYCLES_READ;//8;
	sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;
	sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
	sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
	sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
	sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
	sCommand.Instruction = 0x35;
	sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE;
	sCommand.DataMode = HAL_OSPI_DATA_NONE;
	sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;

	if (HAL_OSPI_Command(OSPIHandle, &sCommand, HAL_OSPI_TIMEOUT) != HAL_OK)
	{
		DEBUG("OSPI QuadModeCfg FAIL\r\n");
		if(0==InErrorHandler) {
			OSPI_Error_Handler();
		}
	}

The following message does not send anything at all, unless I change AddressMode to none.

OSPI_RegularCmdTypeDef sCommand;
uint8_t cr1v = 0;

	sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;;
 	sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
 	sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
	sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
	sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
 	sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
	sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
 	sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
	sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
	sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;
 	sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;

 	sCommand.Instruction = READ_ANY_REG_CMD;//0x65
 	sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
	//sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE;
 	sCommand.DataMode = HAL_OSPI_DATA_1_LINE;
 	sCommand.DummyCycles = DUMMY_CLOCK_CYCLES_READ;//8
 	sCommand.Address = 2;
 	sCommand.NbData = 1;

 if (HAL_OSPI_Command(OSPIHandle, &sCommand, HAL_OSPI_TIMEOUT) != HAL_OK)
 {
		DEBUG("OSPI QuadModeCfg FAIL\r\n");
 }

 if (HAL_OSPI_Receive(OSPIHandle, &cr1v, HAL_OSPI_TIMEOUT) != HAL_OK)
 {
		DEBUG("OSPI QuadModeCfg Receive FAIL\r\n");
 }

The HAL_OSPI_Command function returns HAL_OK even though it does not send the command, and then HAL_OSPI_Receive fails with a timeout.
The octospi.c initialization is below. I'm not completely sure what all the values do but I tried to match it to the original project since that one works. 

/* OCTOSPI1 init function */
void MX_OCTOSPI1_Init(void)
{

 /* USER CODE BEGIN OCTOSPI1_Init 0 */

 /* USER CODE END OCTOSPI1_Init 0 */

 OSPIM_CfgTypeDef OSPIM_Cfg_Struct = {0};

 /* USER CODE BEGIN OCTOSPI1_Init 1 */

 /* USER CODE END OCTOSPI1_Init 1 */
 hospi1.Instance = OCTOSPI1;
 hospi1.Init.FifoThreshold = 1;
 hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
 hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_MICRON;
 hospi1.Init.DeviceSize = 1;
 hospi1.Init.ChipSelectHighTime = 1;
 hospi1.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
 hospi1.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
 hospi1.Init.ClockPrescaler = 255;
 hospi1.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
 hospi1.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_DISABLE;
 hospi1.Init.ChipSelectBoundary = 0;
 hospi1.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED;
 if (HAL_OSPI_Init(&hospi1) != HAL_OK)
 {
 Error_Handler();
 }
 OSPIM_Cfg_Struct.ClkPort = 1;
 OSPIM_Cfg_Struct.NCSPort = 1;
 OSPIM_Cfg_Struct.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
 if (HAL_OSPIM_Config(&hospi1, &OSPIM_Cfg_Struct, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN OCTOSPI1_Init 2 */

 /* USER CODE END OCTOSPI1_Init 2 */

}

void HAL_OSPI_MspInit(OSPI_HandleTypeDef* ospiHandle)
{

 GPIO_InitTypeDef GPIO_InitStruct = {0};
 RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
 if(ospiHandle->Instance==OCTOSPI1)
 {
 /* USER CODE BEGIN OCTOSPI1_MspInit 0 */

 /* USER CODE END OCTOSPI1_MspInit 0 */

 /** Initializes the peripherals clock
 */
 PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_OSPI;
 PeriphClkInit.OspiClockSelection = RCC_OSPICLKSOURCE_MSI;
 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
 {
 Error_Handler();
 }

 /* OCTOSPI1 clock enable */
 __HAL_RCC_OSPIM_CLK_ENABLE();
 __HAL_RCC_OSPI1_CLK_ENABLE();

 __HAL_RCC_GPIOE_CLK_ENABLE();
 __HAL_RCC_GPIOB_CLK_ENABLE();
 /**OCTOSPI1 GPIO Configuration
 PE13 ------> OCTOSPIM_P1_IO1
 PE15 ------> OCTOSPIM_P1_IO3
 PB11 ------> OCTOSPIM_P1_NCS
 PB10 ------> OCTOSPIM_P1_CLK
 PE12 ------> OCTOSPIM_P1_IO0
 PE14 ------> OCTOSPIM_P1_IO2
 */
 GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_15|GPIO_PIN_12|GPIO_PIN_14;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF10_OCTOSPIM_P1;
 HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);

 GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_10;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_NOPULL;
 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF10_OCTOSPIM_P1;
 HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

 /* OCTOSPI1 DMA Init */
 /* OCTOSPI1 Init */
 hdma_octospi1.Instance = DMA1_Channel1;
 hdma_octospi1.Init.Request = DMA_REQUEST_OCTOSPI1;
 hdma_octospi1.Init.Direction = DMA_PERIPH_TO_MEMORY;
 hdma_octospi1.Init.PeriphInc = DMA_PINC_DISABLE;
 hdma_octospi1.Init.MemInc = DMA_MINC_ENABLE;
 hdma_octospi1.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
 hdma_octospi1.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
 hdma_octospi1.Init.Mode = DMA_NORMAL;
 hdma_octospi1.Init.Priority = DMA_PRIORITY_LOW;
 if (HAL_DMA_Init(&hdma_octospi1) != HAL_OK)
 {
 Error_Handler();
 }

 __HAL_LINKDMA(ospiHandle,hdma,hdma_octospi1);

 /* OCTOSPI1 interrupt Init */
 HAL_NVIC_SetPriority(OCTOSPI1_IRQn, 5, 0);
 HAL_NVIC_EnableIRQ(OCTOSPI1_IRQn);
 /* USER CODE BEGIN OCTOSPI1_MspInit 1 */
 /* USER CODE END OCTOSPI1_MspInit 1 */
 }
}

 

Is there any way to figure out what the issue is, or things I should try?

    This topic has been closed for replies.

    3 replies

    Graduate II
    May 20, 2024

    OSPI_RegularCmdTypeDef sCommand = {0}; // Ensure the stack buffer is cleared, and not random junk

    Nothing is immediately jumping out from the code. Not had much trouble here using QSPI devices on an OSPI peripheral.

    Prescaler is ridiculously high

     

     /* OSPI initialization */
     hospi->Init.FifoThreshold = 1; // 1..32 Interrupt threshold
     hospi->Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
     hospi->Init.MemoryType = HAL_OSPI_MEMTYPE_MICRON;
     hospi->Init.DeviceSize = 27; //OSPI_FLASH_SIZE_SHIFT;
     hospi->Init.ChipSelectHighTime = 4; // Min 30ns for nonRead
     hospi->Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
     hospi->Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
     hospi->Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;
    
    #ifdef OSPI_CLK_DIV
     hospi->Init.ClockPrescaler = OSPI_CLK_DIV;
    #else
     hospi->Init.ClockPrescaler = 1; /* QSPI freq = 64 MHz/(1+1) = 32 Mhz */
    #endif
    
     hospi->Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_HALFCYCLE;
    
     hospi->Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_DISABLE;
     hospi->Init.ChipSelectBoundary = 0;
    
     if (HAL_OSPI_Init(hospi) != HAL_OK)
     {
     return(OSPI_ERROR);
     }
    ...
     OSPIM_CfgTypeDef OSPIM_Cfg_Struct = {0};
    
     /*##-4- Configure the OctoSPI IO Manager ####################################*/
     // P1=1, P2=2?
     OSPIM_Cfg_Struct.NCSPort = 1;
     OSPIM_Cfg_Struct.ClkPort = 1; // 1 .. 8
    #ifdef OSPI_DQS_PIN
     OSPIM_Cfg_Struct.DQSPort = 1;
    #else
     OSPIM_Cfg_Struct.DQSPort = 0;
    #endif // OSPI_DQS_PIN
    
     OSPIM_Cfg_Struct.IOHighPort = HAL_OSPIM_IOPORT_NONE; // 1_HIGH; // Not needed?
     OSPIM_Cfg_Struct.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
    
     if (HAL_OSPIM_Config(hospi, &OSPIM_Cfg_Struct, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
     {
     }
    ...
    
    static uint8_t BSP_OSPI_Read(OSPI_HandleTypeDef *hospi, uint8_t* pData, uint32_t ReadAddr, uint32_t Size)
    {
     OSPI_RegularCmdTypeDef sCommand = {0};
    
     sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
     sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
    
     /* Initialize the read command */
     sCommand.Instruction = 0x3B; // DUAL (MOST COMPATIBLE)
     sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
     sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
     sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
     sCommand.DataMode = HAL_OSPI_DATA_2_LINES;
     sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
     sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
     sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
     sCommand.DummyCycles = 8;
    
    #ifdef USE_ADR32
     sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS;
    #else
     sCommand.AddressSize = HAL_OSPI_ADDRESS_24_BITS;
    #endif // USE_ADR32
    
     sCommand.Address = ReadAddr & 0x0FFFFFFF; // Ensure Masking
     sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
     sCommand.NbData = Size;
     sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
    
     /* Configure the command */
     if (HAL_OSPI_Command(hospi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
     {
     return(OSPI_ERROR);
     }
    
     /* Transmission of the data */
     if (HAL_OSPI_Receive(hospi, pData, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
     {
     return(OSPI_ERROR);
     }
    
     return(OSPI_OK);
    }
    Explorer II
    June 25, 2024

    Hello,

    Anyone please provide example code for Initializing, reading, writing ospi flash memory(macronix) in indirect mode

    because i have to update touch gfx project through custom bootloader which is stored in external flash.

     

    please replay asap..

    Graduate II
    June 25, 2024

    Should be some example code in the BSP you can lift.

    Technical Moderator
    June 25, 2024

    Hello @TimJones and welcome to the community :),

     

    Could you please precise which external memory are you using? Please share the memory datasheet?

    Which STM32L4 are you using? 

    Could you please take a look at AN5050 section 6.2 OCTOSPI configuration with STM32CubeMX and get inspired from III. Quad-SPI PSRAM in Regular-command protocol example section to configure the Quad-SPI memory.

    Also, it is recommended to check the STM32 erratsheet section OCTOSPI, when you configure the OCTOSPI interface.

    I hope this help you.

    Thank you.

    Kaouthar

     

    Graduate II
    June 25, 2024

    Today's question is from tech_enthusiast, the OP was last month.