The fixed-baud window counted down a uint32 where almost every window fits 24 bits; the countdown now takes avr::uint24_t when the poll budget allows (the autobaud budget's own choice), uint32 past 16.7M polls — four bytes off every fixed-baud image on every chip, the full suites green on the changed window. The README size table is refreshed — its autobaud column had also gone stale by the no-assembly pass's measurement-loop win, which nothing gated: sizes.py check-readme now runs as the gate's final stage, where every tree is freshly built and the table can actually be held. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
78 lines
3.8 KiB
Markdown
78 lines
3.8 KiB
Markdown
# Atmel Studio
|
||
|
||
`master` carries `bootloader.atsln`, so this branch does too: `ide/bootloader.atsln`
|
||
builds the loaders from the same sources Ninja does, to a **byte-identical
|
||
`.text`** — 400 B for the 328P pureboot loader, 510 B for the `tsb_asm` tier in
|
||
its 512-byte section. CMake remains the build system; the solution is here so the
|
||
port opens in Studio as its predecessor did.
|
||
|
||
## The two projects, and why two
|
||
|
||
pureboot is a chip × backend × clock × baud matrix — `pureboot_add_loader()`
|
||
resolves a deployment into compile definitions — and a `.cppproj` is one binary
|
||
at one set of flags, so a project can only ever be one point of it. `pureboot`
|
||
is that point: the stock 328P deployment, USART0 at 115200 on a 16 MHz crystal,
|
||
an 8-second activation window. `tsb_asm` is the TinySafeBoot tier that occupies
|
||
the same 512-byte section `master`'s `tsb` project targeted.
|
||
|
||
The other three tsb tiers (`tsb_pure`, `tsb_tricks`, `tsb_policy`) are not here.
|
||
They differ from `tsb_asm` in their source file, their section size, and — for
|
||
`tsb_policy` — two loop flags; nothing about that is a Studio concern, and what
|
||
they exist to demonstrate is a size gradient only the CMake size tests measure.
|
||
Adding one is a copy of `tsb_asm/tsb_asm.cppproj` in its own directory, with its
|
||
name, its GUID, its source path and its `--section-start` changed (`0x7c00` for
|
||
the 1 KiB tiers), plus four lines in the solution.
|
||
|
||
`avrdevice` is a project property, so each project gets its own directory:
|
||
Studio builds into `<project dir>/<Configuration>` whatever `OutputDirectory`
|
||
says, and two projects sharing a directory would share one object file.
|
||
|
||
## Debug keeps `-Os`
|
||
|
||
Both configurations compile at `-Os`; Debug adds only `-gdwarf-4`. The `.text`
|
||
is therefore identical in both, which is the point — a loader's section is a
|
||
**correctness** bound and not a budget. `-Og` builds this same source to 590 B,
|
||
and linking it at `--section-start=.text=0x7e00` on a 32 KiB part puts 78 bytes
|
||
past flash end **without a diagnostic**: `rcall`/`rjmp` targets there wrap
|
||
modulo flash size, so the image dies right after activation. A debug
|
||
configuration that silently produces that is worse than none, and DWARF costs no
|
||
flash, so the optimisation level stays where correctness needs it.
|
||
|
||
## What Studio needs from the machine
|
||
|
||
libavr from the **submodule**, found at
|
||
`$(MSBuildProjectDirectory)\..\..\libavr\include` — correct by construction, and
|
||
anchored to the project because a plain relative path resolves against the
|
||
generated makefile's directory (the configuration's output directory), not the
|
||
project's. There is no `LIBAVR_ROOT` escape hatch: a variable exported in a
|
||
shell is invisible to Studio launched from the Start menu, and the failure reads
|
||
as a missing `libavr/libavr.hpp` — which is what the submodule answers.
|
||
|
||
A GCC 16.1 toolchain registered as flavour `avr-g++-16.1.0`, nothing older
|
||
reaching `-std=c++26`.
|
||
|
||
## Generating and gating
|
||
|
||
One generated file is required before a project will load at all, and one command
|
||
per project checks the flags have not drifted (both from libavr's
|
||
`tools/atmelstudio/`):
|
||
|
||
```sh
|
||
for name in pureboot tsb_asm; do
|
||
python libavr/tools/atmelstudio/componentinfo.py \
|
||
"ide/$name/$name.componentinfo.xml" --device ATmega328P
|
||
python libavr/tools/atmelstudio/check-flags.py \
|
||
--solution ide/bootloader.atsln --project "$name" --target "$name" \
|
||
--compile-commands build/atmega328p-generated/compile_commands.json \
|
||
--log "build/as-$name.log"
|
||
done
|
||
```
|
||
|
||
`--project` because one reference describes one binary; `--target` because
|
||
`pureboot.cpp` is compiled by every point of the size matrix and the flags
|
||
differ per point, so the basename alone does not name a reference. Release is
|
||
what the gate compares — the presets define no debug build, and Debug differs
|
||
from Release only in `-gdwarf-4`.
|
||
|
||
Legacy (the yazoalfa-era submodules) stays on `master`.
|