cancel
Showing results for 
Search instead for 
Did you mean: 

Does anybody have working write routine for OSPI ? STM32H7 MX25LM51245G

MNapi
Senior III

I used this

BSP_OSPI_NOR_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size) from

https://github.com/STMicroelectronics/stm32-external-loader/blob/main/STM32L4x_boards/MX25LM51245G_STM32L4P5G-DK/Sources/Library/stm32l4p5g_discovery_ospi_nor.c

 

but what happens after executing write I cannot access the H7 chip anymore.

I have to connect Boot0 pin to 3.3V then I can erase the internal FLASH in Cube programmer.

and it works again

 

uint8_t BSP_OSPI_NOR_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size)
{
OSPI_RegularCmdTypeDef sCommand;
uint32_t end_addr, current_size, current_addr;

/* Calculation of the size between the write address and the end of the page */
current_size = MX25LM51245G_PAGE_SIZE - (WriteAddr % MX25LM51245G_PAGE_SIZE);

/* Check if the size of the data is less than the remaining place in the page */
if (current_size > Size)
{
current_size = Size;
}

/* Initialize the adress variables */
current_addr = WriteAddr;
end_addr = WriteAddr + Size;

sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;

sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
sCommand.Instruction = OCTAL_PAGE_PROG_CMD;
sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_8_LINES;
sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_16_BITS;
sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
sCommand.AlternateBytes = 0x00;
sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
sCommand.AlternateBytesSize = HAL_OSPI_ALTERNATE_BYTES_8_BITS;
sCommand.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE;
sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
sCommand.DummyCycles = 0;
sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;
sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;

sCommand.Instruction = OCTAL_PAGE_PROG_CMD;
sCommand.AddressMode = HAL_OSPI_ADDRESS_8_LINES;
sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS;

sCommand.DataMode = HAL_OSPI_DATA_8_LINES;


/* Perform the write page by page */
do
{
sCommand.Address = current_addr;
sCommand.NbData = current_size;

/* Enable write operations */
if (OSPI_NOR_WriteEnable(&OSPINORHandle) != OSPI_NOR_OK)
{
return OSPI_NOR_ERROR;
}

/* Configure the command */
if (HAL_OSPI_Command(&OSPINORHandle, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return OSPI_NOR_ERROR;
}

/* Transmission of the data */
if (HAL_OSPI_Transmit(&OSPINORHandle, pData, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
{
return OSPI_NOR_ERROR;
}

/* Configure automatic polling mode to wait for end of program */
if (OSPI_NOR_AutoPollingMemReady(&OSPINORHandle, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != OSPI_NOR_OK)
{
return OSPI_NOR_ERROR;
}

/* Update the address and size variables for next page programming */
current_addr += current_size;
pData += current_size;
current_size = ((current_addr + MX25LM51245G_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : MX25LM51245G_PAGE_SIZE;
} while (current_addr < end_addr);


return OSPI_NOR_OK;
}

7 REPLIES 7

Is it stuck in OSPI_NOR_AutoPollingMemReady(), error or timeout?

If it is left active there will be problems, check the exit paths, if it doesn't complete with a match you'll need to use HAL_OSPI_Abort() to stop it.

 

>>but what happens after executing write I cannot access the H7 chip anymore.

Your code probably starts, but gets stuck later. Instrument better so you can see how far it gets before locking up.

Does the OCTOSPI device have it's own async reset input?

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

No it does not stock in OSPI_NOR_AutoPollingMemReady()

 

I had this problem and I found solution. Actually I have it all working fine in Keil.

I try now CubeIDE, I can erase, read

all those functions work fine

/* USER CODE BEGIN 2 */

OSPI_NOR_OctalMode(&hospi1, OSPI_NOR_OCTAL_ENABLE);

OSPI_NOR_WriteEnable(&hospi1);

OSPI_NOR_Erase_Sector( 0x1000, 0x2000);

 

/* USER CODE END 2 */

It is not freezing it will not write to the memory, it gets to while(1) loop and it is working fine

After that when I try to access the chip to upload code it says no STM32 target

The function to write from this github does not work and it makes the chip inaccessible after executing but not freezing. They have the code for Ewarm, maybe it has something to do with compiler itself.

Inaccessibility by STM32 Cube Programmer (without external loaders) points more to a LDO/SMPS issue, or PA13/PA14 being reconfigured. Or a bus level issue.

Not sure it would be a compiler thing, the IDE's use their own external loaders, not ST's

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

From a Bus / Memory Mapped perspective I'd watch for the time-out settings, so it doesn't get hung up indefinitely with speculative reads or probing of memory ranges

https://github.com/STMicroelectronics/stm32-external-loader/blob/main/STM32L4x_boards/MX25LM51245G_STM32L4P5G-DK/Sources/Library/stm32l4p5g_discovery_ospi_nor.c#L692

 

Perhaps add a delay or awareness of a button in the Reset Handler paths so the debugger has a opportunity to wrestle control of the MCU as it connects. Use "Connect Under Reset" methods with NRST connected to the debugger so it can effectuate such a method.

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

debug is set to serial wire PA13,PA14 so the problem is not here

supply source  is set to PWR_LDO_SUPPLY and it is working

 

all is working fine until I execute

 

OSPI_NOR_WriteEnable(&hospi1);

OSPI_NOR_Write(aTxBuffer, 0x0000, 50);

 

then I get error message STM32 not found

 

So I was looking for another write function to test, I do not see too many OSPI examples

 

I have the code working in Keil a little different than this one posted on github

 

 

 

Nothing looking particularly amiss, the other stuff to hand is for the Micron MT35xL256/512/01G/02G parts

OSPI_RegularCmdTypeDef sCommand = {0};

sCommand.Address = current_addr & 0x0FFFFFFF; // zero basis, up to 256MB

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
LCE
Principal
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* OCTOSPI FLASH write page
 *	in SPI OCTAL mode
 */
/**
  * @brief  write page - SPI or MULT
  *				### BLOCKING ###
  *				but only takes about 20µs at 50 MHz,
  *				waiting for programming page done in state machine
  * @PAram  none
  *				write settings elsewhere,
  *				for now fixed page buffer is used
  * @retval 0 = ok
  */
uint8_t OspiFlashWrPage(void)
{
	uint8_t u8RetVal = 0;

	/* check pointer */
	if( NULL == sOspiFlashCtl.pu8WrBuf )
	{
		#if DEBUG_OSPIFLASH
			uart_printf("# ERR: OspiFlashWrPage(): pu8WrBuf = NULL\n\r");
		#endif 	/* DEBUG_OSPIFLASH */
		return HAL_ERROR;
	}

	/* check if flash shows write in progress */
	if( OspiFlashCheckSrWip() != 0 )
	{
		#if DEBUG_OSPIFLASH
			uart_printf("# ERR: OspiFlashWrPage(): WIP\n\r");
		#endif 	/* DEBUG_OSPIFLASH */
		return HAL_ERROR;
	}

	/* check SPI / OCTAL STR mode */
	u8RetVal = OspiFlashRdRegCR2();
	if( HAL_OK != u8RetVal )
	{
		#if DEBUG_OSPIFLASH
			uart_printf("# ERR: OspiFlashWrPage(): OspiFlashRdRegCR2()\n\r");
		#endif 	/* DEBUG_OSPIFLASH */
		return HAL_ERROR;
	}
	else if( (0 != sOspiFlashRegs.u8CR2) &&
			 (0 == (sOspiFlashRegs.u8CR2 & OSPI_FLASH_CR2_SOPI)) )
	{
		#if DEBUG_OSPIFLASH
			uart_printf("# ERR: OspiFlashWrPage(): not in SPI or MULT mode\n\r");
		#endif 	/* DEBUG_OSPIFLASH */
		return HAL_ERROR;
	}

	/* set write enable */
	if( OspiFlashWriteEnable() )
	{
		#if DEBUG_OSPIFLASH
			uart_printf("# ERR: OspiFlashWrPage(): OspiFlashWriteEnable()\n\r");
		#endif 	/* DEBUG_OSPIFLASH */
		return HAL_ERROR;
	}

	/* wait for internal BUSY release to write registers */
	if( OspiFlashCheckBusyTo(OSPI_FLASH_TO_BUSY_MS) )
	{
		#if DEBUG_OSPIFLASH
			uart_printf("# ERR: OspiFlashWrPage(): OCTOSPI_SR_BUSY\n\r");
		#endif 	/* DEBUG_OSPIFLASH */
		return HAL_ERROR;
	}

/* +++++++++++++++++++++++++++++++++++++++++++ */
/* command config */

	/* CR: functional mode = 00 = indirect WRITE */
	pOspiFlash->CR = OSPI_FLASH_CR_EN_IWRITE;
	/* CCR: reset */
	pOspiFlash->CCR = 0;
	/* DLR: data length */
	pOspiFlash->DLR = (sOspiFlashCtl.u32WrLen - 1);
	/* AR: set address */
	pOspiFlash->AR = sOspiFlashCtl.u32WrAddr;

	if( OSPIFLSH_MODE_SPI == u8OspiFlashMode )
	{
		/* TCR: SPI write dummy cycles between addr and data */
		pOspiFlash->TCR = OSPI_FLASH_TCR_SPI_STR;
		/* CCR: no DTR, SPI 8b instruction + 8b data + 32b address: 1 line */
		pOspiFlash->CCR = OSPI_FLASH_CCR_SPI_STR_D1A32I8;
		/* IR: set write instruction */
		pOspiFlash->IR = OSPI_FLASH_CMD_SPI_WR_DATA_4BA;
	}
	else if( OSPIFLSH_MODE_MULT == u8OspiFlashMode )
	{
		/* TCR: OCT write dummy cycles between addr and data */
		pOspiFlash->TCR = OSPI_FLASH_TCR_OCT_STR_WR_DAT;
		/* write data in OCTAL mode with 4 byte address */
		pOspiFlash->CCR = OSPI_FLASH_CCR_OCT_STR_D8A32I16;

		/* IR: set write MULT STR instruction */
		pOspiFlash->IR 	= OSPI_FLASH_CMD_MULT_PROG_PAGE;
	}
	else
	{
		#if DEBUG_OSPIFLASH
			uart_printf("# ERR: OspiFlashWrPage(): not in SPI or MULT mode\n\r");
		#endif 	/* DEBUG_OSPIFLASH */
		return HAL_ERROR;
	}

/* command config done */
/* --------------------------------------------- */

#if DEBUG_OSPIFLASH
	uart_printf("pOspiFlash->DLR = %08lX\n\r", pOspiFlash->DLR);
	uart_printf("pOspiFlash->TCR = %08lX\n\r", pOspiFlash->TCR);
	uart_printf("pOspiFlash->CCR = %08lX\n\r", pOspiFlash->CCR);
	uart_printf("pOspiFlash->IR  = %08lX\n\r", pOspiFlash->IR);
	uart_printf("pOspiFlash->AR  = %08lX\n\r", pOspiFlash->AR);
	uart_printf("sOspiFlashCtl.u32WrLen = %lu\n\r", sOspiFlashCtl.u32WrLen);
#endif 	/* DEBUG_OSPIFLASH */

/* +++++++++++++++++++++++++++++++++++++++++++ */
/* transfer with command, address & data
 *	TRIGGER: writing data register OCTOSPIn->DR
 */

	/* get data via pointer for byte cast */
	__IO uint32_t *pu32DR = &pOspiFlash->DR;

	for( uint32_t i = 0; i < OSPI_FLASH_PAGE_SIZE; i++ )
	{
		u8RetVal = OspiFlashWaitFlagSetTo(OCTOSPI_SR_FTF, OSPI_FLASH_TO_WRFF_MS);
		if( u8RetVal != 0 ) break;

		/* write byte to flash */
		//*((__IO uint8_t *)pu32DR) = u8OspiFlashPageBuf[i];
		*((__IO uint8_t *)pu32DR) = sOspiFlashCtl.pu8WrBuf[i];
		sOspiFlashCtl.u32WrBtDone++;
	}

/* writing data done */
/* --------------------------------------------- */

	/* check transfer complete */
	if( OspiFlashWaitFlagSetTo(OCTOSPI_SR_TCF, OSPI_FLASH_TO_WRFF_MS) )
	{
		u8RetVal++;
		#if DEBUG_OSPIFLASH
			uart_printf("# ERR: OspiFlashWrPage(): OCTOSPI_SR_TCF, u32WrBtDone = %lu\n\r", sOspiFlashCtl.u32WrBtDone);
		#endif 	/* DEBUG_OSPIFLASH */
	}
	#if( 0 ) //DEBUG_OSPIFLASH
		else uart_printf("OspiFlashWrPage() okay, u32WrBtDone = %lu\n\r", sOspiFlashCtl.u32WrBtDone);
	#endif 	/* DEBUG_OSPIFLASH */

	/* clear transfer complete flag */
	pOspiFlash->FCR = OCTOSPI_FCR_CTCF;

	/* transfer ERROR check */
	if( pOspiFlash->SR & OCTOSPI_SR_TEF )
	{
		u8RetVal++;
		u32OspiFlashErrTE++;
		/* clear register flag */
		pOspiFlash->FCR = OCTOSPI_FCR_CTEF;
		#if DEBUG_OSPIFLASH
			uart_printf("# ERR: OspiFlashWrPage(): OCTOSPI_SR_TEF\n\r");
		#endif 	/* DEBUG_OSPIFLASH */
	}

	return u8RetVal;
}

 

No HAL, but working...