Skip to content

atmega: add driver adapters for the ATmega328P - #1098

Open
matpala wants to merge 3 commits into
ZigEmbeddedGroup:mainfrom
matpala:atmega/drivers
Open

matpala wants to merge 3 commits into
ZigEmbeddedGroup:mainfrom
matpala:atmega/drivers

Conversation

@matpala

@matpala matpala commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Part of #1069.

Adds hal.drivers for the ATmega328P, like port/wch/ch32v/src/hals/drivers.zig:

  • GPIO_Device(pin): Digital_IO for a pin. The pin is comptime because the GPIO functions use SBI/CBI. set_bias(.low) returns Unsupported (no pull-downs).
  • SPI_DatagramDevice(cs_pin): DatagramDevice on the SPI with an active-low CS, driven by connect/disconnect. init deselects the device before making CS an output.
  • ClockDevice: on hal.time. Pass it as is for static dispatch, or use clock_device() for the interface.

The spi_nrf24 example now uses them instead of its local adapters, and the clock is hal.time (Timer0) instead of a busy-loop clock. Everything is passed statically. With Zig 0.17.0 and ReleaseSmall, its flash size (avr-size text) goes from 1948 to 2416 bytes, with Timer0 replacing the busy-loop clock.

transceivev (#1077) is left for a follow-up.

DatagramDevice.read/readv through the vtable doesn't build on AVR with Zig 0.17.0 (zig#37099, fixed for 0.17.1); calling the adapter's readv directly works. Also, with Digital_IO through the interface the nRF24 driver calls memcpy on AVR (it copies self), which doesn't link; I'll look at that separately.

All atmega examples build, and the port tests, zig fmt and the linter pass. Tested between two RF-Nano boards with spi_nrf24: bytes arrive in both directions, and with the other board unplugged sends end with [no ACK].

@mattnite

Copy link
Copy Markdown
Contributor

The driver framework is supposed to give you the choice of dynamic dispatch or static dispatch.

What is the code size when you use static dispatch here? The increase in program size is notable. Also are you able to measure and compare the runtime overhead?

@matpala

matpala commented Oct 25, 2026

Copy link
Copy Markdown
Contributor Author

Measured on main with #1096 (drivers now built in ReleaseSmall), Zig 0.17.0. Flash size (avr-size text) of rf-nano-v3_spi_nrf24:

  • main, busy-loop clock: 1948 bytes
  • this PR as it was (SPI and CE static, clock through the interface): 3250 bytes
  • everything static: 2416 bytes

Most of the increase was the clock: clock_device() was the only option, so it always went through the vtable. I changed it to hal.drivers.ClockDevice, which can be passed as is or turned into the interface with .clock_device(), and the example now passes everything statically. It's still 468 bytes above main, with Timer0 replacing the busy-loop clock.

Runtime on the RF-Nano (16 MHz, SPI at 1 MHz), three runs of 1000 receive calls with an empty FIFO (one register read): 39.4 us per call static, 52.4 us with the SPI as a DatagramDevice, about 13 us (33%) more.

This branch has not been deployed

No deployments
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