2024-10-18 03:54 AM - last edited on 2024-10-21 07:28 AM by SofLit
Hello,
I am facing the below scenario in my development board. I am trying to do OTA update in my RIverDI 5 inch display module. I receive the firmware chunk from the ESP board which is connected through the external connectors of the riverDI module and through USART1. The USART1 receives the firmware elf chunks and I need to store them in the STM32. The size of my elf file is more than 3MB and I cant directly store the data in the internal flash memory. The only option that I have right now is the external memory, but I am unable to read/write from it.
When I looked through the internet, it was not suggested to write into the external memory since it is allocated for storing the TouchGfx Assets. But my only option is to store the elf file chunks in the external memory and use the same for the OTA update process.
This is what I tried to do in my appliation.
1. Initialized the OSPI in main
MX_OCTOSPI1_Init();
2. Made sure the Memory mapped more is enabled and the API response for OSPI_NOR_EnableMemoryMappedMode() is 0
3. Called memcpy() to write a simple string into the external memory location
memcpy( (uint8_t *)0x91000000, "hello", 5);
I receive a hardfault handler error when I call the memcpy(). Can you please let me know what am I doing wrong here?
Regards
RiverDI user
2024-10-22 07:43 AM - edited 2024-10-22 07:44 AM
Hello,
Its enabled already in code
Few more information on the application that I am working on.
I have used the OCTOSPI1 and initialized it and used the MX25LM51245G APIs to perform the memory write.
Here is my code:
/* OCTOSPI1 init function */
void MX_OCTOSPI1_Init(void)
{
/* USER CODE BEGIN OCTOSPI1_Init 0 */
MX25LM51245G_Info_t pInfo;
/* USER CODE END OCTOSPI1_Init 0 */
OSPIM_CfgTypeDef sOspiManagerCfg = {0};
HAL_OSPI_DLYB_CfgTypeDef HAL_OSPI_DLYB_Cfg_Struct = {0};
/* USER CODE BEGIN OCTOSPI1_Init 1 */
/* Get Flash informations of one memory */
(void)MX25LM51245G_GetFlashInfo(&pInfo);
/* USER CODE END OCTOSPI1_Init 1 */
hospi1.Instance = OCTOSPI1;
hospi1.Init.FifoThreshold = 4;
hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_MACRONIX;
hospi1.Init.DeviceSize = 32;
hospi1.Init.ChipSelectHighTime = 2;
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 = 2;
hospi1.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
hospi1.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;
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.DQSPort = 1;
sOspiManagerCfg.NCSPort = 1;
sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
sOspiManagerCfg.IOHighPort = HAL_OSPIM_IOPORT_1_HIGH;
if (HAL_OSPIM_Config(&hospi1, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
HAL_OSPI_DLYB_Cfg_Struct.Units = 0;
HAL_OSPI_DLYB_Cfg_Struct.PhaseSel = 0;
if (HAL_OSPI_DLYB_SetConfig(&hospi1, &HAL_OSPI_DLYB_Cfg_Struct) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN OCTOSPI1_Init 2 */
/* OSPI memory reset */
if (ospi_memory_reset(&hospi1) != 0)
{
Error_Handler();
}
if (MX25LM51245G_AutoPollingMemReady(&hospi1,MX25LM51245G_SPI_MODE, MX25LM51245G_STR_TRANSFER) != MX25LM51245G_OK)
{
Error_Handler();
}
/* Enable octal mode */
if (OSPI_NOR_EnterSOPIMode(&hospi1) != 0)
{
Error_Handler();
}
uint8_t data[] = "my hubbell test str";
uint32_t sizeval = strlen(data);
//MX25LM51245G_BlockErase(&hospi1, MX25LM51245G_SPI_MODE, MX25LM51245G_STR_TRANSFER,
// MX25LM51245G_4BYTES_SIZE, 0x90FF0000,
// MX25LM51245G_ERASE_64K);
//
//MX25LM51245G_ChipErase(&hospi1, MX25LM51245G_SPI_MODE, MX25LM51245G_STR_TRANSFER);
if (MX25LM51245G_PageProgram(&hospi1, MX25LM51245G_SPI_MODE,
MX25LM51245G_4BYTES_SIZE,
&data, 0x91000378,
sizeval) == MX25LM51245G_OK)
{
printf("reached here");
}
if (OSPI_NOR_EnableMemoryMappedMode(&hospi1) != 0)
{
Error_Handler();
}
/* USER CODE END OCTOSPI1_Init 2 */
}
The MX25LM51245G_PageProgram() API returns success message but I am unable to see the updated string in the external memory location through the memory browser window in CubeIDE. Also, the MX25LM51245G_BlockErase() and MX25LM51245G_ChipErase() does send the success response, but not clearing the specified memory block.
Is there something that I am missing here?
Regards
RiverDI user
2024-10-22 09:16 AM
Erase can complete immediately, without an error, if assorted BPx are set in SR1 for "Protection" these can get set using probe / configuration for QE (4-pin Enable) of different manufacturer parts, ie Winbond or Micron.
LM part is OCTO
Are you still getting the Hard Fault in Memory Mapped mode? You will get if not in that mode, or exceeds span.
hospi1.Init.DeviceSize = 32; // Isn't this a 5-bit field? 0-31
Inconsistent usage by ST
qspi_init.FlashSize = (uint32_t)POSITION_VAL((uint32_t)pInfo.FlashSize) - 1U;
ospi_config.MemorySize = (uint32_t)POSITION_VAL((uint32_t)pInfo.FlashSize);
27 for 64MB (512Mb) ?
2024-10-22 09:34 AM
I got the hardfault handler when I set the memory mapped mode and tried to write into external flash using memcpy() API. I have not used that approach in my current application and I am trying to write into memory using the MX25LM51245G_PageProgram() API.
The size of the external flash is 64MB, 1024 sectors of 64kb sized blocks.
2024-10-22 11:10 PM
Hello @KDJEM.1 ,
I have already ran this example application in my board (STM32U5A9) and I was able to see the string in the memory location through memory browser. But my issue is, when I tried to incorporate the same changes in my project, I couldn't find any option to enable XSPI. The OSPI example doesn't work for me, so I thought I can incorporate the XSPI changes in my project and use the same methods in example to write into external memory. Unfortunately I couldnt find an option to enable the XSPI. I have even tried to manually copy the xspi.c and .h files from the example project, but that throws lots of error due to settings like (error: 'XSPI_HandleTypeDef' undeclared ), USE_HAL_XSPI_REGISTER_CALLBACKS etc, and it doesn't compile as expected. Can you tell me how to enable the XSPI in my project?
No XSPI option here to select:
2024-10-23 01:44 AM
Hello @RiverDi_user ,
The STM32U5A9 supports three interfaces (OCTOSPI1, OCTOSPI2 and HSPI1).
The STM32U5 HAL delivers both stm32u5xx_hal_ospi.c/.h and stm32u5xx_hal_xspi.c/.h files for customers.
- stm32u5xx_hal_ospi.c/.h: for OCTOSPI1 and OCTOSPI2
- stm32u5xx_hal_xspi.c/.h: for HSPI1, OCTOSPI1 and OCTOSPI2
When using STM32CubeMx for generation code:
* stm32u5xx_hal_ospi.c is used when OCTOSPI instance is chosen
* stm32u5xx_hal_xspi.c is used when HSPI instance is chosen
>but that throws lots of error due to settings like (error: 'XSPI_HandleTypeDef' undeclared), USE_HAL_XSPI_REGISTER_CALLBACKS etc, and it doesn't compile as expected.
->If you want to use OCTOSPI interface, you can used OSPI_HandleTypeDef and USE_HAL_OSPI_REGISTER_CALLBACKS instead of XSPI_HandleTypeDef and USE_HAL_XSPI_REGISTER_CALLBACKS.
I recommend you to take a look at AN5050 this application note explains the difference between Octo-SPI, Hexadeca-SPI and XSPI interfaces in STM32 MCUs. Also this application note provides many examples in section 7 OCTOSPI application examples can 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-10-23 04:20 AM
HI @KDJEM.1,
I have tried to implement the application with OSPI enabled. Here are the steps that I did.
int main(void)
{
/* USER CODE BEGIN 1 */
OSPI_RegularCmdTypeDef sCommand = {0};
OSPI_MemoryMappedTypeDef sMemMappedCfg = {0};
uint32_t address = 0;
uint16_t index;
__IO uint8_t step = 0;
__IO uint8_t *mem_addr;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
// Other necessary inits
MX_OCTOSPI1_Init();
/* Configure the memory in octal mode ------------------------------------- */
OSPI_OctalModeCfg(&hospi1);
sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_8_LINES;
sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_16_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;
// ....../////...... Further code
}
static void OSPI_OctalModeCfg(OSPI_HandleTypeDef *hospi)
{
OSPI_RegularCmdTypeDef sCommand;
OSPI_AutoPollingTypeDef sConfig;
uint8_t reg;
/* Enable write operations ---------------------------------------- */
sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
sCommand.Instruction = WRITE_ENABLE_CMD;
sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE;
sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
sCommand.DataMode = HAL_OSPI_DATA_NONE;
sCommand.DummyCycles = 0;
sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;
sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
if (HAL_OSPI_Command(hospi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
/* Configure automatic polling mode to wait for write enabling ---- */
sCommand.Instruction = READ_STATUS_REG_CMD;
sCommand.DataMode = HAL_OSPI_DATA_1_LINE;
sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
sCommand.NbData = 1;
if (HAL_OSPI_Command(hospi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
sConfig.Match = WRITE_ENABLE_MATCH_VALUE;
sConfig.Mask = WRITE_ENABLE_MASK_VALUE;
sConfig.MatchMode = HAL_OSPI_MATCH_MODE_AND;
sConfig.Interval = AUTO_POLLING_INTERVAL;
sConfig.AutomaticStop = HAL_OSPI_AUTOMATIC_STOP_ENABLE;
if (HAL_OSPI_MemoryMapped(hospi, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* Write Configuration register 2 (with new dummy cycles) --------- */
sCommand.Instruction = WRITE_CFG_REG_2_CMD;
sCommand.Address = CONFIG_REG2_ADDR3;
sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS;
sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
if (HAL_OSPI_Command(hospi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
reg = CR2_DUMMY_CYCLES_66MHZ;
if (HAL_OSPI_Transmit(hospi, ®, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
/* Wait that the memory is ready ---------------------------------- */
sCommand.Instruction = READ_STATUS_REG_CMD;
sCommand.AddressMode = HAL_OSPI_ADDRESS_NONE;
if (HAL_OSPI_Command(hospi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
sConfig.Match = MEMORY_READY_MATCH_VALUE;
sConfig.Mask = MEMORY_READY_MASK_VALUE;
if (HAL_OSPI_AutoPolling(hospi, &sConfig, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
/* Enable write operations ---------------------------------------- */
sCommand.Instruction = WRITE_ENABLE_CMD;
sCommand.DataMode = HAL_OSPI_DATA_NONE;
if (HAL_OSPI_Command(hospi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
/* Configure automatic polling mode to wait for write enabling ---- */
sCommand.Instruction = READ_STATUS_REG_CMD;
sCommand.DataMode = HAL_OSPI_DATA_1_LINE;
if (HAL_OSPI_Command(hospi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
sConfig.Match = WRITE_ENABLE_MATCH_VALUE;
sConfig.Mask = WRITE_ENABLE_MASK_VALUE;
if (HAL_OSPI_AutoPolling(hospi, &sConfig, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
/* Write Configuration register 2 (with octal mode) --------------- */
sCommand.Instruction = WRITE_CFG_REG_2_CMD;
sCommand.Address = CONFIG_REG2_ADDR1;
sCommand.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
if (HAL_OSPI_Command(hospi, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
reg = CR2_STR_OPI_ENABLE;
if (HAL_OSPI_Transmit(hospi, ®, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
/* Wait that the configuration is effective and check that memory is ready */
HAL_Delay(MEMORY_REG_WRITE_DELAY);
/* Wait that the memory is ready ---------------------------------- */
OSPI_AutoPollingMemReady(hospi);
}
When I run the application, I get the Error_handler in line number 93 with the error state as "136" which is HAL_OSPI_STATE_BUSY_MEM_MAPPED. I believe its due to the API call just before line number 93 and the processor is still in that state.
Is there something that I can try to proceed forward from here?
and my OSPI init API is:
void MX_OCTOSPI1_Init(void)
{
/* USER CODE BEGIN OCTOSPI1_Init 0 */
MX25LM51245G_Info_t pInfo;
/* USER CODE END OCTOSPI1_Init 0 */
OSPIM_CfgTypeDef sOspiManagerCfg = {0};
HAL_OSPI_DLYB_CfgTypeDef HAL_OSPI_DLYB_Cfg_Struct = {0};
/* USER CODE BEGIN OCTOSPI1_Init 1 */
/* Get Flash informations of one memory */
(void)MX25LM51245G_GetFlashInfo(&pInfo);
/* 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 = 32;
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;
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.DQSPort = 1;
sOspiManagerCfg.NCSPort = 1;
sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
sOspiManagerCfg.IOHighPort = HAL_OSPIM_IOPORT_1_HIGH;
if (HAL_OSPIM_Config(&hospi1, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
HAL_OSPI_DLYB_Cfg_Struct.Units = 0;
HAL_OSPI_DLYB_Cfg_Struct.PhaseSel = 0;
if (HAL_OSPI_DLYB_SetConfig(&hospi1, &HAL_OSPI_DLYB_Cfg_Struct) != HAL_OK)
{
Error_Handler();
}
Regards
RiverDI_User
2024-10-23 06:07 AM - edited 2024-10-23 06:08 AM
Hello @RiverDi_user ,
Which memory are you using?
Could you please share the memory datasheet?
If you are using the same memory as mounted in STM32U5x9J-DK (MX25LM51245G), please take a look at this post. In this post you can find two working projects based on STM32CubeMx generation code: one in STR mode and one in DTR mode.
Please refer to these projects and check you OCTOSPI configuration device size, FifoThreshold, Prescaler......
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-10-24 05:59 AM - edited 2024-10-24 06:06 AM
Hi @KDJEM.1,
I am using STM32U5A9 variant (not discovery board) and the external flash is MX25LM51245G. I just checked this link you have shared yesterday and its similar to my issue. But I dont get the point, how changing from STMQUbe to Keil solved his issue.
I already have the https://github.com/STMicroelectronics/stm32-mx25lm51245g .c and .h files for the MX25LM51245G in my project, so I tried to utilize the APIs for reading and writing into the memory. I didnt receive any error, but it didnt write into the memory aswell.
Code example below
/* OCTOSPI1 init function */
void MX_OCTOSPI1_Init(void)
{
/* USER CODE BEGIN OCTOSPI1_Init 0 */
MX25LM51245G_Info_t pInfo;
/* USER CODE END OCTOSPI1_Init 0 */
OSPIM_CfgTypeDef sOspiManagerCfg = {0};
HAL_OSPI_DLYB_CfgTypeDef HAL_OSPI_DLYB_Cfg_Struct = {0};
/* USER CODE BEGIN OCTOSPI1_Init 1 */
/* Get Flash informations of one memory */
(void)MX25LM51245G_GetFlashInfo(&pInfo);
/* USER CODE END OCTOSPI1_Init 1 */
hospi1.Instance = OCTOSPI1;
hospi1.Init.FifoThreshold = 4;
hospi1.Init.DualQuad = HAL_OSPI_DUALQUAD_DISABLE;
hospi1.Init.MemoryType = HAL_OSPI_MEMTYPE_MACRONIX;
hospi1.Init.DeviceSize = 32;
hospi1.Init.ChipSelectHighTime = 2;
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 = 2;
hospi1.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
hospi1.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;
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.DQSPort = 1;
sOspiManagerCfg.NCSPort = 1;
sOspiManagerCfg.IOLowPort = HAL_OSPIM_IOPORT_1_LOW;
sOspiManagerCfg.IOHighPort = HAL_OSPIM_IOPORT_1_HIGH;
if (HAL_OSPIM_Config(&hospi1, &sOspiManagerCfg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
HAL_OSPI_DLYB_Cfg_Struct.Units = 0;
HAL_OSPI_DLYB_Cfg_Struct.PhaseSel = 0;
if (HAL_OSPI_DLYB_SetConfig(&hospi1, &HAL_OSPI_DLYB_Cfg_Struct) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN OCTOSPI1_Init 2 */
/* OSPI memory reset */
if (ospi_memory_reset(&hospi1) != 0)
{
Error_Handler();
}
if (MX25LM51245G_AutoPollingMemReady(&hospi1,MX25LM51245G_SPI_MODE, MX25LM51245G_STR_TRANSFER) != MX25LM51245G_OK)
{
Error_Handler();
}
/* Enable octal mode */
if (OSPI_NOR_EnterSOPIMode(&hospi1) != 0)
{
Error_Handler();
}
uint8_t data[] = "my hubbell test str";
uint32_t sizeval = strlen(data);
//MX25LM51245G_BlockErase(&hospi1, MX25LM51245G_SPI_MODE, MX25LM51245G_STR_TRANSFER,
// MX25LM51245G_4BYTES_SIZE, 0x90FF0000,
// MX25LM51245G_ERASE_64K);
//
//MX25LM51245G_ChipErase(&hospi1, MX25LM51245G_SPI_MODE, MX25LM51245G_STR_TRANSFER);
if (MX25LM51245G_PageProgram(&hospi1, MX25LM51245G_SPI_MODE,
MX25LM51245G_4BYTES_SIZE,
&data, 0x91000378,
sizeval) == MX25LM51245G_OK)
{
printf("reached here");
}
if (OSPI_NOR_EnableMemoryMappedMode(&hospi1) != 0)
{
Error_Handler();
}
/* USER CODE END OCTOSPI1_Init 2 */
}
I have given my API calls in the previous comments already. Please let me know if you need any further info to support this.
Regards
RiverDI_User
2024-10-29 08:10 AM
Hello @RiverDi_user ,
Are you try to run projects shared in this discussion? Do they work?
In your configuration, the device size is wrong. Please try to refer the shared example and correct it.
Also, it is necessary to check the Chip select high time and Refresh rate because these parameters depend on OCTOSPI clock. Please refer to AN5050 Table 8. STM32CubeMX - Configuration of OCTOSPI parameters.
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-11-04 09:30 PM
Hello @KDJEM.1,
I had a look at the document link you shared and tried with device size 26 and Refreshrate as 0 (as per doc) as I am using MX25LM51245G. But I still get the same results. One thing that I noticed is, when I try to write the data into external memory and tried to read it, I could partially read/write data into the memory and I see only 20 bytes of data being written and read when I browse through the memory. But when I read the memory from STM32QubeProgrammer, I could read the whole string that I have written in the location.
Also, when I use HAL_OSPI_Command_IT() API the application hardfaults in HAL_OSPI_IRQHandler(). (I am not sure why)
Browsing through STM32QubeIDE debugger:
Any idea why its happening like this?
Here is my updated code:
/* Initialization of the OSPI ------------------------------------------ */
OSPIHandle.Instance = OCTOSPI1;
HAL_OSPI_DeInit(&OSPIHandle);
OSPIHandle.Init.FifoThreshold = 1;
OSPIHandle.Init.MemoryType = HAL_OSPI_MEMTYPE_MACRONIX;
OSPIHandle.Init.DeviceSize = 26;
OSPIHandle.Init.ChipSelectHighTime = 3;
OSPIHandle.Init.FreeRunningClock = HAL_OSPI_FREERUNCLK_DISABLE;
OSPIHandle.Init.ClockMode = HAL_OSPI_CLOCK_MODE_0;
OSPIHandle.Init.WrapSize = HAL_OSPI_WRAP_NOT_SUPPORTED;
OSPIHandle.Init.ClockPrescaler = 2;
OSPIHandle.Init.SampleShifting = HAL_OSPI_SAMPLE_SHIFTING_NONE;
OSPIHandle.Init.DelayHoldQuarterCycle = HAL_OSPI_DHQC_ENABLE;
OSPIHandle.Init.ChipSelectBoundary = 0;
OSPIHandle.Init.DelayBlockBypass = HAL_OSPI_DELAY_BLOCK_BYPASSED;
OSPIHandle.Init.Refresh = 0;
if (HAL_OSPI_Init(&OSPIHandle) != HAL_OK)
{
Error_Handler();
}
// MX_NVIC_Init();
/* Configure the memory in octal mode ------------------------------------- */
OSPI_OctalModeCfg(&OSPIHandle);
sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_8_LINES;
sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_16_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;
uint8_t pData1[256];
MX25LM51245G_ReadSTR(&hospi1, MX25LM51245G_SPI_MODE,
MX25LM51245G_3BYTES_SIZE, &pData1[0], 0x90000000, 0x100);
while (step != 2)
{
switch(step)
{
case 0:
CmdCplt = 0;
/* Enable write operations ------------------------------------------ */
OSPI_WriteEnable(&OSPIHandle);
/* Erasing Sequence ------------------------------------------------- */
sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
sCommand.Instruction = MX25LM51245G_OCTA_SUBSECTOR_ERASE_4K_CMD;
sCommand.AddressMode = HAL_OSPI_ADDRESS_8_LINES;
sCommand.Address = address;
sCommand.DataMode = HAL_OSPI_DATA_NONE;
sCommand.DummyCycles = 0;
/* Todo:
* :
* HAL_OSPI_Command_IT command doesnt work and hardfaults, so used HAL_OSPI_Command temporarily */
if (HAL_OSPI_Command(&OSPIHandle, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
else
{
CmdCplt ++;
}
step++;
break;
case 1:
if(CmdCplt != 0)
{
CmdCplt = 0;
/* Configure automatic polling mode to wait for end of erase ------ */
OSPI_AutoPollingMemReady(&OSPIHandle);
/* Enable write operations ---------------------------------------- */
OSPI_WriteEnable(&OSPIHandle);
/* Memory-mapped mode configuration ------------------------------- */
sCommand.OperationType = HAL_OSPI_OPTYPE_WRITE_CFG;
sCommand.Instruction = MX25LM51245G_OCTA_PAGE_PROG_CMD;
sCommand.DataMode = HAL_OSPI_DATA_8_LINES;
sCommand.NbData = 1;
sCommand.DQSMode = HAL_OSPI_DQS_ENABLE;
if (HAL_OSPI_Command(&OSPIHandle, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
sCommand.OperationType = HAL_OSPI_OPTYPE_READ_CFG;
sCommand.Instruction = MX25LM51245G_OCTA_READ_CMD;
sCommand.DummyCycles = MX25LM51245G_CR2_DC_8_CYCLES;//DUMMY_CLOCK_CYCLES_READ;
sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;
if (HAL_OSPI_Command(&OSPIHandle, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
Error_Handler();
}
/* Issue page program command Note: doesn work*/
if (MX25LM51245G_PageProgram(&hospi1, MX25LM51245G_SPI_MODE,
MX25LM51245G_3BYTES_SIZE, &aTxBuffer[0], 0x93000000,
0x100) != MX25LM51245G_OK)
{
printf("write failed");
}
HAL_Delay(500);
uint8_t pData2[256];
// MX25LM51245G_ReadSTR(&hospi1, MX25LM51245G_SPI_MODE,
// MX25LM51245G_3BYTES_SIZE, &pData2[0], 0x93000000, 0x100);
sMemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_ENABLE;
sMemMappedCfg.TimeOutPeriod = 0x40;
if (HAL_OSPI_MemoryMapped(&OSPIHandle, &sMemMappedCfg) != HAL_OK)
{
Error_Handler();
}
uint8_t pData[256];
MX25LM51245G_ReadSTR(&hospi1, MX25LM51245G_SPI_MODE,
MX25LM51245G_3BYTES_SIZE, &pData[0], 0x90000000, 0x100);
// erase_block(0x93000000);
mem_addr = (uint8_t *)(OCTOSPI1_BASE + address);
// mem_addr = (uint8_t * )0x90FFFF00;
for (index = 0; index < (sizeof(aTxBuffer) / sizeof(*(aTxBuffer)) - 1); index++)
{
readData[index] = *mem_addr;
if (*mem_addr != aTxBuffer[index])
{
res++;
}
mem_addr++;
}
/* Writing Sequence ----------------------------------------------- */
mem_addr = (uint8_t *)(OCTOSPI1_BASE + address);
for (index = 0; index < (sizeof(aTxBuffer) / sizeof(*(aTxBuffer)) - 1); index++)
{
*mem_addr = aTxBuffer[index];
mem_addr++;
}
/* In memory-mapped mode, not possible to check if the memory is ready
after the programming. So a delay corresponding to max page programming
time is added */
HAL_Delay(MEMORY_PAGE_PROG_DELAY);
MX25LM51245G_ReadSTR(&hospi1, MX25LM51245G_SPI_MODE,
MX25LM51245G_3BYTES_SIZE, &pData[0], 0x90000000, 0x100);
/* Reading Sequence ----------------------------------------------- */
mem_addr = (uint8_t *)(OCTOSPI1_BASE + address);
for (index = 0; index < (sizeof(aTxBuffer) / sizeof(*(aTxBuffer)) - 1) ; index++)
{
readData[index] = *mem_addr;
if (*mem_addr != aTxBuffer[index])
{
res++;
}
mem_addr++;
}
MX25LM51245G_ReadSTR(&hospi1, MX25LM51245G_SPI_MODE,
MX25LM51245G_3BYTES_SIZE, &pData3[0], 0x90000000, 0x100);
if (res != 0)
{
// BSP_LED_On(LED_RED);
}
else
{
// BSP_LED_Toggle(LED_GREEN);
HAL_Delay(50);
}
address += OSPI_PAGE_SIZE;
if(address >= OSPI_END_ADDR)
{
address = 0;
}
/* Abort OctoSPI driver to stop the memory-mapped mode ------------ */
if (HAL_OSPI_Abort(&OSPIHandle) != HAL_OK)
{
Error_Handler();
}
step = 2;
}
break;
default :
Error_Handler();
}
}
Thanks & Regards