2024-06-10 08:06 AM - last edited on 2024-06-10 04:20 PM by Tesla DeLorean
I used this
BSP_OSPI_NOR_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size) from
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;
}
2024-06-10 01:24 PM
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?
2024-06-10 02:42 PM - edited 2024-06-10 02:43 PM
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.
2024-06-10 02:58 PM
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
2024-06-10 04:25 PM
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
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.
2024-06-10 05:40 PM
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
2024-06-10 07:07 PM
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
2024-06-11 04:32 AM
/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
/* 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...