Skip to main content
Graduate
June 16, 2024
Solved

Undetermined Nonvolatile configuration register of MT25QL01GBBB NOR Flash Memory using STM32F765VGT6

  • June 16, 2024
  • 1 reply
  • 3152 views
I have an MT25QL01GBBB8ESF-0SIT controlled by an STM32F765VGT6 microcontroller. This was coded using C and the STM32 HAL in the STM32CubeIDE. It was verified working using different SPI commands such as read JEDEC ID, page program, etc. However, after writing to the nonvolatile configuration register, all the tested code stopped working. 
 
Now, I am trying to fix this issue using the power loss recovery function and interface rescue functions of the flash memory. But the flash memory still does not work properly. Would appreciate help in fixing this issue. Let me know if any more information is needed.
 
I have tried resetting the chip using software and hardware reset pin. I also have an exact duplicate of the chip connected to the same SPI line and verified all the code to be working properly except for the write nonvolatile configuration register function as I did not want to corrupt that chip as well.
 
Currently, I am trying to implement a power loss recovery and interface rescue function based on the documentation of the flash memory. However, results are still not as expected. 
 
Results:
|Results| JEDEC ID | Flag SR  |
|--------| -------- | -------- |
|Expected| 0x20BA21 | 0x80     |
|Actual  | 0xFFFFFF | 0xFF     |
 
ISSUE:
Nonvolatile Configuration Register was set to an undetermined state due to a logical error in the code after sending a write nonvolatile configuration register command. 
SOLUTION: 
Use the power loss recovery sequence in the documentation of the flash memory and reset the nonvolatile configuration register. Big thanks to @Tesla DeLorean for pointing out the issue and providing a solution.
  1. Disable SPI.
  2. Set pin SPI_SCK, SPI_MOSI (DQ0), and HOLD (DQ3) as GPIO pins at very high max output speed.
  3. Insert the clock cycle function in your main.c. Run the GPIO sequence as shown in the code below.
  4. Power Loss Recovery Sequence is completed and extended SPI is now enabled.
  5. Verify working by reading the JEDEC ID of the flash memory.
  6. Reset the Nonvolatile Configuration Register by writing 0xFFFF to the nonvolatile configuration register. Ignore LSB requirement.
//Clock cycle function.
void clock_cycle(uint8_t clocks){
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
	for(uint8_t i = 0; i<clocks; i++){
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
	}
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);
}

//Insert this in main function
// DO NOT USE BREAKPOINTS. SEQUENCE MUST BE COMPLETED WITHOUT INTERRUPTION
//Step 1
 printf("Starting step 1 power loss recovery sequence");
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); //DQ3
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET); //DQ0
 clock_cycle(7);
 clock_cycle(9);
 clock_cycle(13);
 clock_cycle(17);
 clock_cycle(25);
 clock_cycle(33);
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); //DQ3
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET); //DQ0

 //Step 2
 printf("Starting step 2 power loss recovery sequence");
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); //DQ3
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET); //DQ0
 clock_cycle(8);
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); //DQ3
 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_RESET); //DQ0

 printf("Completed power loss recovery sequence");

 

 

 

 

 

 

 

 

 

    This topic has been closed for replies.
    Best answer by Tesla DeLorean

    You're sending a magic sequence of all ONEs to MOSI

    You might have to do this sequencing void direct GPIO interaction, not using the SPI peripheral.

    And you need a brief break time between sequences with the chip select.

    Perhaps use a scope or logic analyzer to confirm the correct pattern if having trouble.

    1 reply

    Graduate II
    June 16, 2024

    Well reverse_bits() is broken.

    Is there a slight delay in csHIGH(FM) so next HIGH/LOW has separation.

    WaynsdayAuthor
    Graduate
    June 16, 2024

    Thank you for taking the time.

    That seems to be the case. The write nonvolatile register command requires input data of LSB first so I've corrected the function here. This has not been tested yet.

    Additionally, there is no delay in csHIGH(FM). I will implement a 1ms delay. Thank you

    static uint8_t reverse_bits(uint8_t byte)
    {
     byte = (byte & 0xF0) >> 4 | (byte & 0x0F) << 4;
     byte = (byte & 0xCC) >> 2 | (byte & 0x33) << 2;
     byte = (byte & 0xAA) >> 1 | (byte & 0x55) << 1;
     return byte;
    }
    
    void MT25QL_WriteNONVOL(SPI_HandleTypeDef *hspi, MT25QL_FM_NO_t FM, uint16_t reg_val)
    {
    	uint8_t tData[3];
    	tData[0] = WRITE_NONVOL_CFG_REG_CMD;
    	tData[1] = reverse_bits((reg_val >>8) & 0xFF);
    	tData[2] = reverse_bits(reg_val & 0xFF);
    
    	write_enable(hspi, FM);
    	csLOW(FM);
    	SPI_Write(hspi, tData, 3);
    	csHIGH(FM);
    
    	//write enable reset is automatic
    }

     

     

    Graduate II
    June 16, 2024

    >>I will implement a 1ms delay. 

    That's likely to be slow and excessive.

    Could you use DWT CYCCNT or a TIM counting at 1 MHz / 1 us (counting, not interrupting)? Or honestly a 50-100 ns

    Test by printing content rather than sending to the IC

    What are you writing to WRITE_NONVOL_CFG_REG_CMD, and why?