Skip to content

atmega: add opt-in Timer0 time HAL for ATmega328P - #1087

Merged
mattnite merged 2 commits into
ZigEmbeddedGroup:mainfrom
matpala:atmega/time
Oct 14, 2026
Merged

mattnite merged 2 commits into
ZigEmbeddedGroup:mainfrom
matpala:atmega/time

Conversation

@matpala

@matpala matpala commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

Adds hal.time for the ATmega328P using Timer0. Part of #1069; the timer is opt-in, as discussed there.

  • Provides init, get_time_since_boot, sleep_ms and sleep_us. Time is measured from init.
  • Timer0 runs in normal mode with a /64 prescaler. Its overflow interrupt extends the count to 64 bits.
  • The application registers hal.time.timer0_overflow for TIMER0_OVF, calls init and enables interrupts. init checks the handler registration at compile time. AVR does not use HAL default_interrupts, so registration is explicit. Without initialization, Timer0 remains available for PWM on D5/D6.
  • The CPU frequency comes from the board at compile time. Each tick must span a whole power-of-two number of microseconds: 4 µs at 16 MHz or 8 µs at 8 MHz. Unsupported frequencies produce a compile error. Includes host tests for find_us_per_tick.
  • Reads preserve the interrupt state and account for a pending overflow by rereading TCNT0. Sleeps busy-wait with an extra tick of margin; sleep_ms uses 1 ms chunks to avoid runtime 64-bit multiplication. Sleeps require interrupts enabled. The overflow handler must run within one overflow period: 1.024 ms at 16 MHz or 2.048 ms at 8 MHz.
  • Adds blinky_time for the Nano, Pro Mini 3.3 V and RF-Nano V3.

Hardware-tested on an Emakefun RF-Nano V3.0 (16 MHz) and an Arduino Pro Mini 3.3 V (8 MHz). The example toggles the LED with sleep_ms(500) between toggles. On each board, I counted 60 LED turn-ons over a manually timed 60-second interval.

Inspected the example ELFs: vector 16 points to the Timer0 overflow handler, which returns with reti, and no compiler_rt helpers are linked.

Comment thread port/microchip/atmega/src/hals/atmega328p/time.zig Outdated
Comment thread port/microchip/atmega/src/hals/atmega328p/time.zig Outdated
Comment thread port/microchip/atmega/src/hals/atmega328p/time.zig Outdated
Comment thread port/microchip/atmega/src/hals/atmega328p/time.zig Outdated
Comment thread port/microchip/atmega/src/hals/atmega328p/time.zig Outdated
Comment thread port/microchip/atmega/src/hals/atmega328p/time.zig Outdated
@mattnite

mattnite commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Wait so you sat there for an entire minute counting the number of times the LED blinked?

@matpala

matpala commented Oct 13, 2026

Copy link
Copy Markdown
Contributor Author

Guilty. Most suspenseful minute of my week :) It only catches gross errors though (a wrong prescaler or tick size is 2x off), so I measured it properly too.

A test firmware prints get_time_since_boot() over UART every 10 s, and a script fits those values against the host clock as each line arrives (the host clock agrees with Windows' NTP-synced clock to about 4 ppm). To tell lost ticks apart from the board's oscillator, a second firmware counts Timer0 overflows by polling TOV0 with interrupts off, without hal.time. A lost overflow would make hal.time run slower than the polling count.

Board hal.time (10 min) Polling, no interrupts (5 min)
RF-Nano V3.0, 16 MHz −1893 ppm −1889 ppm
Pro Mini 3.3 V, 8 MHz −3844 ppm −3878 ppm

Both methods agree on each board, so hal.time doesn't lose overflows; the error is each board's oscillator (0.19% and 0.38% slow, typical of ceramic resonators). The remaining differences are small and in the opposite direction from lost ticks; most likely the oscillator drifting with temperature between runs.

Happy to share the firmware and the script if they're useful.

@mattnite

Copy link
Copy Markdown
Contributor

How much of that comment was generated by an LLM?

@matpala

matpala commented Oct 13, 2026

Copy link
Copy Markdown
Contributor Author

I usually use LLMs to help write my comments, as I'm not very good at writing in English. I ran the tests and measurements myself on both boards, and the numbers are copied from the output.
Happy to keep replies shorter and plainer if you prefer.

@Grazfather

Copy link
Copy Markdown
Collaborator

Yeah we know you're working with an LLM. That is fine (imo), as long as you're not doing drive-by slop PRs. These have been rather good quality, and you've been testing on hardware (which is important)

@mattnite

Copy link
Copy Markdown
Contributor

That's okay, but honestly I'd prefer you use the language you're most comfortable with. It puts a little more work on us having to put it through a translator, but I'd rather read a translation of how you express yourself over a machine talking for you.

@mattnite
mattnite merged commit b3e605b into ZigEmbeddedGroup:main Oct 14, 2026
37 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants