2024-05-20 02:31 PM
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?
2024-05-20 02:58 PM
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);
}
2024-06-25 12:08 AM
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..
2024-06-25 12:58 AM
Should be some example code in the BSP you can lift.
2024-06-25 02:43 AM
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.
2024-06-25 02:58 AM
Today's question is from tech_enthusiast, the OP was last month.
2024-06-25 03:13 AM
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.
2024-06-25 05:15 AM
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..
2024-06-25 05:46 AM
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.