cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7B3 OctoSPI Flash. Octal_Polling_WEL() has a problem

LLily.2
Associate II

Hi everyone, this is my first time posting a question.

I use the MX25UM51245G OctoSPI Flash memory of the STM32H7B3LI Discovery Board. Use stm32cubeIDE. I have referred to STM32L4 Octo-SPI Application note and STM32H7 Octo-SPI Application note.

But I still have a problem at the place of Octal_Polling_WEL(), the error occurs at

If (HAL_OSPI_Receive(&hospi1, reg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)

the return reg value is 0x00.

void MX25LM51245G_OctalPollingWEL(void)
{//This function Configures Software polling to wait until WEL=1
 
	OSPI_RegularCmdTypeDef s_command = {0};
	OSPI_AutoPollingTypeDef s_config = {0};
 
	// Configure automatic polling mode to wait for memory ready
	s_command.OperationType   = HAL_OSPI_OPTYPE_COMMON_CFG;
	s_command.FlashId      = HAL_OSPI_FLASH_ID_1;
	s_command.InstructionMode  = HAL_OSPI_INSTRUCTION_8_LINES;
	s_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_ENABLE;
	//s_command.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
	s_command.InstructionSize  = HAL_OSPI_INSTRUCTION_16_BITS;
	s_command.Instruction    = MX25LM51245G_OCTA_READ_STATUS_REG_CMD;
	s_command.AddressMode    = HAL_OSPI_ADDRESS_8_LINES;
	s_command.AddressDtrMode   = HAL_OSPI_ADDRESS_DTR_ENABLE;
	//s_command.AddressDtrMode   = HAL_OSPI_ADDRESS_DTR_DISABLE;
	s_command.AddressSize    = HAL_OSPI_ADDRESS_32_BITS;
	s_command.Address      = 0;
	s_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
	s_command.DataMode      = HAL_OSPI_DATA_8_LINES;
	s_command.DataDtrMode    = HAL_OSPI_DATA_DTR_ENABLE;
	//s_command.DataDtrMode    = HAL_OSPI_DATA_DTR_DISABLE;
	s_command.DummyCycles    = DUMMY_CYCLES_REG_OCTAL;
	s_command.NbData       = 2;
	//s_command.NbData       = 1;
	s_command.DQSMode      = HAL_OSPI_DQS_DISABLE;
	s_command.SIOOMode      = HAL_OSPI_SIOO_INST_EVERY_CMD;
 
 
	s_config.Match     = 2;//Set the match to 0x02 to check if the WEL bit is Set
	s_config.Mask     = MX25LM51245G_SR_WEL;//Set the mask to 0x02 to mask all Status REG bits except WEL
	s_config.MatchMode   = HAL_OSPI_MATCH_MODE_AND;
	s_config.Interval   = MX25LM51245G_AUTOPOLLING_INTERVAL_TIME;
	s_config.AutomaticStop = HAL_OSPI_AUTOMATIC_STOP_ENABLE;
 
	uint8_t reg[2];
 
	do
	{
              if (HAL_OSPI_Command(&hospi1, &s_command, 
   HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
                      Error_Handler();
 
             if (HAL_OSPI_Receive(&hospi1, reg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
                Error_Handler();
 
	//use to SPI mode. not use OPI mode, it will cause to the error 
	//if (HAL_OSPI_AutoPolling(&hospi1, &s_config, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
           //return -1;
	}while((reg[0] & WRITE_ENABLE_MASK_VALUE) != WRITE_ENABLE_MATCH_VALUE); 
 
}

Please tell me if anyone has encountered this problem and can help solve it, thank you.

1 ACCEPTED SOLUTION

Accepted Solutions

If the memory is returning zero for that command/request you'll probably want to confirm that at a bus level.

Would suggest reading other registers, and functionality of the chip, to confirm those read different things, and read consistently with expectations. Say reading a serial number or unique ID, or reading SFDP

I don't recall if this part supports it, but what we're trying to achieve is some means to validate functionality, and appropriate modes of operation.

https://www.macronix.com/Lists/ApplicationNote/Attachments/1870/AN114v1-SFDP%20Introduction.pdf

In at least one of the examples I think you blindly wrote register content, so any non-volatile bits would be gone.

The block lock is more likely to result in Erase or Writes failing. Doing a Write Enable typically doesn't infer an address.

My recommendation continues to be that you need to build a foundation of basic functionality, so you can sanity check if your code works as expected. Once the basic read, write, erase, register/status stuff is understood and validated you can then pivot into more exotic modes of operation, and quickly determine which do and do not work as expect, or as before. It's very easy to get these devices into relatively unworkable states if you send them a stream of commands and data they don't understand or interpret properly.

Here we do that with extensive instrumentation, and validation with test patterns.

I can't commit resources to debugging/troubleshooting your hardware / software.

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

View solution in original post

8 REPLIES 8

0x88 seems like the peripheral or the pins aren't correctly enabled.

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

Thank you for your reply.

I connected the pin according to stm32H7B3I_Schematic.pdf, and I have repeatedly confirmed that the pin is correct, so it should be correct...

The picture below is the pin of stm32cube and STM32H7B3 OctoSPI Flash Schematic pdf.
_legacyfs_online_stmicro_images_0693W00000bjhfoQAA.png
_legacyfs_online_stmicro_images_0693W00000bjhfyQAA.png 

Does it work in non-DTR mode?

Bring up the OCTOSPI part in the simplest of modes and get that working.

I haven't read the Macronix spec cover to cover, but I'd doubt the status register is using complex modes, and certainly not out of reset.

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

The preceding section is configured to use non-DTR mode.

While the OPI_WriteEnable and Octal_PollingWEL operations in the subsequent section are performed using DTR mode. The reference source for this is the STM32H7 Octo-SPI Application Note.

I have also used OPI_WriteEnable and Octal_PollingWEL in non-DTR mode, but there are still errors.​

Below is a simplified .c file:

Why are you driving the NCS pin manually?

Still errors? That the chip doesn't return the expected values, or it hasn't accepted commands, or changes in configuration registers.

Instrument the code so you can see what's happening.

Modify registers at a bit level, read original content, and mask/or on bits of interest. Instrument that.

Perhaps look at bus level transactions with a logic analyzer.

Start with basic functionality.

If the switch to DTR modes is not successful, or the STM32 vs Memory have different ideas about which mode is being used, the commands are likely to fail.

Check status bits.

Make it work on the DISCO board first.

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

1. The issue with manually driving the NCS pin has been resolved, as I have removed it. However, I am still receiving a reg value of 0.

(if (HAL_OSPI_Receive(&hospi1, reg, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)

2. In the sections of OPI_WriteEnable and Octal_PollingWEL, regardless of whether DtrMode is set to DTR_ENABLE or DTR_DISABLE, the reg value remains at 0.​

3. Due to the lack of external pins on the stm32H7B3 board, it is not possible to use a logic analyzer for testing. This is quite a challenging situation...

4. Since I am a newcomer and have only recently started learning, I am guessing whether the issue could be related to Block lock protection?


_legacyfs_online_stmicro_images_0693W00000bjyWPQAY.png

If the memory is returning zero for that command/request you'll probably want to confirm that at a bus level.

Would suggest reading other registers, and functionality of the chip, to confirm those read different things, and read consistently with expectations. Say reading a serial number or unique ID, or reading SFDP

I don't recall if this part supports it, but what we're trying to achieve is some means to validate functionality, and appropriate modes of operation.

https://www.macronix.com/Lists/ApplicationNote/Attachments/1870/AN114v1-SFDP%20Introduction.pdf

In at least one of the examples I think you blindly wrote register content, so any non-volatile bits would be gone.

The block lock is more likely to result in Erase or Writes failing. Doing a Write Enable typically doesn't infer an address.

My recommendation continues to be that you need to build a foundation of basic functionality, so you can sanity check if your code works as expected. Once the basic read, write, erase, register/status stuff is understood and validated you can then pivot into more exotic modes of operation, and quickly determine which do and do not work as expect, or as before. It's very easy to get these devices into relatively unworkable states if you send them a stream of commands and data they don't understand or interpret properly.

Here we do that with extensive instrumentation, and validation with test patterns.

I can't commit resources to debugging/troubleshooting your hardware / software.

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

Thank you for your help during this time.

I deleted all stm32cubeide. STM32Cube regenerates a new stm32cubeide, and the program is not modified at all, so there is no problem at all.

It is amazing...