pureboot: release a USART left enabled on the software link's pins
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) <noreply@anthropic.com>
This commit is contained in:
@@ -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 <char Inst, avr::io::pin Tx>
|
||||
[[gnu::always_inline]] inline void release_usart_on()
|
||||
{
|
||||
if constexpr (avr::uart::has_usart<Inst>())
|
||||
if constexpr (avr::uart::detail::usart_pin<Inst>("TXD") == Tx)
|
||||
avr::hw::reg_impl<avr::uart::detail::ureg<Inst, "UCSR#B">()>::write(0);
|
||||
}
|
||||
|
||||
template <avr::io::pin Tx>
|
||||
[[gnu::always_inline]] inline void release_usarts_on()
|
||||
{
|
||||
release_usart_on<'0', Tx>();
|
||||
release_usart_on<'1', Tx>();
|
||||
}
|
||||
|
||||
template <avr::hertz_t C, avr::baud_t B>
|
||||
struct hardware_link {
|
||||
using uart = avr::uart::usart<usart_digit, C, {.baud = B, .max_baud_error = 2.5_pct}>;
|
||||
@@ -212,6 +233,7 @@ struct software_link {
|
||||
static void init()
|
||||
{
|
||||
avr::init<rx_t, tx_t>();
|
||||
release_usarts_on<avr::PUREBOOT_TX>();
|
||||
}
|
||||
|
||||
static bool pending()
|
||||
@@ -245,6 +267,7 @@ struct autobaud_link {
|
||||
static void init()
|
||||
{
|
||||
avr::init<uart>();
|
||||
release_usarts_on<avr::PUREBOOT_TX>();
|
||||
}
|
||||
|
||||
static std::uint8_t rx()
|
||||
|
||||
Reference in New Issue
Block a user