cancel
Showing results for 
Search instead for 
Did you mean: 

Communicating with QSPI nor-flash via OctoSPI (OSPI) [STM32H730VBT6]

GCern.1
Associate II

Hello, I have a very basic setup of OSPI1 on STM32H730VBT and I am trying to read the 1st Status Register of the Winbond W25Q128JV.

Environment

  • STM32CubeMX: 6.5.0
  • STM32Cube_FW_H7_V1.10.0
  • STM32CubeIDE Version: 1.9.0 Build: 12015_20220302_0855 (UTC)

Hardware

A custom board with STM32H730VBT and Winbond W25Q128JV connected via OSPI1.

Code

Generated OSPI init code

void MX_OCTOSPI1_Init(void)
{
 
  /* USER CODE BEGIN OCTOSPI1_Init 0 */
 
  /* USER CODE END OCTOSPI1_Init 0 */
 
  OSPIM_CfgTypeDef sOspiManagerCfg = {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 = 24;
  hospi1.Init.ChipSelectHighTime = 1;
  hospi1.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
  hospi1.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
  hospi1.Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;
  hospi1.Init.ClockPrescaler = 1; /* HCLK3 is already 65MHz */
  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;
  hospi1.Init.MaxTran = 0;
  hospi1.Init.Refresh = 0;
  if (HAL_OSPI_Init(&hospi1) != HAL_OK)
  {
    Error_Handler();
  }
  sOspiManagerCfg.ClkPort = 1;
  sOspiManagerCfg.NCSPort = 1;
  sOspiManagerCfg.DQSPort = 0;
  sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
  sOspiManagerCfg.IOHighPort = HAL_OSPIM_IOPORT_NONE;
  sOspiManagerCfg.Req2AckTime = 1; /* required when full assert is enabled... */
  if (HAL_OSPIM_Config(&hospi1, &sOspiManagerCfg, 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 PeriphClkInitStruct = {0};
  if(ospiHandle->Instance==OCTOSPI1)
  {
  /* USER CODE BEGIN OCTOSPI1_MspInit 0 */
 
  /* USER CODE END OCTOSPI1_MspInit 0 */
 
  /** Initializes the peripherals clock
  */
    PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_OSPI;
    PeriphClkInitStruct.OspiClockSelection = RCC_OSPICLKSOURCE_D1HCLK;
    if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
    {
      Error_Handler();
    }
 
    /* OCTOSPI1 clock enable */
    __HAL_RCC_OCTOSPIM_CLK_ENABLE();
    __HAL_RCC_OSPI1_CLK_ENABLE();
 
    __HAL_RCC_GPIOE_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    __HAL_RCC_GPIOD_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    /**OCTOSPI1 GPIO Configuration
    PE2     ------> OCTOSPIM_P1_IO2
    PB2     ------> OCTOSPIM_P1_CLK
    PD11     ------> OCTOSPIM_P1_IO0
    PD13     ------> OCTOSPIM_P1_IO3
    PC10     ------> OCTOSPIM_P1_IO1
    PB6     ------> OCTOSPIM_P1_NCS
    */
    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_OCTOSPIM_P1;
    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
 
    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_OCTOSPIM_P1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
    GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_13;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_OCTOSPIM_P1;
    HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
 
    GPIO_InitStruct.Pin = 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_AF9_OCTOSPIM_P1;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    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);
 
  /* USER CODE BEGIN OCTOSPI1_MspInit 1 */
 
  /* USER CODE END OCTOSPI1_MspInit 1 */
  }
}

PS: `sOspiManagerCfg` init is slightly modified to not produce an error when full assert is enabled but `Req2AckTime` is not set by the STM32CubeMX.

Status Register 1 (SR1) read code

uint8_t reg = 0U;
OSPI_RegularCmdTypeDef cmd = {
		.Instruction = 0x05,
		.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE,
		.DataMode = HAL_OSPI_DATA_1_LINE,
		.AddressMode = HAL_OSPI_ADDRESS_NONE,
		.NbData = 1U,
		.DummyCycles = 0U
};
 
hal_ret = HAL_OSPI_Command(&hospi1, &cmd, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);
if (hal_ret != HAL_OK) {
	return hal_ret;
}
 
 
hal_ret = HAL_OSPI_Receive(&hospi1, &reg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);
if (hal_ret != HAL_OK) {
	return hal_ret;
}
 
return HAL_OK;

Current

  • Missing CLK on PB2
  • Not HAL errors
  • The SR1 read as `0x00`

Expected

  • PB2 CLK signal
  • Non zero SR1

Everything works perfectly when using QSPI on STM32H750 (same board, same clock configuration output [doesn't exceed < Max 133MHz for O/QSPI]). However, when Octo-SPI (OSPI) is used, then nothing is being read. It looks like the CLK signal is not present.

Any ideas what can be tried out?

This discussion is locked. Please start a new topic to ask your question.
1 ACCEPTED SOLUTION

Accepted Solutions
GCern.1
Associate II

@Andreas Bolsch​, @Community member​, thank you for the assistance. The issue turned out to be the clock.

View solution in original post

7 REPLIES 7

Do you have a UART available for debug on this board? Which ports/pins?

sOspiManagerCfg.IOHighPort = HAL_OSPIM_IOPORT_NONE; // ??

Try

sOspiManagerCfg.IOHighPort = HAL_OSPIM_IOPORT_1_HIGH;

hospi1.Init.ChipSelectHighTime = 2;

hospi1.Init.ClockPrescaler = 4; // Perhaps shoot for 50-100 MHz

Had Winbond/Macronix parts working on NUCLEO-H723ZG here

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

@Community member​ ,

sOspiManagerCfg.IOHighPort = HAL_OSPIM_IOPORT_1_HIGH;

why?

Mentioned Winbond NOR-Flash is a Quad Mode (max) flash and OSPI has to be used in Quad Mode (Data[3:0]) - therefore, STM32CubeMX won't even generate `IOHighPort` setting, as it is equal to `0` anyway.

The

HAL_OSPIM_IOPORT_NONE

was added to be explicit here.

hospi1.Init.ClockPrescaler = 4;

The HCLK3 used as OSPI clock source is already 65MHz which is already within propose frequency range.

hospi1.Init.ChipSelectHighTime = 2;

Shouldn't play a big role here. Tried, no difference.

GCern.1
Associate II

@Community member​,

U(S)ARTs are off (serial wire debug is enabled),

LDO (STM32H730VBT6 MCU).

STM32CubeMX

OSPI

0693W00000Nq72eQAB.jpgClock0693W00000Nq75OQAR.jpg 

I don't use CubeMX to program, like I said have QSPI devices working on NUCLEO-H723ZG, and also H7A3

Nevermind, probably high/low bank of pins thru the mux, just scanning code differences.

I can port the test code,need to know external clock source, LDO/SMPS, usable UART

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

Checking with read status register won't be indicative, as 0x00 is a perfectly legal (and expected) value. Try Read ID command 0x9F instead.

Furthermore, inspect all OctoSPI registers after each HAL call and compare their contents against RM, in particular OCTOSPI_SR might give a clue.

This should output via SWV, running at 130 MHz

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

@Andreas Bolsch​, @Community member​, thank you for the assistance. The issue turned out to be the clock.