cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G071RB MCU bricked/unresponsive after attempting firmware update via I2C

ShivamSpintly
Associate II

I was attempting a STM32 firmware update over the I2C interface using some other host MCU. For this, I used the NUCLEO-G071RB; so I referred to the ST's AN4221 and implemented their firmware update flow.

I configured the option bytes using STM32CubeProgrammer so that the STM32 bootloader can be accessed using the BOOT0 pin instead. I had already implemented their UART firmware update flow and I had got it working without any issues. But now our product needs to perform the firmware over I2C instead. So I made the necessary changes so that the host MCU uses the I2C interface instead of UART to communicate with the STM32 bootloader.

0693W00000Sv7tdQAB.png 

As mentioned in their AN2606, I used 0x51 as the slave address for STM32G071RB bootloader. Also instead of using their old UART commands, I switched to their I2C No-Stretch commands (so as to avoid clock stretching while communicating via I2C). I was able to successfully communicate with the STM32 bootloader. I sent the "Get ID" (0x02) command to the bootloader and I received an ACK and was also to fetch the Chip ID (0x460).

Now coming to the issue:

Once I was able to fetch the Chip ID, I sent the "No-Stretch Readout Unprotect" (0x93) command and I received the ACK byte (0x79) for that command. Now I waited for the 2nd ACK (which would be received once the STM32 disables the readout protection and performs mass erase on the entire flash memory).

0693W00000Sv7ubQAB.png 

dfu_status_e wait_for_response (void)
{
    uint8_t rcvd_data = BUSY;
    while (rcvd_data == BUSY)
    {
        receive_data(&rcvd_data, 1);
    }
 
    if (rcvd_data == ACK)
    {
        return DFU_OK;
    }
    else if (rcvd_data == NACK)
    {
        return DFU_NACK;
    }
    else
    {
        return DFU_UNKNOWN;
    }
}

So I kept polling until I was receiving the BUSY byte (0x76) and waited for the ACK (0x79). But I never received the ACK, the MCU kept receiving the BUSY byte atleast for 40 seconds while in the STM32G071RB datasheet the mass erase time is mentioned to be just 40.1 ms.

0693W00000Sv7vAQAR.pngSince the program execution was stuck for quite a long time, I reset the whole system. Then I tried the whole thing yet again, but this time the bootloader completely stopped responding to the I2C commands. It stopped giving an ACK (the 9th bit) on the slave address itself. I suspected something was wrong with the MCU since it was working fine before.

0693W00000Sv7w8QAB.png 

So I tried communicating with STM32G071RB using STM32CubeProgrammer (over ST-LINK) but it started throwing this Error: No STM32 target found. I then checked the FAIL.TXT file, it said "The interface firmware FAILED to reset/halt the target MCU". I suspected that the STM32's user application might be corrupted and that might be blocking the ST-LINK SWD pins so I configured the STM32CubeProgrammer (changed the Mode from Normal to Under Reset) so that it can initiate the communication with the STM32 MCU just after it has come out of reset but that didn't work either. It returned the same Error: No STM32 target found. I tried the same thing by manually resetting the MCU as well as forcing the MCU into the system memory (bootloader) whenever it comes out of reset (by tieing the BOOT0 pin high) but even that didn't work. I also tried using the UART interface but none of the things worked.

I found this under the Flash option byte programming section (in STM32G0x1 reference manual). Could it be that I might've corrupted the option bytes, since I was trying to write the RDP bits in the option bytes (by issuing the Readout Unprotect command through the bootloader).

0693W00000Sv84vQAB.png 

It says that it erases the user option bytes and rewrites it in the next cycle by fetching the previous values from the option registers along with the option change that the user requested. So is it possible that I might've bricked the device by resetting the MCU while it was performing the mass erase and also changing the RDP option (although I waited for atleast 40s before doing so) or is the MCU damaged because of some other reasons? Also if such a scenario can permanently brick the device, then how should we handle this case in production where one can't be sure about power outage during the firmware update?

3 REPLIES 3
GwenoleB
ST Employee

Hello @Community member​,

Indeed it seems that you corrupted the option bytes. Just to understand how exactly what happened, can you confirm you followed the Option Bytes programming sequence to disable the RDP?

From your explanation, you never mentioned an OBL_Launch or POR to disable RDP.

While any OBL_Lauch or POR is performed, option bytes are not loading. Moreover the reset has to be properly perform to avoid any glitch on reset line and corrupt option bytes register. Any corruption induces a mismatch which actually enable the BOOT_LOCK and RDP level 1. Then, the device is permanently lock. There is no way back.

Best Regards,

Gwénolé

Thanks for responding.

Since you asked, I didn't write any application code to program the option bytes so I didn't have to follow any programming sequence. I tried programming the option bytes via the STM32's proprietary boot loader instead. I sent the Readout Unprotect command to the STM32 boot loader to disable the Readout protection as mentioned in the application note AN4221.

Hello @Gwenole BROCHARD​ 

Any update on this? Just to clear it up again; I tried programming the option bytes through the STM32's boot loader and not through my own application. Is it possible for them to get corrupted this way and end up with the device getting bricked?