Skip to content

atmega: add SPI host HAL for the ATmega328P - #1076

Draft
matpala wants to merge 8 commits into
ZigEmbeddedGroup:mainfrom
matpala:atmega/spi
Draft

matpala wants to merge 8 commits into
ZigEmbeddedGroup:mainfrom
matpala:atmega/spi

Conversation

@matpala

@matpala matpala commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

Adds a polled SPI host HAL for the ATmega328P (hals/atmega328p/spi.zig) and an example that reads the nRF24L01+ STATUS and CONFIG registers on the Emakefun RF-Nano V3.0.

Part of #1069. Depends on #1070 (the example prints over the UART); this branch includes its commits, and I'll rebase once it's merged.

  • Same shape as the wch SPI and the UART in atmega: add USART0 HAL for the ATmega328P #1070: boards export a spi_setup (only the CPU clock, since the pins are fixed) and the application passes the SCK frequency, CPOL/CPHA and bit order to apply.
  • The SCK divider is chosen at comptime: the fastest one that doesn't exceed the requested frequency, with a compile error below the slowest one. Host tests cover the divider selection and the rejected case; testing the compile error itself is left as a TODO (Proposal: testing @compileError ziglang/zig#513).
  • apply sets SCK, HODI and PB2 (the hardware SS) as outputs, since an SS input pulled low would switch the SPI into device mode. Chip select is left to the caller.
  • write_blocking, read_blocking and transceive_blocking return void and need exclusive access to the peripheral: they don't report write collisions (WCOL), and there are no timeouts yet since the port has no time source.

The generated peripherals.SPI can't be used directly: it's a pointer to address 0 (not allowzero) with absolute register offsets (#1072). The HAL points at each register through the generated types instead.

Tested on an RF-Nano V3.0: reading the radio returns STATUS=0x0E and CONFIG=0x08, its reset values, after both a warm and a cold start.

Blocking, polled USART0 driver with comptime baud rate selection (normal or U2X0, whichever has the lower error), configurable parity and stop bits (default 8N1), and a uart_echo example.

Reads use an out parameter because functions returning an error union with a non-void payload don't compile for AVR yet (ziglang/zig#37099). For the same reason there are no std.Io interfaces or std.log support yet.
@@ -0,0 +1,153 @@
//! SPI host for the ATmega328P (polling).
//!
//! SCK is PB5, HODI is PB3 and HIDO is PB4. PB2 is the peripheral's own SS

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use MOSI/MISO nomenclature in mz.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, renamed to MOSI/MISO in the HAL, the board docs and the RF-Nano pin map.

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.

2 participants