2023-12-12 06:41 AM
Hello,
We encountered a problem with the internal Bootloader of the STM32G0B1KBU6 MCU.
Conditions
First, the option bytes are set with an STLINK-V3 programming adapter (SWD interface) and CubeProgrammer (2.15.0) according to Pattern 11 of AN2606:
nBoot_SEL => unchecked
nboot1 => checked
nboot0 => unchecked
Reproduction
1. In our product assembly process:
Initial programming of the user software is successful with STLINK-V3 Programming Adapter via SWD interface. Stm32flashtool is used to flash the controller at I2C address 0x5d. Pin PB6 and PB7 are used to access I2C bootloader.
2. Trying to reprogram the controller while testing:
Now, with the software already running on STM32G0B1KBU6 (verified) we go through the STM bootloader activation Pattern 11 (AN2606, Sec. 4.1) with pulling boot0 and reset low, then pulling boot0 and afterwards reset high.
Expected
3. MCU is reflashable via I2C bus.
Observed
3. As soon as the bootloader is addressed by an erase or flash command with the stm32flash tool, the level of I2C clock drops to zero permanently and communication with the MCU or other I2C devices is not possible.
Workarounds
The only workaround we have is hardware resetting the MCU after a power cycle while boot0 and reset pin are permanently set high. After a few erase and flash commands via I2C at address 0x5d, the memory flash is permanently erasable and flashable without breaking the I2C bus’s clock.
This problem also only occurred for 3 out of 10 boards. 7 MCUs are programmable while software is running.
Is there any known issue with I2C Bootloader similar to ours?
Thanks a lot in advance!
Solved! Go to Solution.
2024-02-06 06:16 AM
We have finally found the root of the problem. Pin 23 (PA12[PA10]), which is responsible for the DFU bootloader, was not defined up until now.
If this is set to GND via 10kOhm and a reset is carried out via the reset pin, the I2C clock can occasionally be reproduced. Presumably because the DFU bootloader is activated as a result? We did not assume that this pin plays a relevant role, as according to AN2606 it can only be activated by the following condition: "VDDUSB IO must be connected to 3.3 V as USB peripheral is used by the bootloader." If we set PA12 high using a pull-up resistor, the error no longer occurs.
2023-12-12 07:53 AM
Are you sure it's not just holding SCL low during the write/erase, then releasing afterward? That's expected behavior.
Use the no-stretch commands and poll for completing if your master doesn't like this.
2023-12-12 11:24 PM
Hi TDK,
unfortunately the SCL is not released after write/erase command in our observed behaviour. SCL stays low without recovering unless the hardware is reset by a power cycle. Nonetheless we'll try out the no-stretch commands.
2023-12-13 06:48 AM
Hello again,
even non-stretch commands (non-stretch memory erase command) drop the SCL to zero without recovering. SCL stays low, when master is disconnected. Here are 2 pictures of the signals captured with an oscilloscope. First picture shows an successful erase (workaround), second picture shows the SCL failure of non-stretch memory erase command.
blue -> boot0 pin, red -> reset pin , yellow -> I2C SCL, green -> I2C SDA
2023-12-18 08:22 AM
It is definitely an error case caused by the microcontroller. As soon as SCL is broken by reading/writing at address 0x5d and the master is removed, it does not recover. The Clock only recovers after a power cycle. Even if a read command (i2cget) is sent to bootloader address 0x5d (after reset + boot0 pin to high), the clock collapses as shown in the oscilloscope image.
2023-12-18 09:19 AM
How hw sw you use as master? First clk pulse isnt ideal
2023-12-18 10:33 AM
Okay, so SCL is being stretched on the next command. Can you show the full transaction, starting with NRST rising edge?
Not saying there isn't an issue, but the plot you've shown only shows that clock stretching is happening which isn't an issue in itself.
A non-stretch memory command requires polling for an ACK byte before the next command is sent, which isn't shown.
> then pulling boot0 and afterwards reset high.
Are you driving NRST high or putting it in high-impedance mode? If you're driving it high, that could be a problem as the chip can't reset itself.
2023-12-19 12:04 AM
The clock stretching begins even with no-stretch commands. The erase fail.png attached is captured after sending the first two bytes. I use i2ctransfer command to send these two bytes to address 0x5d as follows:
i2ctransfer 1 w2@0x5d 0x45 0xBA
As I said, the clock is not recovering unless a Power Cycle is done. If clock stretching is enabled, shouldn't it recover at some point?
The bootloader is enabled by pulling mcu reset low, putting boot0 on high, then releasing reset pin. This is all done by an GPIO-Extender, which is also addressed by I2C. See pictures underneath.
2023-12-19 12:08 AM
For debugging I use I2C-tools of a Raspberry Pi 3. It is wired to the I2C-line of the PCB, which makes the signal not that gorgeous.
2023-12-19 06:22 AM
When i good understand you comm on one bus with expander and with bootloader , this maybe isnt problem because last expander traffic is unreset an hold boot high. But is RPI i2ctransfer right way to controll loader?
Why you choice I2C? Good is test with usb to i2c and
Cube\STM32CubeProgrammer\bin\STM32_Programmer_CLI.exe"
-------------------------------------------------------------------
STM32CubeProgrammer v2.10.0
-------------------------------------------------------------------
Usage :
STM32_Programmer_CLI.exe [command_1] [Arguments_1][[command_2] [Arguments_2]...]
Generic commands:
-?, -h, --help : Show this help
-c, --connect : Establish connection to the device
<port=<PortName> : Interface identifier. ex COM1, /dev/ttyS0, usb1,
JTAG, SWD...)
USB port optional parameters:
[sn=<serialNumber>] : Serial number of the usb dfu
[PID=<Product ID>] : Product ID. ex: 0xA38F, etc, default 0xDF11
[VID=<Vendor ID>] : Vendor ID. ex: 0x0389, etc, default x0483
UART port optional parameters:
[br=<baudrate>] : Baudrate. ex: 115200, 9600, etc, default 115200
[P=<parity>] : Parity bit, value in {NONE,ODD,EVEN}, default EVEN
[db=<data_bits>] : Data bit, value in {6, 7, 8} ..., default 8
[sb=<stop_bits>] : Stop bit, value in {1, 1.5, 2} ..., default 1
[fc=<flowControl>] : Flow control
Value in {OFF,Hardware,Software} ..., default OFF
rts=<status> : low or high
dtr=<status> : low or high
Not supported for STM32MP
[noinit=noinit_bit]: Set No Init bits, value in {0,1} ..., default 0
[console] : Enter UART console mode
JTAG/SWD debug port optional parameters:
[freq=<frequency>] : Frequency in KHz. Default frequencies:
4000 SWD 9000 JTAG with STLINKv2
24000 SWD 21333 with STLINKv3
[index=<index>] : Index of the debug probe. default index 0
[sn=<serialNumber>]: Serial Number of the debug probe
[ap=<accessPort>] : Access Port index to connect to. default ap 0
[mode=<mode>] : Connection mode. Value in {UR/HOTPLUG/NORMAL/POWERDOWN}
default mode: NORMAL
[reset=<mode>] : Reset modes: SWrst/HWrst/Crst. Default mode: SWrst
Reset mode with UR connection mode is HWrst
[shared] : Enable shared mode allowing connection of two or more
instances of STM32CubeProgrammer or other debugger
to the same ST-LINK probe.
[tcpport=<Port>] : Port used for running ST-Link Server, default 7184
[LPM] : Enable debug in Low Power mode(default mode)
[dLPM] : Disable debug in Low Power mode
[getAuthID] : Get device identification (Option only for STM32U5 series)
[speed=<Reliable/fast>]: Choose flashing Reliable/fast (Option only for STM32U5 series)
SPI port optional parameters:
[br=<baudrate>] : Baudrate.
[cpha=<cpha_val>] : 1Edge or 2Edge. default 1Edge
[cpol=<cpol_val>] : low or high
[crc=<crc_val>] : enable or disable (0/1).
[crcpol=<crc_pol>] : crc polynom value.
[datasize=<size>] : 8bit/16bit
[direction=<val>] : Direction: 2LFullDuplex/2LRxOnly/1LRx/1LTx
[firstbit=<val>] : First Bit: MSB/LSB
[frameformat=<val>]: Frame Format: Motorola/TI
[mode=<val>] : Mode: master/slave
[nss=<val>] : NSS: soft/hard
[nsspulse=<val>] : NSS pulse: Pulse/NoPulse
[delay=<val>] : Delay: Delay/NoDelay, delay of few microseconds
[noinit=noinit_bit]: Set No Init bits, value in {0,1} ..., default 0
CAN port optional parameters:
[br=<rbaudrate>] : Baudrate : 125, 250, 500, 1000 Kbps, default 125
[mode=<canmode>] : CAN Mode : NORMAL, LOOPBACK..., default NORMAL
[ide=<type>] : CAN Type : STANDARD or EXTENDED, default STANDARD
[rtr=<format>] : Frame Format: DATA or REMOTE, default DATA
[fifo=<afifo>] : Msg Receive : FIFO0 or FIFO1, default FIFO0
[fm=<fmode] : Filter Mode : MASK or LIST, default MASK
[fs=<fscale>] : Filter Scale: 16 or 32, default 32
[fe=<fenable>] : Filter Activation : ENABLE or DISABLE, default ENABLE
[fbn=<fbanknb>] : Filter Bank Number : 0 to 13, default 0
[noinit=noinit_bit]: Set No Init bits, value in {0,1} ..., default 0
I2C port optional parameters:
[add=<ownadd>] : Slave address : address in hex format
[br=<sbaudrate>] : Baudrate : 100 or 400 Kbps, default 400
[sm=<smode>] : Speed Mode : STANDARD or FAST, default FAST
[am=<addmode>] : Address Mode : 7 or 10 bits, default 7
[af=<afilter>] : Analog filter : ENABLE or DISABLE, default ENABLE
[df=<dfilter>] : Digital filter : ENABLE or DISABLE, default DISABLE
[dnf=<dnfilter>] : Digital noise filter : 0 to 15, default 0
[rt=<rtime>] : Rise time : 0-1000(STANDARD), 0-300(FAST), default 0
[ft=<ftime>] : Fall time : 0-300 (STANDARD), 0-300(FAST), default 0
[noinit=noinit_bit]: Set No Init bits, value in {0,1} ..., default 0
here you can see all params usable with I2C or other ...