From 3899e8ef40772882bee62aa0ef6d6c15fba92747 Mon Sep 17 00:00:00 2001 From: BlackMark Date: Fri, 24 Jul 2026 17:22:48 +0200 Subject: [PATCH] pureboot: release a USART left enabled on the software link's pins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A software or autobaud link on a USART's own pins (PD0/PD1 on the mega328P, so the Uno's USB bridge reaches it) was mute after an application handed over with that USART still enabled: its TXEN keeps the USART owning the TX pin, so the bit-banged transmitter cannot drive it — the loader locked and obeyed commands but never answered. The link's init now clears the UCSRnB of the USART whose TXD is its TX pin. Guarded with if constexpr on that pin match, so a link on non-USART pins emits nothing: +4 bytes on a USART-pin build (494 of 512 for the mega328P autobaud), zero on the default pb0/pb1 matrix. Co-Authored-By: Claude Opus 4.8 (1M context) --- pureboot/pureboot.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/pureboot/pureboot.cpp b/pureboot/pureboot.cpp index dab1429..7881008 100644 --- a/pureboot/pureboot.cpp +++ b/pureboot/pureboot.cpp @@ -166,6 +166,27 @@ constexpr char usart_digit = '0' + PUREBOOT_USART; constexpr char usart_digit = '0'; #endif +// Release a hardware USART the application may have left enabled onto a +// bit-banged link's pins. A software transmitter drives its TX pin through the +// port register, but while that USART's TXEN is set the USART owns the pin and +// the port write does nothing — the loader would receive and obey yet never +// answer. Writing UCSRnB zero hands the pin back to the port. Guarded on the +// pin actually being a USART's TXD, so a link on non-USART pins emits nothing. +template +[[gnu::always_inline]] inline void release_usart_on() +{ + if constexpr (avr::uart::has_usart()) + if constexpr (avr::uart::detail::usart_pin("TXD") == Tx) + avr::hw::reg_impl()>::write(0); +} + +template +[[gnu::always_inline]] inline void release_usarts_on() +{ + release_usart_on<'0', Tx>(); + release_usart_on<'1', Tx>(); +} + template struct hardware_link { using uart = avr::uart::usart; @@ -212,6 +233,7 @@ struct software_link { static void init() { avr::init(); + release_usarts_on(); } static bool pending() @@ -245,6 +267,7 @@ struct autobaud_link { static void init() { avr::init(); + release_usarts_on(); } static std::uint8_t rx()