cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H573 XSPI strange behavior

PThiering
Associate

Dear Forum Members,

I'm developing a hardware with a small LCD screen which is using a QSPI interface. I succeeded with an STM32H723 with its OCTOSPI interface through DMA, and I got good results, but I encountered memory mapping problems with the complicated split RAM structure of that MCU, so I switched to an STM32H573, which has all of its 640k RAM in one continous block.

Signals used for data transmission: D0~D3, NCS, SCK. For commands and data headers, the protocol uses D0 only in 1-bit SPI mode, than pixel data is being sent in 4-bit QSPI format for each line.

I'm struggling with the XSPI interface setting up correctly for the new microcontroller, it does not send out any data (viewed on a scope), even the NCS signal is not pulled down on HAL_XSPI_Transmit or HAL_XSPI_Command calls. I think I missed some registers which are not generated by the STM32Cube IDE. I've found AN5050, which is mostly about how to attach an external memory chip through these interfaces.

I think I missed setting up or initializing some functions which were not set up completely by the CubeIDE.

 

Working init code I used for the previous MCU generated by STM32Cube IDE, and added some default headers for commands: 

 

 

 

static 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 */ /* OCTOSPI1 parameter configuration*/ hospi1.Instance = OCTOSPI1; hospi1.Init.FifoThreshold = 16; hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE; hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_MICRON; hospi1.Init.DeviceSize = 32; hospi1.Init.ChipSelectHighTime = 5; 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 = 4; 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.IOLowPort = HAL_OSPIM_IOPORT_1_LOW; if (HAL_OSPIM_Config(&hospi1, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN OCTOSPI1_Init 2 */ /* 0xde is the first byte every transmit */ OSPI_Cmdhandler.Instruction = LCD_INS_DATA; /* qspi 24bit address, lcd command is set in A15~A8 */ OSPI_Cmdhandler.Address = 0x000000; OSPI_Cmdhandler.DummyCycles = 0; OSPI_Cmdhandler.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE; // anything except pixel data is 1-bit OSPI_Cmdhandler.AddressMode = HAL_OSPI_ADDRESS_1_LINE; OSPI_Cmdhandler.AddressSize = HAL_OSPI_ADDRESS_24_BITS; OSPI_Cmdhandler.DataMode = HAL_OSPI_DATA_NONE; OSPI_Cmdhandler.NbData = 0; OSPI_Cmdhandler.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; OSPI_Cmdhandler.DQSMode = HAL_OSPI_DQS_DISABLE; // OSPI_Cmdhandler.AlternateByteMode = HAL_OSPI_ALTERNATE_BYTES_NONE; // OSPI_Cmdhandler.DdrMode = HAL_OSPI_DDR_MODE_DISABLE; // OSPI_Cmdhandler.DdrHoldHalfCycle = HAL_OSPI_DDR_HHC_ANALOG_DELAY; /* USER CODE END OCTOSPI1_Init 2 */ }
View more

 

 

LCD Transmit function: (works perfectly on the STM32H723)

 

 

void lcd_transmit(uint32_t cmd, uint32_t len, uint8_t *dat) { OSPI_Cmdhandler.Address = 0x00000000; if (len == 0) { /* write command, no parameter, one line in use */ OSPI_Cmdhandler.Instruction = LCD_INS_CMD; OSPI_Cmdhandler.Address |= cmd << 8; OSPI_Cmdhandler.DataMode = HAL_OSPI_DATA_NONE; OSPI_Cmdhandler.NbData = 0; /* interrupt mode */ HAL_OSPI_Command(&hospi1, &OSPI_Cmdhandler, HAL_OSPI_TIMEOUT_DEFAULT_VALUE); // HAL_OSPI_Command_IT(&hospi1, &OSPI_Cmdhandler); } else if (len <= INIT_DAT_LEN) { /* write command with parameter, only 1 line in use */ OSPI_Cmdhandler.Instruction = LCD_INS_CMD; OSPI_Cmdhandler.Address |= cmd << 8; OSPI_Cmdhandler.DataMode = HAL_OSPI_DATA_1_LINE; OSPI_Cmdhandler.NbData = len; /* interrupt mode */ // HAL_OSPI_Command_IT(&hospi1, &OSPI_Cmdhandler); // HAL_OSPI_Transmit_IT(&hospi1, dat); HAL_OSPI_Command(&hospi1, &OSPI_Cmdhandler, HAL_OSPI_TIMEOUT_DEFAULT_VALUE); HAL_OSPI_Transmit(&hospi1, dat, HAL_OSPI_TIMEOUT_DEFAULT_VALUE); } else { /* write display data by hbyte length, data must be sent over QSPI */ OSPI_Cmdhandler.Instruction = LCD_INS_DATA; OSPI_Cmdhandler.Address |= cmd << 8; OSPI_Cmdhandler.DataMode = HAL_OSPI_DATA_4_LINES; OSPI_Cmdhandler.NbData = len; /* mdma mode */ HAL_OSPI_Command(&hospi1, &OSPI_Cmdhandler, HAL_OSPI_TIMEOUT_DEFAULT_VALUE); HAL_OSPI_Transmit_DMA(&hospi1, dat); // // HAL_Delay(1); // HAL_OSPI_Transmit(&hospi1, dat,HAL_OSPI_TIMEOUT_DEFAULT_VALUE); } // HAL_OSPI_AutoPollingMemReady(&hospi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE); // HAL_Delay(1); }
View more

 

 

 

 

Code which is not working for STM32H573

 

 

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 = 16; hospi1.Init.MemoryMode = HAL_XSPI_SINGLE_MEM; hospi1.Init.MemoryType = HAL_XSPI_MEMTYPE_MICRON; hospi1.Init.MemorySize = HAL_XSPI_SIZE_16B; hospi1.Init.ChipSelectHighTimeCycle = 5; hospi1.Init.FreeRunningClock = HAL_XSPI_FREERUNCLK_DISABLE; hospi1.Init.ClockMode = HAL_XSPI_CLOCK_MODE_0; hospi1.Init.WrapSize = HAL_XSPI_WRAP_NOT_SUPPORTED; hospi1.Init.ClockPrescaler = 50; hospi1.Init.SampleShifting = HAL_XSPI_SAMPLE_SHIFT_NONE; hospi1.Init.DelayHoldQuarterCycle = HAL_XSPI_DHQC_DISABLE; hospi1.Init.ChipSelectBoundary = HAL_XSPI_BONDARYOF_16B; 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 */ }
View more

 

 

 

GPIO mappings in the HAL_MSP file:

 

 

void HAL_XSPI_MspInit(XSPI_HandleTypeDef* hxspi) { GPIO_InitTypeDef GPIO_InitStruct = {0}; RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0}; if(hxspi->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_HCLK; if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) { Error_Handler(); } /* Peripheral clock enable */ __HAL_RCC_OSPI1_CLK_ENABLE(); __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); /**OCTOSPI1 GPIO Configuration PA6 ------> OCTOSPI1_IO3 PA7 ------> OCTOSPI1_IO2 PB0 ------> OCTOSPI1_IO1 PB1 ------> OCTOSPI1_IO0 PB2 ------> OCTOSPI1_CLK PB10 ------> OCTOSPI1_NCS */ 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_AF6_OCTOSPI1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_7; 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_OCTOSPI1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; GPIO_InitStruct.Alternate = GPIO_AF6_OCTOSPI1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_2|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_OCTOSPI1; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); /* OCTOSPI1 DMA Init */ /* GPDMA1_REQUEST_OCTOSPI1 Init */ handle_GPDMA1_Channel0.Instance = GPDMA1_Channel0; handle_GPDMA1_Channel0.Init.Request = GPDMA1_REQUEST_OCTOSPI1; handle_GPDMA1_Channel0.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST; handle_GPDMA1_Channel0.Init.Direction = DMA_MEMORY_TO_PERIPH; handle_GPDMA1_Channel0.Init.SrcInc = DMA_SINC_FIXED; handle_GPDMA1_Channel0.Init.DestInc = DMA_DINC_FIXED; handle_GPDMA1_Channel0.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD; handle_GPDMA1_Channel0.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD; handle_GPDMA1_Channel0.Init.Priority = DMA_LOW_PRIORITY_HIGH_WEIGHT; handle_GPDMA1_Channel0.Init.SrcBurstLength = 1; handle_GPDMA1_Channel0.Init.DestBurstLength = 1; handle_GPDMA1_Channel0.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0; handle_GPDMA1_Channel0.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER; handle_GPDMA1_Channel0.Init.Mode = DMA_NORMAL; if (HAL_DMA_Init(&handle_GPDMA1_Channel0) != HAL_OK) { Error_Handler(); } __HAL_LINKDMA(hxspi, hdmatx, handle_GPDMA1_Channel0); if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel0, DMA_CHANNEL_NPRIV) != HAL_OK) { Error_Handler(); } /* OCTOSPI1 interrupt Init */ HAL_NVIC_SetPriority(OCTOSPI1_IRQn, 14, 0); HAL_NVIC_EnableIRQ(OCTOSPI1_IRQn); /* USER CODE BEGIN OCTOSPI1_MspInit 1 */ /* USER CODE END OCTOSPI1_MspInit 1 */ } }
View more

 

 

 

Then, in the main loop I tried to send out something:

(also tried with Transmit_IT or Transmit_DMA but the same result, software runs)

If I set free running clock ON, then the clock can be seen on the scope.

 

 

/* Initialize all configured peripherals */ MX_GPIO_Init(); MX_GPDMA1_Init(); MX_OCTOSPI1_Init(); MX_DCACHE1_Init(); MX_ICACHE_Init(); /* USER CODE BEGIN 2 */ XSPI_RegularCmdTypeDef sCommand1={0}; /*Initialize the write register command */ sCommand1.OperationType = HAL_XSPI_OPTYPE_COMMON_CFG; sCommand1.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; sCommand1.InstructionWidth = HAL_XSPI_INSTRUCTION_16_BITS; sCommand1.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE; sCommand1.Instruction = 0xEA; sCommand1.AddressMode = HAL_XSPI_ADDRESS_1_LINE; sCommand1.AddressWidth = HAL_XSPI_ADDRESS_24_BITS; sCommand1.AddressDTRMode = HAL_XSPI_ADDRESS_DTR_DISABLE; sCommand1.Address = 0xFF; sCommand1.AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE; sCommand1.DataMode = HAL_XSPI_DATA_4_LINES; sCommand1.DataDTRMode = HAL_XSPI_DATA_DTR_DISABLE; sCommand1.DataLength = 8; sCommand1.DummyCycles = 0; sCommand1.DQSMode = HAL_XSPI_DQS_DISABLE; sCommand1.IOSelect = HAL_XSPI_SELECT_IO_3_0; // sCommand1.SIOOMode = HAL_XSPI_SIOO_INST_ONLY_FIRST_CMD; /* Configure the command*/ HAL_XSPI_Command(&hospi1, &sCommand1, 5000); uint8_t tmp[16]= { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 }; HAL_XSPI_Transmit(&hospi1, &tmp[0], 100); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { HAL_XSPI_Command(&hospi1, &sCommand1, 1000); HAL_XSPI_Transmit(&hospi1, &tmp[0],1000); // HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_10); HAL_Delay(1); /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */
View more

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
PThiering
Associate

I think the problem was resolved. There's a "memory size" setting in CubeMX which had to be set to "512k / 4mbit" and then the thing begon sending data. Idk why... 

For further reference, there was the fix.

 

PThiering_0-1736427268631.png

 

View solution in original post

1 REPLY 1
PThiering
Associate

I think the problem was resolved. There's a "memory size" setting in CubeMX which had to be set to "512k / 4mbit" and then the thing begon sending data. Idk why... 

For further reference, there was the fix.

 

PThiering_0-1736427268631.png