cancel
Showing results for 
Search instead for 
Did you mean: 

W25Q256 write protection

Thomas8607
Senior

Hi!

Why can i not disable the protection? I use W25Q256. I can't write and erase the flash ic.

The programming was working, but suddenly an error occurred during download. Here I noticed that the bits of SR 1 went to 1 and I can't reset them.

What could be the problem that I can't find?

I attached the picture from the readed registers.

Thank you!

 

Here is my code:

 

/* Enable Quad Mode & Set Dummy Cycles Count */ HAL_StatusTypeDef W25Q_QSPI_Configuration() { uint8_t reg1 = 0, reg2 = 0, reg3 = 0; uint8_t w_reg1 = 0, w_reg2 = 0, w_reg3 = 0; if (W25Q_Read_Status_Registers(&reg1, 1) != HAL_OK) { return HAL_ERROR; } if (W25Q_Read_Status_Registers(&reg2, 2) != HAL_OK) { return HAL_ERROR; } if (W25Q_Read_Status_Registers(&reg3, 3) != HAL_OK) { return HAL_ERROR; } #if W25Q_FLASH_SIZE > 0x1000000 // If ADP != 1 if(!((reg3 >> 1) & 0b1)) { // Check 1.bit w_reg3 = reg3 | (1 << 1); // Set ADP 1.bit } // If ADS != 1 if(reg3 & 0b1) { // Check ADS 0.bit W25Q_Enter4ByteMode(1); // Enter 4byte mode } #else // If ADS != 1 if(((reg3 >> 0) & 1)) { // Check 0.bit // Enter 4 byte mode W25Q_Enter4ByteMode(0); // Exit 4byte mode } #endif w_reg1 = 0x0; //reg1; w_reg2 = reg2 | W25Q_SR_Quad_Enable; w_reg3 = reg3 | 0xA9; if (W25Q_Write_Status_Registers(w_reg1, 1) != HAL_OK) { return HAL_ERROR; } if (W25Q_Write_Status_Registers(w_reg2, 2) != HAL_OK) { return HAL_ERROR; } if (W25Q_Write_Status_Registers(w_reg3, 3) != HAL_OK) { return HAL_ERROR; } return HAL_OK; }
View more

 

 

6 REPLIES 6

Some of the older parts SR1 and SR2 must write as a pair.

The high order bit in SR1 clears via a power cycle, once set you can't change the other bits.

Yes, need to clear the BPx bits and COM

Seen a number of people jam up the parts this way.

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

Can you help me with what exactly I have to do to make the ic work again, what is the solution to this error? I tried quite a few things but it didn't work. Thanks

https://community.st.com/t5/stm32-mcus-products/stm32h743-external-loader/m-p/639422/highlight/true#M235411

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 the link, but
I rewrote the code into my program, but when I read the registers back, all the bits are still 1. I can't set them to 0.
I also defined W25Q256 so that the status register is 16 bits, but it is not good.
I don't know what else could be wrong and why it happened at all.

/* QSPI Initial Function */ HAL_StatusTypeDef W25Q_QSPI_Init(void) { hqspi.Instance = QUADSPI; if (HAL_QSPI_DeInit(&hqspi) != HAL_OK) { return HAL_ERROR; } MX_QUADSPI_Init(); if (W25Q_QSPI_ResetChip() != HAL_OK) { return HAL_ERROR; } if (W25Q_QSPI_Configuration() != HAL_OK) { return HAL_ERROR; } if (W25Q_QSPI_AutoPollingMemReady() != HAL_OK) { return HAL_ERROR; } if (W25Q_QSPI_WriteEnable() != HAL_OK) { return HAL_ERROR; } return HAL_OK; } /* Reset Chip Function */ HAL_StatusTypeDef W25Q_QSPI_ResetChip() { QSPI_CommandTypeDef sCommand = {0}; /* Enable Reset --------------------------- */ sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; sCommand.Instruction = W25Q_ENABLE_RST_CMD; /* Reset command enable */ sCommand.AddressMode = QSPI_ADDRESS_NONE; sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; sCommand.DataMode = QSPI_DATA_NONE; sCommand.DummyCycles = 0; sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } /* Reset execute */ sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; sCommand.Instruction = W25Q_RESET_CMD; /* Reset command execute */ sCommand.AddressMode = QSPI_ADDRESS_NONE; sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; sCommand.DataMode = QSPI_DATA_NONE; sCommand.DummyCycles = 0; sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } for (uint32_t temp = 0; temp < 500000; temp++) { __NOP(); } return HAL_OK; } /* Write Enable Function */ HAL_StatusTypeDef W25Q_QSPI_WriteEnable() { QSPI_CommandTypeDef sCommand = { 0 }; QSPI_AutoPollingTypeDef sConfig = { 0 }; /* Enable write operations ------------------------------------------ */ sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; sCommand.Instruction = W25Q_WRITE_ENABLE_CMD; sCommand.AddressMode = QSPI_ADDRESS_NONE; sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; sCommand.DataMode = QSPI_DATA_NONE; sCommand.DummyCycles = 0; sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } /* Configure automatic polling mode to wait for write enabling ---- */ sConfig.Match = 0x02U; sConfig.Mask = 0x02U; sConfig.MatchMode = QSPI_MATCH_MODE_AND; sConfig.StatusBytesSize = 1; sConfig.Interval = W25Q_AUTOPOLLING_INTERVAL_TIME; sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; sCommand.Instruction = W25Q_READ_SR1_CMD; sCommand.DataMode = QSPI_DATA_1_LINE; if (HAL_QSPI_AutoPolling(&hqspi, &sCommand, &sConfig, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return HAL_ERROR; } return HAL_OK; } /* Auto Polling Memory Function */ HAL_StatusTypeDef W25Q_QSPI_AutoPollingMemReady() { QSPI_CommandTypeDef sCommand = { 0 }; QSPI_AutoPollingTypeDef sConfig = { 0 }; /* Configure automatic polling mode to wait for memory ready ------ */ sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; sCommand.Instruction = W25Q_READ_SR1_CMD; /* Register 1 reading */ sCommand.AddressMode = QSPI_ADDRESS_NONE; sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; sCommand.DataMode = QSPI_DATA_1_LINE; sCommand.DummyCycles = 0; sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; sConfig.Match = 0x00U; sConfig.Mask = 0x01U; sConfig.MatchMode = QSPI_MATCH_MODE_AND; sConfig.StatusBytesSize = 1; sConfig.Interval = W25Q_AUTOPOLLING_INTERVAL_TIME; sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE; if (HAL_QSPI_AutoPolling(&hqspi, &sCommand, &sConfig, HAL_MAX_DELAY) != HAL_OK) { return HAL_ERROR; } return HAL_OK; } /* Write Status Registers Function */ HAL_StatusTypeDef W25Q_Write_Status_Registers(uint32_t reg_data, uint8_t reg_num) { QSPI_CommandTypeDef sCommand = {0}; sCommand.NbData = 1; switch(reg_num) { #if 1 // WINBOND case 1 : // REG1 sCommand.Instruction = W25Q_WRITE_SR1_CMD; sCommand.NbData = 2; // REG1 and REG2 as 16-bit break; #else case 1 : sCommand.Instruction = W25Q_WRITE_SR1_CMD; break; // REG1 case 2 : sCommand.Instruction = W25Q_WRITE_SR2_CMD; break; // REG2 case 3 : sCommand.Instruction = W25Q_WRITE_SR3_CMD; break; // REG3 #endif default: return(HAL_ERROR); } sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE; sCommand.AddressMode = QSPI_ADDRESS_NONE; sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; sCommand.DataMode = QSPI_DATA_1_LINE; sCommand.DummyCycles = 0; sCommand.DdrMode = QSPI_DDR_MODE_DISABLE; sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY; sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD; /* Enable write operations */ if (W25Q_QSPI_WriteEnable() != HAL_OK) { return(HAL_ERROR); } /* Send the command */ if (HAL_QSPI_Command(&hqspi, &sCommand, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return(HAL_ERROR); } /* Transmission of the data */ if (HAL_QSPI_Transmit(&hqspi, (void *)&reg_data, HAL_QSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { return(HAL_ERROR); } return(HAL_OK); } // Enable Quad Mode HAL_StatusTypeDef W25Q_QSPI_Configuration() // WINBOND { uint32_t Id, Reg1, Reg2; if (W25Q_Read_Status_Registers(&Id, 0x9F) == HAL_OK) { Id &= 0xFFFF; if ((Id != 0x40EF) && (Id != 0x60EF)) // WINBOND CHECK return(HAL_ERROR); } else { return(HAL_ERROR); } if (W25Q_Read_Status_Registers(&Reg1, 1) != HAL_OK) return(HAL_ERROR); if (W25Q_Read_Status_Registers(&Reg2, 2) != HAL_OK) return(HAL_ERROR); // Unfudge parts where invalid MICRON, MACRONIX and WINBOND sequences have been registered #if defined(USE_W25Q256) || defined(USE_W25Q512) || defined(USE_W25Q01) || defined(USE_W25Q02) if (((Reg2 & 0x42) != 0x02) || ((Reg1 & 0x3C) != 0)) { Reg2 |= 2; // Set QE Reg2 &= ~0x40; // COM=0 Reg1 &= ~0x3C; // Clear BP0,BP1,BP2,BP3 #else if (((Reg2 & 0x42) == 0) || ((Reg1 & 0x1C) != 0)) // W25Q64 / W25Q128 { Reg2 |= 2; // Set QE Reg2 &= ~0x40; // COM = 0 Reg1 &= ~0x1C; // Clear BP0,BP1,BP2 #endif if (W25Q_Write_Status_Registers(((Reg2 << 8) | Reg1), 1) != HAL_OK) // WINBOND WRITES BOTH return(HAL_ERROR); /* Configure automatic polling mode to wait the memory is ready */ if (W25Q_QSPI_AutoPollingMemReady() != HAL_OK) { //puts("Fail Quad"); return(HAL_ERROR); } if (W25Q_Read_Status_Registers(&Reg1, 1) != HAL_OK) return(HAL_ERROR); if (W25Q_Read_Status_Registers(&Reg2, 2) != HAL_OK) return(HAL_ERROR); } return(HAL_OK); }
View more

 

Like I said, once the high order bit of SR1 (SRP) gets set, perhaps by other code you run, perhaps by the /WP pin state, it locks the part until power cycled. I've skimmed the data sheets a couple of times and don't have a clear read of exactly what is happening. Perhaps you can find a Winbond FAE to have a discussion with?

You can't change the status register if it's implicitly locked.

Perhaps you can switch out for a new part? And then tread more carefully, or identify where you're locking it up?

Watch that the memory IC is in the correct modes for the commands/methods being used to talk to it. Writing several megabytes in the wrong modes may result in patterns which are misinterpreted.

 

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

My SRL is low, SRP is high I will try pull up the WP pin with an external resistor. This is hardware unprotect, so i try reset the BP bits. Maybe. 

If i can't i will change to a new flash ic.

 

I used this flash ic at 120Mhz, so it was maybe go to wrong bit settings. I will set to 100Mhz.

I read it here:

https://community.st.com/t5/stm32-mcus-embedded-software/problem-with-nor-flash-w25q512-cannot-erase-sector-chip/td-p/665883

 

Thank you!