ide: the Atmel Studio solution master has, on the libavr port

master carries bootloader.atsln, so main does too. Two projects, because a
.cppproj is one binary at one flag set and this build has hundreds: the stock
328P pureboot loader (USART0 at 115200 on a 16 MHz crystal), and the tsb_asm
tier that occupies the same 512-byte section master's own tsb project targeted.
Both come out byte-identical to the Ninja build — 404 B and 510 B of .text —
in both configurations.

Debug keeps -Os and adds only -gdwarf-4. A loader's section is a correctness
bound, and -Og builds this source to 590 B: the link at 0x7e00 accepts that
without a diagnostic, 78 bytes past flash end, where rcall/rjmp wrap modulo
flash size and the image dies just after activation. Debug info costs no flash,
so the optimisation level stays where correctness needs it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-27 22:11:28 +02:00
parent af0dd15a77
commit 3ce817ea03
5 changed files with 337 additions and 1 deletions

78
ide/README.md Normal file
View File

@@ -0,0 +1,78 @@
# 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`** — 404 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 checked out **beside this repo**, found at
`$(MSBuildProjectDirectory)\..\..\..\libavr\include` — 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`. Pinning libavr as a submodule is the better answer and is on
libavr's task list.
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`.