cancel
Showing results for 
Search instead for 
Did you mean: 

Issue with OCTOSPI1 Port1 IO[7:4] on STM32H735IGT6 in Quad-SPI Mode

feten_kortoba
Associate

Hi everyone,

I'm currently working on a project where I need to use Port1 IO[7:4] of OCTOSPI1 on the STM32H735IGT6 MCU to interface with a MT25QL512ABB NOR Flash in Quad-SPI mode with dual-quad mode disabled.

I configured the OCTOSPI1 peripheral in CubeMX as follows:

  • Mode: Quad SPI
  • Clock: Port1 CLK
  • Chip Select: Port1 NCS
  • Data [3:0]: Port1 IO[7:4]

After generating the code and implementing test logic for writing, erasing, and reading from the NOR Flash, I observed the following:

  1. Clock and Chip Select signals are fine (verified using an oscilloscope).
  2. IO[7:4] signals are null (unchangeable), meaning no data activity is visible on the lines.

My test code follows the standard configuration steps to enable writes, send commands, and perform operations like erasing and programming. I even tried reinitializing the peripheral in a loop for multiple operations, but the IOs remain inactive.

I'm attaching a screenshot of my CubeMX configuration and some excerpts from my code:

 

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MPU Configuration--------------------------------------------------------*/
  MPU_Config();

  /* Enable the CPU Cache */
  CPU_CACHE_Enable();
  /* 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_OCTOSPI1_Init();
  /* USER CODE BEGIN 2 */
  //Test_NOR_Flash();
  /* Configure the memory in quad mode ------------------------------------- */


  /* Configure the memory in octal mode ------------------------------------- */
  QSPI_OctalDtrModeCfg(&OSPIHandle);

  sCommand.OperationType      = HAL_OSPI_OPTYPE_COMMON_CFG;
  sCommand.FlashId            = HAL_OSPI_FLASH_ID_2;
  sCommand.InstructionMode    = HAL_OSPI_INSTRUCTION_1_LINE;
  sCommand.InstructionSize    = HAL_OSPI_INSTRUCTION_32_BITS;
  sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
  sCommand.AddressSize        = HAL_OSPI_ADDRESS_32_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;

  /* Infinite loop */
  while (1)
  {
    switch(step)
    {
    case 0:
      CmdCplt = 0;

      /* Enable write operations ------------------------------------------- */
      OSPI_WriteEnable(&OSPIHandle);

      /* Erasing Sequence ----------------------------------------------- */
      sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
      sCommand.Instruction   = SECTOR_ERASE_CMD;
      sCommand.AddressMode   = HAL_OSPI_ADDRESS_1_LINE;
      sCommand.DataMode      = HAL_OSPI_DATA_NONE;
      sCommand.Address       = address;
      sCommand.DummyCycles   = 0;
      sCommand.DQSMode       = HAL_OSPI_DQS_DISABLE;

      if (HAL_OSPI_Command_IT(&OSPIHandle, &sCommand) != HAL_OK)
      {
        Error_Handler();
      }

      step++;

      break;

    case 1:

      if(CmdCplt != 0)
      {
        CmdCplt = 0;
        StatusMatch = 0;

        /* Configure automatic polling mode to wait for end of erase ------- */
        OSPI_AutoPollingMemReady(&OSPIHandle);

        step++;
      }
      break;

    case 2:

      if(StatusMatch != 0)
      {
        StatusMatch = 0;
        TxCplt = 0;

        /* Enable write operations ------------------------------------------- */
        OSPI_WriteEnable(&OSPIHandle);

        /* Writing Sequence ------------------------------------------------ */
        sCommand.Instruction = 0x02;//PAGE_PROG_CMD;
        sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
        sCommand.DataMode    = HAL_OSPI_DATA_4_LINES;
        sCommand.NbData      = BUFFERSIZE;
        sCommand.Address     = address;

        if (HAL_OSPI_Command(&OSPIHandle, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
        {
          Error_Handler();
        }

        if (HAL_OSPI_Transmit_IT(&OSPIHandle, aTxBuffer) != HAL_OK)
        {
          Error_Handler();
        }


        step++;
      }
      break;

    case 3:

      if(TxCplt != 0)
      {
        TxCplt = 0;
        StatusMatch = 0;

        /* Configure automatic polling mode to wait for end of program ----- */
        OSPI_AutoPollingMemReady(&OSPIHandle);

        /* Memory-mapped mode configuration ------------------------------- */
        sCommand.OperationType = HAL_OSPI_OPTYPE_WRITE_CFG;
        sCommand.DataMode      = HAL_OSPI_DATA_1_LINE;
        sCommand.NbData        = 1;
        sCommand.DQSMode       = HAL_OSPI_DQS_DISABLE;
        sCommand.DummyCycles   = 0;

        if (HAL_OSPI_Command(&OSPIHandle, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
        {
          Error_Handler();
        }

        sCommand.OperationType = HAL_OSPI_OPTYPE_READ_CFG;
        sCommand.Instruction   = 0x0B;//IO_DTR_READ_CMD;
        sCommand.DummyCycles   = 8 ;
        sCommand.DQSMode       = HAL_OSPI_DQS_DISABLE;

        if (HAL_OSPI_Command(&OSPIHandle, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
        {
          Error_Handler();
        }

        sMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE;


        if (HAL_OSPI_MemoryMapped(&OSPIHandle, &sMemMappedCfg) != HAL_OK)
        {
          Error_Handler();
        }

        /* Reading Sequence ----------------------------------------------- */
        mem_addr = (__IO uint8_t *)(OCTOSPI1_BASE + address);
        for (index = 0; index < BUFFERSIZE ; index++)
        {
          if (*mem_addr != aTxBuffer[index])
          {
          }
          mem_addr++;
        }


        address += OSPI_PAGE_SIZE;
        if(address >= OSPI_END_ADDR)
        {
          address = 0;
        }

        /* Re-Initialize OctoSPI*/
        HAL_OSPI_DeInit(&OSPIHandle);
        HAL_OSPI_Init(&OSPIHandle);

        step = 0;
      }

      break;

    default :
      Error_Handler();
    }
  }
}

 

 

Questions:

  1. Is it possible to use Port1 IO[7:4] for Quad-SPI mode with the MT25QL512ABB on this MCU?
  2. Are there additional settings or configurations (either in CubeMX or HAL library) that I might have missed?

Any guidance or suggestions would be greatly appreciated!

1 REPLY 1
KDJEM.1
ST Employee

Hello @feten_kortoba and welcome to the community;

 

The IO[7:4] can be mapped to Data [3..0]. So, IO[7:4] can be used as possible remap for quad-SPI mode.

Could you check OCTOSPI GPIOs and clocks configuration?

The configured GPIOs must match the memory connection. If the configuration is not correct, the user must manually configure all the GPIOs, one by one, by clicking directly on each pin. 

Also make sure that the output speed is set to "very high" for all the GPIOs.

I recommend you to refer to Table8. STM32CubeMX - Configuration of OCTOSPI parameters in AN5050 and check your OCTOSPI configuration.

Try to disable the cache.

Maybe Overall FAQs for QUADSPI/OCTOSPI/HSPI/XSPI can help you.

 

Thanks and best regards,

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.