pureboot: the detail reaches become the library's own API
The three things this repo took from under libavr's counter are now over it, and the local copies fold away. The USART release on a software link's pins is the library's init contract (its guard here becomes a deletion, byte-identical images held by the gate); the WDRF routing test is power::peek_reset_cause().watchdog instead of a hand lookup of the flag's register; the tsb tiers' baud arithmetic is the public solver. libavr pin advances over those three additions. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2
libavr
2
libavr
Submodule libavr updated: 26b80e262d...911a87538f
@@ -38,13 +38,6 @@ using dev = avr::device<{.clock = avr::hertz_t{PUREBOOT_CLOCK_HZ}}>;
|
||||
constexpr avr::baud_t wire_baud{PUREBOOT_BAUD};
|
||||
#endif
|
||||
|
||||
// The watchdog reset flag's home: MCUSR, or the classic megas' MCUCSR.
|
||||
consteval std::int16_t wdrf_field()
|
||||
{
|
||||
auto reg = std::string_view{avr::hw::db.regs[static_cast<std::size_t>(avr::power::detail::reset_reg())].name};
|
||||
return avr::hw::db.field_index(reg, "WDRF");
|
||||
}
|
||||
|
||||
// The loader owns the top 512 bytes; a staging copy goes in the slot below.
|
||||
// Chips without a hardware boot section — the tinies and the m48s, whose SPM
|
||||
// runs from anywhere (Atmel-8271 §26) — keep the application's relocated
|
||||
@@ -174,27 +167,6 @@ 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}>;
|
||||
@@ -241,7 +213,6 @@ struct software_link {
|
||||
static void init()
|
||||
{
|
||||
avr::init<rx_t, tx_t>();
|
||||
release_usarts_on<avr::PUREBOOT_TX>();
|
||||
}
|
||||
|
||||
static bool pending()
|
||||
@@ -275,7 +246,6 @@ struct autobaud_link {
|
||||
static void init()
|
||||
{
|
||||
avr::init<uart>();
|
||||
release_usarts_on<avr::PUREBOOT_TX>();
|
||||
}
|
||||
|
||||
static std::uint8_t rx()
|
||||
@@ -498,7 +468,7 @@ void fill_page(std::uint8_t bank, std::uint16_t at)
|
||||
#endif
|
||||
// A watchdog reset belongs to the application, whose watchdog stays forced
|
||||
// on until it clears WDRF — no activation window in its way.
|
||||
if (avr::hw::field_impl<wdrf_field()>::test())
|
||||
if (avr::power::peek_reset_cause().watchdog)
|
||||
run_app();
|
||||
|
||||
link::init();
|
||||
|
||||
@@ -65,7 +65,7 @@ constexpr std::uint8_t comm_window = 200;
|
||||
constexpr std::uint16_t build_date = 26 * 512 + 7 * 32 + 20;
|
||||
|
||||
// Fixed 115200 8N1; the library solves UBRR + U2X from clock and baud.
|
||||
constexpr auto baud = avr::uart::detail::solve_baud(16_MHz, 115200_Bd);
|
||||
constexpr auto baud = avr::uart::solve_baud(16_MHz, 115200_Bd);
|
||||
|
||||
// The 16-byte device-info block, streamed out on activation.
|
||||
// clang-format off
|
||||
|
||||
@@ -200,7 +200,7 @@ extern "C" [[noreturn]] void tsb_app(); // the application's reset vector: --def
|
||||
// only the divisor low byte and U2X0 need a store. The solver still does
|
||||
// the datasheet work; the asserts pin the reset-state assumptions.
|
||||
{
|
||||
constexpr auto sol = avr::uart::detail::solve_baud(dev::clock, 115200_Bd);
|
||||
constexpr auto sol = avr::uart::solve_baud(dev::clock, 115200_Bd);
|
||||
static_assert(sol.u2x && sol.ubrr < 256, "lean bring-up writes UBRR0L only, with U2X0");
|
||||
avr::hw::reg<"UBRR0">::write(static_cast<std::uint8_t>(sol.ubrr));
|
||||
avr::hw::ucsr0a::write(avr::hw::ucsr0a::u2x0(1));
|
||||
|
||||
@@ -65,7 +65,7 @@ constexpr std::uint8_t comm_window = 200;
|
||||
constexpr std::uint16_t build_date = 26 * 512 + 7 * 32 + 20;
|
||||
|
||||
// Fixed 115200 8N1; the library solves UBRR + U2X from clock and baud.
|
||||
constexpr auto baud = avr::uart::detail::solve_baud(16_MHz, 115200_Bd);
|
||||
constexpr auto baud = avr::uart::solve_baud(16_MHz, 115200_Bd);
|
||||
|
||||
// The 16-byte device-info block, streamed out on activation.
|
||||
// clang-format off
|
||||
|
||||
Reference in New Issue
Block a user