Code, better

1. Tasks

1.1. Task 1

  • Load the original Arduino .ino version of ShortSquawker onto an ATtiny85 and demonstrate it squawking as demonstrated during class time.

The ISP programmer interferes with the user pushbutton’s pin. Disconnect that pin from the programmer after programming or else the pin will be read as low constantly, as if the user is holding the button down all the time.

An alternate solution for development is to disable the state machine that handles the input button by commenting-out attiny_shortsquawker.ino line 487. This, of course, disables the user button feature.

1.2. Task 2

  • Port the code to C and demonstrate that it still operates the same.

Make a new folder to hold the C version, copy the .ino file into it, then change the file name such that it ends in``.c`; perhaps to main.c.

Figure out the process to compile this code and end up with a .hex file suitable for programming with avrdude using the tools included with the WinAVR package.

Modify the code as necessary to build with the following requirements:

  • Use avr-gcc option -std=c99 to use the 1999 C standard.[1]

  • Turn on all warnings, and trigger none with your code:

    • -Wall -Wextra -Werror

Along the way, create a Makefile to orchestrate those commands and dependencies for building the firmware. You should be able to begin with the .c file and Makefile (and perhaps other source files), run make upload from a command window, and have the system compile, link, and upload the .hex to your chip using avrdude.

1.3. Task 3

  • Rewrite function void debug_value(uint16_t) in assembly to ensure that each bit interval is exactly the same duration.

That function’s purpose is to barf out the value of a 16-bit number out of a pin similar to a UART signal. It first outputs a 0-1-0 pulse, then the variable’s bits lsb first, then another 0-1-0 pulse.

1.4. Task 4

Improve the code by e.g. making data types more consistent or other cleanup.

Fix the wave_triangle() function to actually create a triangle shape.

When the input is over-limit, turn the timer off instead of just pausing the output waveform generation.

Add a feature to power off the system when there has been no user activity after some interval.

2. Example avr-gcc project

Copy this main.c and one of the Makefile examples to a folder. Then use the WinAVR command window to run make to generate .hex and .lst file outputs.

main.c — Toggle a pin example
#include <avr/io.h>  // Register names
#include <util/delay_basic.h>  // for _delay_loop_2()

/*** Configuration constants ***/
#define LED_PIN PB3

int main(void)
{
    // <avr/sfr_defs.h> defines the macro _BV() as
    //      #define _BV(bit) (1 << (bit))
    // Use PB3 as the output
    DDRB |= _BV(LED_PIN);

    while (1) {
        // toggle pin and do it again
        PORTB ^= _BV(LED_PIN);

        // 65536 iterations, 4 clocks each + call overhead
        _delay_loop_2(0);
    }
}
Makefile — minimal example
# minimal Makefile
# no variables or other features except for command line continuations
.PHONY: default
default: main.hex main.lst


main.o: main.c
	avr-gcc -c -mmcu=attiny85 -std=gnu99 -g -Os -flto -Wall -Wextra \
	    -DF_CPU=8000000 main.c

main.elf: main.o
	avr-gcc -mmcu=attiny85 -g -Os -flto -Wall -Wextra \
	    -fuse-linker-plugin -Wl,--gc-sections -o main.elf main.o

main.hex: main.elf
	avr-objcopy -O ihex -R .eeprom main.elf main.hex

main.lst: main.elf
	avr-objdump --disassemble --source --line-numbers --demangle \
	    main.elf > main.lst

.PHONY: clean
clean:
	rm main.o main.elf main.hex main.lst
Makefile — alternate example with more features
MCU=attiny85

# Compiler options (for C language)
COMPILE_C_OPTS=
COMPILE_C_OPTS+=-c
COMPILE_C_OPTS+=-mmcu=$(MCU)
COMPILE_C_OPTS+=-std=gnu11
COMPILE_C_OPTS+=-g
COMPILE_C_OPTS+=-Os
COMPILE_C_OPTS+=-flto
COMPILE_C_OPTS+=-Wall -Wextra
COMPILE_C_OPTS+=-DF_CPU=8000000	  # *** must match the fuse settings!

# Linker options
LINK_OPTS=
LINK_OPTS+=-mmcu=$(MCU)
LINK_OPTS+=-g
LINK_OPTS+=-Os
LINK_OPTS+=-flto
LINK_OPTS+=-Wall -Wextra
LINK_OPTS+=-fuse-linker-plugin
LINK_OPTS+=-Wl,--gc-sections

# HEX output options
HEX_OPTS=
HEX_OPTS+=-O ihex
HEX_OPTS+=-R .eeprom

# Listing output options
LST_OPTS=
LST_OPTS+=--disassemble
LST_OPTS+=--source
LST_OPTS+=--line-numbers
LST_OPTS+=--demangle


# The first target is the default if no target was specified.
.PHONY: default
default: main.hex main.lst


# How to compile the .c and get the .o object file.
main.o: main.c
	avr-gcc $(COMPILE_C_OPTS) main.c

# Link the objects together to make a single ELF binary
# There may be more than one for some projects.
main.elf: main.o
	avr-gcc $(LINK_OPTS) -o main.elf main.o

# Generate HEX file for programming the chip
main.hex: main.elf
	avr-objcopy $(HEX_OPTS) main.elf main.hex

# Dump the listing file so we can inspect the generated assembly.
# No line continuations just because.
main.lst: main.elf
	avr-objdump $(LST_OPTS) main.elf > main.lst


.PHONY: clean
clean:
	@-rm main.o main.elf main.hex main.lst

3. References

The zip archive has been updated to …​valpo2.zip.

3.1. Makefile tips

See how make is interpreting the rules by adding the --debug=v option:

make --debug=v

When using backslash "\" for line continuation, the "\" MUST be the LAST character on that line. NO spaces or comments.

The continued lines also begin with a Tab character and then four spaces for a nice (optional) indent, like:

<Tab><sp><sp><sp><sp>command

The -g compile/link option adds extra information to the output object files. That is how avr-objdump gets the source code folded into the .lst output.

The -flto option is not available in our WinAVR Portable version of AVR-GCC.

The first target is the default if no target was specified. Build all output files, which are the "leaves" of the dependency graph. The .PHONY: target tells make that this is not a real file. This makes a difference if there ever is a file that is named default. Plus, it is good practice to tell the tool (and the next person) that you truly want this target’s rule to run every time.


1. C99 is required in some safety standards for embedded software