The submodule replaces FetchContent and the unpinned forge fallback; LIBAVR_ROOT stays as the tandem-development override, the presets take the toolchain file from the submodule, and the Studio project's include path anchors there — correct by construction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
76 lines
3.4 KiB
Markdown
76 lines
3.4 KiB
Markdown
# ds3231
|
|
|
|
Maxim DS3231 RTC driver on [libavr](https://git.blackmark.me/avr/libavr):
|
|
clock and alarm read/write, alarm interrupts, oscillator-stop detection,
|
|
die temperature. One source runs on every libavr chip — TWI hardware on
|
|
the mega328P, open-drain software I2C on the tinies. All bus errors
|
|
surface as `std::expected`.
|
|
|
|
```cpp
|
|
using bus = dev::i2c<{.frequency = 100_kHz}>;
|
|
using rtc = ds3231::device<bus>;
|
|
|
|
auto now = rtc::read_clock(); // result<date_time>
|
|
(void)rtc::set_alarm1({}, ds3231::alarm1_rate::once_per_second);
|
|
```
|
|
|
|
`example/main.cpp` is the full tour. libavr rides as the `libavr/` submodule,
|
|
pinned to the commit this driver builds against; `LIBAVR_ROOT` (cache or
|
|
environment) overrides it for development against a working tree:
|
|
|
|
```sh
|
|
git submodule update --init libavr
|
|
cmake --preset attiny85-generated
|
|
cmake --build --preset attiny85-generated
|
|
```
|
|
|
|
Presets cover attiny85/atmega328p in both libavr modes (generated and
|
|
reflect). The legacy yazoalfa-based driver lives on the `master` branch.
|
|
|
|
## Atmel Studio
|
|
|
|
`master` carries a Studio solution, so this branch does too: `ide/ds3231.atsln`
|
|
builds `example/main.cpp` for both parts the presets cover, each to a
|
|
**byte-identical `.text`** against the CMake build — 1242 B on the ATmega328P,
|
|
1212 B on the ATtiny85 — with the flags mirrored by hand. CMake remains the
|
|
build system.
|
|
|
|
`avrdevice` is a project-level property in Studio, so a part means a project, not
|
|
a configuration: `ide/atmega328p/` and `ide/attiny85/`. They need separate
|
|
directories rather than separate names — Studio builds into `<project
|
|
dir>/<Configuration>` whatever `OutputDirectory` says, so two projects sharing
|
|
one directory would also share one `example/main.o`, and building one after the
|
|
other without a rebuild would link the other part's object.
|
|
|
|
Studio finds libavr in the **submodule** at
|
|
`$(MSBuildProjectDirectory)\..\..\libavr\include` — correct by construction,
|
|
and anchored to the project because a plain relative path is resolved 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 — which is what the
|
|
submodule answers. It also needs a GCC 16.1 toolchain registered as flavour
|
|
`avr-g++-16.1.0`, nothing older reaching `-std=c++26`.
|
|
|
|
One generated file is required before the project will load, and one command
|
|
checks the flags have not drifted (both from libavr's `tools/atmelstudio/`):
|
|
|
|
```sh
|
|
for mcu in atmega328p attiny85; do
|
|
case $mcu in atmega328p) device=ATmega328P;; attiny85) device=ATtiny85;; esac
|
|
python libavr/tools/atmelstudio/componentinfo.py \
|
|
"ide/$mcu/ds3231-$mcu.componentinfo.xml" --device "$device"
|
|
python libavr/tools/atmelstudio/check-flags.py --solution ide/ds3231.atsln \
|
|
--project "ds3231-$mcu" \
|
|
--compile-commands "build/$mcu-generated/compile_commands.json" \
|
|
--log "build/as-$mcu.log"
|
|
done
|
|
```
|
|
|
|
One reference describes one part, hence `--project`. Release is what the gate
|
|
compares, the presets defining no debug build; Debug carries the `-Og
|
|
-gdwarf-4` pair libavr's own debug preset uses.
|
|
|
|
Differences from legacy: weekday-rate alarms now actually set the DY bit
|
|
(the old `setAlarmHelper` always cleared it), reads/writes are single
|
|
coherent bus transactions, and errors are reported instead of ignored.
|