florisla / stm32loader

Flash firmware to STM32 microcontrollers using Python.
GNU General Public License v3.0
111 stars 55 forks source link

Stray null byte botches bootloader procedure #46

Closed Maldus512 closed 2 years ago

Maldus512 commented 4 years ago

I am trying to flash firmware onto an STM32F413 powered custom board through the UART1 bootloader. It appears that on system reset via the DTR line my MCU fires off a null (0x00) byte that prevents any bootloading tool I've tried so far (stm32loader, st-flash, STMCubeProgrammer) from succeeding.

With your Python module I could slightly bend the procedure and find out the issue. A temporary solution was to flush the input FIFO of the serial port right after resetting the MCU:

def reset_from_system_memory(self):
        """Reset the MCU with boot0 enabled to enter the bootloader."""
        self._enable_boot0(True)
        self._reset()

        ### Reset the input buffer to avoid reading noise
        self.connection.serial_connection.reset_input_buffer() # <------

        # Try the 0x7F synchronize that selects UART in bootloader mode
        # (see ST application notes AN3155 and AN2606).
        # If we are right after reset, it returns ACK, otherwise first
        # time nothing, then NACK.
        # This is not documented in STM32 docs fully, but ST official
        # tools use the same algorithm.
        # This is likely an artifact/side effect of each command being
        # 2-bytes and having xor of bytes equal to 0xFF.

        for attempt in range(self.SYNCHRONIZE_ATTEMPTS):
            if attempt:
                print("Bootloader activation timeout -- retrying", file=sys.stderr)
            self.write(self.Command.SYNCHRONIZE)
            read_data = bytearray(self.connection.read())

            if read_data and read_data[0] in (self.Reply.ACK, self.Reply.NACK):
                # success
                return

        # not successful
        raise CommandError("Bad reply from bootloader")

Would it be worth to integrate this behavior with a pull request? I realize this might as well be an issue with my custom hardware, but it shouldn't do any harm to throw away any received character before the bootloader synchronization has even begun. I can also see that this fix breaks the abstraction of the SerialConnection object; should I add another method to "flush" incoming input?

florisla commented 4 years ago

Hi,

This seems like to be the same issue as #48. Are you by any chance using a CP2102N UART adapter, at high speeds?

A pull request would be appreciated, yes. A 'flush_input' method on SerialConnection sounds perfect.

florisla commented 2 years ago

This is now implemented in c018d70e3498ce4196cd73e592e2a894c00abdb2 .