Building against cutting edge avr-libc on Mac
Introduction
The new ATtiny chips feature enhanced performance parameters including up to 32 KB of flash memory and up to 2 KB of RAM. These microcontrollers operate at clock speeds up to 20 MHz and include support for the Universal Serial Interface, which allows for I2C, SPI, and UART configurations. Importantly, they feature improved 12-bit ADCs, 10-bit DACs for better analog performance, and the capability to operate at a voltage range of 1.8V to 5.5V, making them highly adaptable for various power supply conditions. Some models also include a built-in hardware multiplier, which facilitates faster calculations for control applications. Additionally, the new ATtiny series maintain compatibility with the AVR instruction set and can be programmed via UPDI for straightforward development and debugging.
However, tooling for them is not yet straightforward - avr-libc supports them only in the main branch, and a lot of people are waiting for the next release which seems to have stalled sadly.
Getting avr-libc ‘main’ branch working on OSX
This was complicated, until I figured it out. Once I’d figured it out it was - as is usual - easy.
Setting up the latest avr-libc
from the main branch involves a few steps but is straightforward once you understand the process. First, ensure that you have Homebrew installed, as it will be used to install avr-gcc
.
Install Dependencies
Install avr-gcc
, which includes avr-binutils
and a version of avr-libc
, using Homebrew:
brew install avr-gcc
(Un)helpfully, the maintainers upstream include a version of avr-libc into the directory that this installs into, which the linker etc will want to use.
If you installed the default version (9) then you will have a directory here, until the minor version number changes.
/opt/homebrew/Cellar/avr-gcc@9/9.4.0_1
You can find out where it was installed by running
brew info avr-gcc
We then need to build and install the current version of avr-libc. This is probably a stop gap solution, until the next version is released.
The build process for avr-libc is documented at https://www.nongnu.org/avr-libc/user-manual/install_tools.html.
To wit, run these commands:
mkdir ~/src/avr/ && cd ~/src/avr # Create and change to the directory where avr-libc will be cloned
export PREFIX=$HOME/local/avr # Set installation prefix
git clone https://github.com/avrdudes/avr-libc.git # Clone the latest avr-libc from the repository
cd avr-libc
The following will run configure with the appropriate arguments, installing it into the local home directory.
./configure --prefix=$PREFIX --build=`./config.guess` --host=avr
make && make install # Compile and install
Now we have it installed ok, let’s go to the directory that brew installed files to, and overwrite the installed version via a symlink to our new install:
cd /opt/homebrew/Cellar/avr-gcc@9/9.4.0_1
mv avr avr.orig # Backup original AVR library
ln -sf $PREFIX/avr avr # Create symlink to new library
You should now be able to build and compile code for the new Atmel/Microchip ATTiny series!
Blinky
main.c
#include <avr/io.h>
#include <avr/interrupt.h>
#define LED_PIN PIN3_bp // Adjust based on actual connected pin
void setup_timer(void) {
TCB0.CCMP = 50000; // Compare match value
TCB0.CTRLB = TCB_CNTMODE_INT_gc; // Periodic Interrupt Mode
TCB0.INTCTRL = TCB_CAPT_bm; // Enable interrupt on compare match
TCB0.CTRLA = TCB_ENABLE_bm | TCB_CLKSEL_CLKDIV2_gc; // Enable timer, clock source prescaler: CLK_PER/2
}
ISR(TCB0_INT_vect, ISR_BLOCK) {
PORTB.OUTTGL = (1 << LED_PIN); // Toggle LED state
TCB0.INTFLAGS = TCB_CAPT_bm; // Clear the interrupt flag
}
int main(void) {
// Set LED pin as output
PORTB.DIR |= (1 << LED_PIN);
setup_timer(); // Setup timer
sei(); // Enable global interrupts
while (1) {
// Main loop does nothing, just sleep
asm("sleep");
}
return 0; // Return statement added for clarity, though typically not reached
}
Makefile
Change the /dev/ttyUSB0 to be what it is on MacOS, e.g. /dev/tty.usbserial-A50285BI
.
MCU = attiny1614
F_CPU = 5000000 # 5 MHz, adjust as per your clock settings
CC = avr-gcc
OBJCOPY = avr-objcopy
CFLAGS = -mmcu=$(MCU) -DF_CPU=$(F_CPU) -Wall -Os
TARGET = main
SRCS = main.c
all: $(TARGET).hex
$(TARGET).hex: $(TARGET).elf
$(OBJCOPY) -O ihex -R .eeprom $< $@
$(TARGET).elf: $(SRCS)
$(CC) $(CFLAGS) -o $@ $^
clean:
rm -f $(TARGET).elf $(TARGET).hex
flash: $(TARGET).hex
avrdude -p $(MCU) -c serialupdi -P /dev/ttyUSB0 -U flash:w:$<:i
.PHONY: all clean flash
Outro
I’m building a new PCB, the BAUDI/O, and it uses two of the new attiny1614 chips. More details once it’s ready to release, but if you want more background on the new functions of these chips then https://github.com/SpenceKonde/megaTinyCore/blob/master/megaavr/extras/ATtiny_x14.md is a splended resource!