cancel
Showing results for 
Search instead for 
Did you mean: 

OSPI in QSPI mode, issue with sending address

TimJones
Associate

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?

8 REPLIES 8

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);
}
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Tech_enthusiast_Manoj
Associate II

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

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

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

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

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

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

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

Hello @Tech_enthusiast_Manoj ,

 

As mentioned by @Tesla DeLorean the BSP example can help you.

Also, in order to configure the OCTOSPI in Indirect/Memory-mapped mode and to configure the external Octo-SPI Macronix Flash memory allowing communication, I recommend you to take a look II. Octo-SPI FLASH in Regular-command protocol example  in AN5050.

May this MOOC can help you STM32 Graphics: How to set up a different OSPI flash memory in a TouchGFX template, Part 1 - YouTube

 

Thank you.

Kaouthar

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Thanks @KDJEM.1  ospi flash write is working properly.

But I need one more help ,

I have to flash .hex in mcu and external flash as well , please suggest me how to decode .hex for flashing,

is there any function or API to do this .

I had done flashing .bin by custom bootloader which is working fine,

But i need to flash .hex because TouchGFX creates target.hex which is combined hex file for internal and external flash.

PLEASE HELP..

The format is simple and well documented, one of your coders will have to code 

Perhaps use objcopy or objdump to get to a binary.

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