W25Q256 write protection
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-09-10 5:26 AM
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(®1, 1) != HAL_OK) {
return HAL_ERROR;
}
if (W25Q_Read_Status_Registers(®2, 2) != HAL_OK) {
return HAL_ERROR;
}
if (W25Q_Read_Status_Registers(®3, 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;
}
- Labels:
-
QSPI
-
STM32H7 Series
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-09-10 6:17 AM
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.
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-09-10 7:11 AM
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-09-10 7:57 PM
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-09-11 2:52 AM
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 *)®_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);
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-09-11 9:35 AM - edited ‎2024-09-11 9:37 AM
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.
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2024-09-11 11:01 AM
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:
Thank you!
